【问题标题】:OpenGL - How to create and bind cubemap arrays?OpenGL - 如何创建和绑定立方体贴图数组?
【发布时间】:2016-11-08 00:48:26
【问题描述】:

超过纹理单元限制后,我决定使用立方体贴图数组纹理。

出于测试目的,我将立方体贴图的内容渲染为天空盒。问题是,当我绑定立方体贴图数组时,OpenGL 会忽略它,而是使用之前绑定的立方体贴图来渲染天空盒。

GL.BindTexture(TextureTarget.TextureCubeMap, shadowMaps[5].cubeMapTexture);
GL.BindTexture(TextureTarget.TextureCubeMapArray, shadowMapArray.cubeMapHandle); // Ignored

我假设这是错误创建的立方体贴图数组的默认行为。据我所知,我所做的一切都是正确的:Framebuffer complete

那么,创建和绑定立方体贴图数组的正确方法是什么?

public class CubeMapArray
{
    public static int size = 512;
    public static int layers = 8; // number of cube maps in array

    public int FBO_handle;
    public int cubeMapHandle;
    public int cubeMapDepthHandle;

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

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

        // 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.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);

        // 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, cubeMapHandle, 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);
    }
}

}

着色器非常简单,令人惊讶的是,它可以绑定常规立方体贴图。

顶点

#version 330

in vec3 texCoord;
out vec4 fragColor;
uniform samplerCube cubeMapArray[16];

void main (void) 
{
    fragColor = texture(cubeMapArray[0], texCoord);
}

片段

#version 330

uniform mat4 modelMatrix; 
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

in vec3 in_position;
out vec3 texCoord;

void main() 
{
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
    texCoord = in_position;
}

【问题讨论】:

    标签: c# opengl opentk


    【解决方案1】:

    您需要在着色器代码中使用相应的采样器类型。立方体贴图数组在 OpenGL 4.0 及更高版本中可用,因此您还需要将 GLSL 版本增加到 400 或更高版本。

    着色器代码将看起来像这样:

    #version 400
    ...
    uniform samplerCubeArray cubeMapArray;
    ...
    fragColor = texture(cubeMapArray, vec4(texCoord, 0));
    

    注意,用于采样的数组层被指定为纹理坐标的第 4 个分量。

    【讨论】:

      【解决方案2】:
      uniform samplerCube cubeMapArray[16];
      

      好的,array of samplersarray texture 之间存在差异。您在这里拥有的是一组采样器。您在 OpenGL 中创建的是一个数组纹理。

      数组纹理是来自它们的非数组对应物的separate texture types。立方体贴图阵列纹理不是立方体贴图纹理;它是一个立方体贴图数组纹理。就像二维数组纹理不是二维纹理一样。

      所以如果你想要一个数组纹理,你必须使用适当的采样器类型。由于它是立方体贴图数组纹理,因此您使用samplerCubeArray。而且你必须摆脱数组下标。

      从立方体贴图阵列纹理中采样时,第四个组件是您要从中采样的阵列层:

      fragColor = texture(cubeMapArray, vec4(texCoord, 0));
      

      另外,如果您打算使用立方体贴图数组纹理,请不要绑定非数组立方体贴图纹理根本。这并不违法;它只是令人困惑,最好避免。

      【讨论】:

      • Reto 先回答了,所以给了他,但再次感谢。我正在绑定非数组立方体贴图纹理,以查看前面的立方体贴图数组纹理是否被绑定。
      猜你喜欢
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      相关资源
      最近更新 更多