2011-06-20 156 views
2

我有一個頂點/片段着色器,它繪製了一個基於紋理執行許多計算的矩形。 (它混合像素,修改它們等)。事情是,每個矩形和它包含的像素都不會改變。我只移動整個矩形並縮放它們。優化OpenGL片段着色器

有沒有什麼辦法來優化片段着色器,因爲矩形並不需要重新計算?

回答

5

所以,如果我正確地理解你,你計算一次這些矩形,然後想重用它們?這種任務是通過渲染紋理,然後使用生成的紋理來解決的。

渲染到紋理最容易通過幀緩衝區對象完成。

編輯:使用FBO一個簡單的例子來渲染到紋理

// test_fbo_teapot.cpp 

#include <GL/glew.h> // Uses GLEW for extension loading 
#include <GL/glut.h> // Uses GLUT as framework 
        // Check those are on your system for compilation 
        // and if not please install them. 

#include <cmath> 
#include <iostream> 

using namespace std; 

namespace render 
{ 
    int width, height; 
    float aspect; 

    void init(); 
    void reshape(int width, int height); 
    void display(); 

    int const fbo_width = 512; 
    int const fbo_height = 512; 

    GLuint fb, color, depth; 
}; 

void idle(); 

int main(int argc, char *argv[]) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 

    glutCreateWindow("FBO test"); 
    glutDisplayFunc(render::display); 
    glutReshapeFunc(render::reshape); 
    glutIdleFunc(idle); 

    glewInit(); 

    render::init(); 
    glutMainLoop(); 

    return 0; 
} 

void idle() 
{ 
    glutPostRedisplay(); 
} 

void CHECK_FRAMEBUFFER_STATUS() 
{               
    GLenum status; 
    status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 
    switch(status) { 
    case GL_FRAMEBUFFER_COMPLETE: 
     break; 

    case GL_FRAMEBUFFER_UNSUPPORTED: 
    /* choose different formats */ 
     break; 

    default: 
     /* programming error; will fail on all hardware */ 
     throw "Framebuffer Error"; 
    } 
} 

namespace render 
{ 
    float const light_dir[]={1,1,1,0}; 
    float const light_color[]={1,0.95,0.9,1}; 

    void init() 
    { 
     glGenFramebuffers(1, &fb); 
     glGenTextures(1, &color); 
     glGenRenderbuffers(1, &depth); 

     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb); 

     glBindTexture(GL_TEXTURE_2D, color); 
     glTexImage2D( GL_TEXTURE_2D, 
       0, 
       GL_RGBA, 
       fbo_width, fbo_height, 
       0, 
       GL_RGBA, 
       GL_UNSIGNED_BYTE, 
       NULL); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); 

     glBindRenderbuffer(GL_RENDERBUFFER, depth); 
     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbo_width, fbo_height); 
     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); 

     CHECK_FRAMEBUFFER_STATUS(); 
    } 

    void reshape(int width, int height) 
    { 
     render::width=width; 
     render::height=height; 
     aspect=float(width)/float(height); 
     glutPostRedisplay(); 
    } 

    void prepare() 
    { 
     static float a=0, b=0, c=0; 

     glBindTexture(GL_TEXTURE_2D, 0); 
     glEnable(GL_TEXTURE_2D); 
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb); 

     glViewport(0,0,fbo_width, fbo_height); 

     glClearColor(1,1,1,0); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluPerspective(45, 1, 1, 10); 

     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 

     glEnable(GL_LIGHT0); 
     glEnable(GL_LIGHTING); 

     glEnable(GL_DEPTH_TEST); 
     glDisable(GL_CULL_FACE); 

     glLightfv(GL_LIGHT0, GL_POSITION, light_dir); 
     glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color); 

     glTranslatef(0,0,-5); 

     glRotatef(a, 1, 0, 0); 
     glRotatef(b, 0, 1, 0); 
     glRotatef(c, 0, 0, 1); 

     glutSolidTeapot(0.75); 

     a=fmod(a+0.1, 360.); 
     b=fmod(b+0.5, 360.); 
     c=fmod(c+0.25, 360.); 
    } 

    void intermediary() 
    { 
    } 

    void final() 
    { 
     static float a=0, b=0, c=0; 

     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 

     glViewport(0,0, width, height); 

     glClearColor(1,1,1,1); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluPerspective(45, aspect, 1, 10); 

     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     glTranslatef(0,0,-5); 

     glRotatef(b, 0, 1, 0); 

     b=fmod(b+0.5, 360.); 

     glEnable(GL_TEXTURE_2D); 
     glBindTexture(GL_TEXTURE_2D, color); 

     glEnable(GL_DEPTH_TEST); 
     glEnable(GL_CULL_FACE); 

     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

     glDisable(GL_LIGHTING); 

     float cube[][5]= 
     { 
      {-1, -1, -1, 0, 0}, 
      { 1, -1, -1, 1, 0}, 
      { 1, 1, -1, 1, 1}, 
      {-1, 1, -1, 0, 1}, 

      {-1, -1, 1, -1, 0}, 
      { 1, -1, 1, 0, 0}, 
      { 1, 1, 1, 0, 1}, 
      {-1, 1, 1, -1, 1}, 
     }; 
     unsigned int faces[]= 
     { 
      0, 1, 2, 3, 
      1, 5, 6, 2, 
      5, 4, 7, 6, 
      4, 0, 3, 7, 
      3, 2, 6, 7, 
      4, 5, 1, 0 
     }; 

     glEnableClientState(GL_VERTEX_ARRAY); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

     glVertexPointer(3, GL_FLOAT, 5*sizeof(float), &cube[0][0]); 
     glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), &cube[0][3]); 

     glCullFace(GL_BACK); 
     glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces); 

     glCullFace(GL_FRONT); 
     glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces); 

     glDisableClientState(GL_VERTEX_ARRAY); 
     glDisableClientState(GL_TEXTURE_COORD_ARRAY); 

    } 

    void display() 
    { 
     prepare(); 
     intermediary(); 
     final(); 

     glutSwapBuffers(); 
    } 
}; 
+0

你能提供一個鏈接到一個簡單的例子?東西可能像「如果還沒有繪製,繪製和寫入紋理,否則,繪製生成的紋理到屏幕」 –

+0

@AdedeepGrewal:你也可以使用:[glCopyTexImage2D](http://www.opengl.org/sdk/docs/人/ XHTML/glCopyTexImage2D.xml)。它可能會更慢,但稍微簡單一些,並且可以在較舊的硬件上工作。 –