【问题标题】:How to use shader for drawing FBO lwjgl如何使用着色器绘制 FBO lwjgl
【发布时间】:2015-09-15 23:00:50
【问题描述】:

我正在制作一个 2D 游戏,我想制作一个光罩。到目前为止,我制作了一个帧缓冲区,我在其中保存了我的蒙版,但我无法在其上应用着色器。当我不使用着色器时,光照贴图被正确绘制(没有场景,所以对于这段代码,我绘制了一个带有一个白色矩形的黑屏)但是当我尝试将它与场景混合时它只是绘制黑屏。这就是我绘制帧缓冲区并应用着色器的方式。

//draw scene

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_frameBufferObject);//enable frame buffer
            glPushAttrib(GL_VIEWPORT_BIT);
            glViewport(0, 0, 1920, 1080);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  

            //fill with black
            glColor3f(0.0f, 0.0f, 0.0f);
            glBegin(GL_QUADS);
                glVertex2f(0, 0);
                glVertex2f(1920, 0);
                glVertex2f(1920, 1080);
                glVertex2f(0, 1080);
            glEnd();

            //example light, a rectangle trough which i should see the scene
            glColor3f(1.0f,1.0f,1.0f);
            glBegin(GL_QUADS);
                glVertex2f(100, 100);
                glVertex2f(300, 100);
                glVertex2f(300, 300);
                glVertex2f(100, 300);
            glEnd();

            //Deactivate the framebuffer object
            glPopAttrib();
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

            glUseProgram(shaderProgram3);//this is the shader program
            //Render the framebuffer object to the screen

            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, m_frameBufferTexture);
                glBegin(GL_QUADS);
                    glTexCoord2f(0f, 0f);
                    glVertex2f(0, 0);
                    glTexCoord2f(1f, 0f);
                    glVertex2f(1920, 0); 
                    glTexCoord2f(1f, 1f);
                    glVertex2f(1920, 1080);
                    glTexCoord2f(0f, 1f);
                    glVertex2f(0, 1080);
                glEnd();
            glDisable(GL_TEXTURE_2D);
            glUseProgram(0);

    Display.update();
    Display.sync(60);

这是着色器

uniform sampler2D backbuffer;

void main( void ) {    
    vec2 position;
    position.x = gl_FragCoord.x/1920;
    position.y = gl_FragCoord.y/1080;
    vec4 color = texture2D(backbuffer, position);
    gl_FragColor.x -=1-color.x;
    gl_FragColor.y -=1-color.y;
    gl_FragColor.z -=1-color.z;
}

【问题讨论】:

    标签: shader lwjgl mask fragment-shader


    【解决方案1】:

    当您在着色器中执行以下操作时:

    gl_FragColor.x -=1-color.x;
    gl_FragColor.y -=1-color.y;
    gl_FragColor.z -=1-color.z;
    

    您假设当您输入main() 时,gl_FragColor 包含当前帧缓冲区的当前像素颜色。

    但事实并非如此! gl_FragColor 是您需要在着色器中设置的颜色,在您设置它之前,它的值将是未定义的(在您的情况下它似乎设置为黑色),它永远不会包含“当前帧缓冲区颜色”(检查规范,这适用于所有版本的 OpenGL / OpenGLES 没有例外)。

    要获得当前的帧缓冲区颜色,您需要为移动 GPU 使用像 EXT_shader_framebuffer_fetch 这样的 OpenGL 扩展,遗憾的是对于桌面 GPU 不存在这种扩展(但您可以在 OpenGL4 中使用 Image Load Store)。

    但在这里我离题了,因为我认为您不需要任何这些扩展,您需要的只是在渲染蒙版时启用 blending 并正确配置混合公式以达到您的效果。

    【讨论】:

    • 感谢您的回答,但至少我可以访问纹理当前像素,因为它们应该混合多个灯光。
    • 我不明白你所说的“纹理”是什么?你是在谈论你的场景像素还是光罩像素或其他东西?同样在考虑多盏灯之前,让我们首先为一盏灯制作这项工作......
    • 如果你想在你的“光帧缓冲区”中有多个灯光,那么这是相同的过程:在每一帧,你用黑色清除帧缓冲区,然后在里面绘制 light1,然后你启用 opengl 混合并在里面绘制 light2,然后是 light3 ...最后你有一个帧缓冲区,其中包含你在场景中绘制的所有灯光,再次使用 opengl 混合。
    • 再次感谢最后一个问题。我现在画了它,但我很难考虑混合函数参数,以便当光罩全白时,它应该渲染场景颜色,当光罩全黑时,它应该渲染光罩。
    • 编辑我用 glBlendFunc(GL_DST_COLOR,GL_ZERO);
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多