OpenGL - 清除立方体贴图阵列中的单个立方体贴图

时间:2017-08-27 22:16:10

标签: c# opengl opentk

我需要清除立方体贴图数组中的特定立方体贴图图层。我认为这可以通过glClearTexSubImage实现,但我没有任何运气。

enter image description here

为了给出上下文,我是阴影贴图。立方体贴图阵列包含8个立方体贴图图层,每个图层包含8个光源之一的场景/深度信息。

首先,使用

清除整个立方体贴图数组
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 

接下来,从8个光源的角度将场景渲染到8个立方体贴图中。

for (int j = 0; j < lights.Count; j++)
{
    // Create the light's view matrices
    List<Matrix4> shadowTransforms = new List<Matrix4>();
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0)));
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0)));
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, 1)));
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1)));
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0)));
    shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0)));

    // Send uniforms to the shader
    for (int i = 0; i < 6; i++)
    {
        Matrix4 shadowTransform = shadowTransforms[i];
        GL.UniformMatrix4(shader.getUniformID("shadowTransforms[" + i + "]"), false, ref shadowTransform);
    }
    GL.Uniform1(shader.getUniformID("lightID"), j);

    // Draw Scene
    DrawSceneInstanced(shader);
}

这一切都很好,每帧更新每个阴影贴图。但是,为了优化,我希望每帧只更新一个阴影贴图,这意味着我需要单独清除单个立方体贴图图层。

这是怎么做到的?

FBO / Cubemap数组创建和附件

public CubeMapArray()
{
    // Create the FBO
    GL.GenFramebuffers(1, out FBO_handle);

    // Create and bind the CubeMap array
    GL.GenTextures(1, out cubeMapTextureHandle);
    GL.BindTexture(TextureTarget.TextureCubeMapArray, cubeMapTextureHandle);

    // Allocate storage space
    GL.TexImage3D(TextureTarget.TextureCubeMapArray, 0, PixelInternalFormat.Rg16, size, size, layers * 6, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);

    // Set the suitable texture parameters
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureBaseLevel, 0);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMaxLevel, 0);

    // Create and bind the CubeMap depth array
    GL.GenTextures(1, out cubeMapDepthHandle);
    GL.BindTexture(TextureTarget.TextureCubeMapArray, cubeMapDepthHandle);

    // Allocate storage space
    GL.TexImage3D(TextureTarget.TextureCubeMapArray, 0, PixelInternalFormat.DepthComponent, size, size, layers * 6, 0, PixelFormat.DepthComponent, PixelType.UnsignedByte, IntPtr.Zero);

    // Set the suitable texture parameters
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureBaseLevel, 0);
    GL.TexParameter(TextureTarget.TextureCubeMapArray, TextureParameterName.TextureMaxLevel, 0);

    // Attach cubemap texture as the FBO's color buffer
    GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO_handle);
    GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, cubeMapTextureHandle, 0);
    GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, cubeMapDepthHandle, 0);

    // Error check
    var errorcheck = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
    Console.WriteLine("CUBEMAP ARRAY: " + errorcheck);

    // Bind default framebuffer
    GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}

1 个答案:

答案 0 :(得分:2)

使用texture array to the FBO附加glFramebufferTextureLayer的特定图层,然后使用glClear()清除附件。

解决方案尝试:

GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowMapArray.FBO_handle);

FramebufferTarget target = FramebufferTarget.Framebuffer;
FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0;
int level = 0;
int layer = currentShadowMap;
int texture = shadowMapArray.FBO_handle;

GL.FramebufferTextureLayer(target, attachment, texture, level, layer);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);