2011-06-20 9 views
2

私は、テクスチャに基づいて多くの計算を実行する矩形を描画する頂点/フラグメントシェーダを持っています。 (それはピクセルをブレンドし、それらを変更するなど)。つまり、各矩形とそれに含まれるピクセルは変更されません。私は矩形全体を動かし、ズームするだけです。OpenGLフラグメントシェーダの最適化

矩形を実際に再計算する必要はないので、フラグメントシェーダを最適化する方法はありますか?

答えて

5

私はあなたを正しく理解していれば、それらの四角形を一度計算して再利用したいのですか?この種のタスクは、テクスチャにレンダリングし、生成されたテクスチャをさらに使用することで解決されます。

テクスチャへのレンダリングは、Framebufferオブジェクトを使用すると最も簡単です。

EDIT:テクスチャ

// 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

にレンダリングするFBOを使用するための簡単な例では、あなたは簡単な例へのリンクを提供することができますか? "描画されていない場合は、描画してテクスチャに書き出し、それ以外の場合は、生成したテクスチャを描画します" –

+0

@AmandeepGrewal:[glCopyTexImage2D](http://www.opengl.org/sdk/docs/) man/xhtml/glCopyTexImage2D.xml)。それは遅くなるかもしれませんが、少し簡単で、古いハードウェアで動作します。 –