OpenGL - 在绑定不同的 FBO 时访问立方体贴图

OpenGL - Accessing a cubemap when a different FBO is bound

我在将我的阴影贴图实现从正向渲染切换到延迟渲染时遇到困难。我找到了问题所在,是立方体贴图未发送到着色器。我怀疑这是因为我的 "GBuffer" FBO 被绑定而不是立方体贴图 FBO。

如果 GLSL 可以在一次绘制调用中访问来自两个不同 FBO 的颜色附件,我想走那条路,这可能吗?

下面是正向渲染代码。

public void NormalPass(Shader shader)
{
    // Reset state
    GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
    GL.BindTexture(TextureTarget.Texture2D, 0);

    GL.UseProgram(shader.ID);
    GL.Viewport(0, 0, Width, Height);
    GL.CullFace(CullFaceMode.Back);
    GL.ClearColor(0.5f, 0.5f, 0.5f, 1f);

    // Uniforms
    Matrix4 viewMatrix = player.GetViewMatrix();
    Matrix4 projectionMatrix;
    Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)Width / (float)Height, 0.1f, 100.0f, out projectionMatrix);
    GL.UniformMatrix4(shader.viewMatrixLocation, false, ref viewMatrix); 
    GL.UniformMatrix4(shader.projectionMatrixLocation, false, ref projectionMatrix);
    GL.Uniform3(shader.lightPositionLocation, lightPos);

    GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);
    DrawScene(shader, false);                               // False = Not shadowpass
    GL.BindTexture(TextureTarget.TextureCubeMap, 0);
}

这里是失败的延迟渲染修改

public void Composite(Shader shader)
{
    //Set up FBO reading/writing
    GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
    GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, gBuffer.FBO);

    // Bind textures
    GL.ActiveTexture(TextureUnit.Texture2);
    GL.BindTexture(TextureTarget.Texture2D, gBuffer.positionTexture);
    GL.ActiveTexture(TextureUnit.Texture1);
    GL.BindTexture(TextureTarget.Texture2D, gBuffer.normalTexture);

    GL.UseProgram(shader.ID);
    GL.Disable(EnableCap.DepthTest);
    GL.Viewport(0, 0, Width, Height);
    GL.CullFace(CullFaceMode.Back);
    GL.ClearColor(0.5f, 0.5f, 0.5f, 1f);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    // Uniforms
    Matrix4 viewMatrix = player.GetViewMatrix();
    GL.UniformMatrix4(shader.viewMatrixLocation, false, ref viewMatrix);
    GL.Uniform3(shader.lightPositionLocation, lightPos);

    GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);
    Quad2D.drawScreenSizedQuad();   // Draw the combined lighting and diffuse to screen
    GL.BindTexture(TextureTarget.TextureCubeMap, 0);
}

很高兴根据要求提供更多信息。

If GLSL can access colour attachments from two different FBOs in a single draw call, I'd like to go that route, is this possible?

这个问题表明对正在发生的事情缺乏了解。 GLSL 访问 纹理,而不是 FBO 的颜色附件。

很明显,纹理可以用作颜色附件。但区别很重要,因为无论如何,GLSL 正在访问绑定的纹理,而不是 FBO 中的任何内容。

OpenGL 关于读取作为颜色附件附加到 FBO 的纹理的唯一规则是:只要这些纹理实际上没有附加到特定的帧缓冲区,它就会工作,该特定帧缓冲区是活动绘制帧缓冲区渲染命令。即便如此,OpenGL will only care if you break the feedback loop rules.

因此,您对读取帧缓冲区所做的绑定是毫无意义的。那不是使纹理可用于阅读或类似的东西;这不是读取帧缓冲区绑定点的目的。它仅用于 framebuffer reading commands and framebuffer blitting operations.

所以简单地将默认帧缓冲区绑定到 FramebufferTarget.Framebuffer,就像您在转发案例中所做的那样,就可以了。

你的主要问题是:

GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);

您没有使用 glActiveTexture 来指定要绑定该立方体贴图的纹理单元。这意味着它将使用您设置的最后一个纹理单元:TextureUnit.Texture1,并且您已经在那里绑定了一个 2D 纹理。从同一个纹理单元读取两种不同类型的两个纹理在 GLSL 中是非法的。

所以赔率很好,这不是你的意思。 总是 在任何 glBindTexture 调用之前使用 glActiveTexture。除非你使用 glBindTextures from GL 4.4/ARB_multibind or glBindTextureUnit from GL 4.5/ARB_DSA.