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

本文关键字:立方 访问 立方体 体贴 FBO 绑定 OpenGL | 更新日期: 2023-09-27 17:59:19

我在将阴影映射实现从前向渲染切换到延迟渲染时遇到困难。我已经找到了问题所在,它是立方体贴图未发送到着色器。我怀疑这是因为我的"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);
}

很乐意应要求提供更多信息。

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

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

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

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

OpenGL 关于读取作为颜色附件附加到 FBO 的纹理的唯一规则是:只要这些纹理实际上没有附加到渲染命令期间作为活动绘制帧缓冲区的特定帧缓冲区,它就会起作用。即便如此,OpenGL也只会关心你是否打破了反馈循环规则。

因此,对读取帧缓冲区的绑定是没有意义的。这不是使纹理可供阅读或诸如此类;这不是读取帧缓冲绑定点的用途。它仅用于帧缓冲读取命令和帧缓冲块操作。

因此,只需将默认帧缓冲绑定到 FramebufferTarget.Framebuffer ,就像您在前向情况下所做的那样,就可以了。

你的主要问题是这样的:

GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);

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

所以赔率很高,这不是你的意思。在任何glBindTexture调用之前,请务必使用glActiveTexture。除非您使用的是 GL 4.4/ARB_multibind 中的glBindTextures或 GL 4.5/ARB_DSA 中的glBindTextureUnit