【问题标题】:Optimize OpenGL Fragment Shader优化 OpenGL 片段着色器
【发布时间】:2011-09-19 00:26:35
【问题描述】:

我有一个顶点/片段着色器,它绘制一个基于纹理执行许多计算的矩形。 (它混合像素,修改它们等)。问题是每个矩形及其包含的像素都不会改变。我只移动整个矩形并缩放它们。

由于矩形不需要重新计算,有什么方法可以优化片段着色器?

【问题讨论】:

    标签: opengl shader fragment-shader


    【解决方案1】:

    那么,如果我理解正确的话,您会计算一次这些矩形然后想重复使用它们吗?此类任务通过渲染到纹理然后进一步使用生成的纹理来解决。

    渲染到纹理最容易通过帧缓冲区对象完成。

    编辑:使用 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();
        }
    };
    

    【讨论】:

    • 你能提供一个简单例子的链接吗?可能类似于“如果尚未绘制,则绘制并写入纹理,否则,将生成的纹理绘制到屏幕”
    • @AmandeepGrewal:您也可以使用:glCopyTexImage2D。它可能会更慢,但更简单一些,并且可以在旧硬件上运行。
    猜你喜欢
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    相关资源
    最近更新 更多