OpenGL - 单通道立方体贴图不产生输出

时间:2016-10-24 15:28:06

标签: c# opengl glsl opentk

enter image description here

我编写了一个粗略的阴影贴图实现,它使用6个不同的视图矩阵渲染场景6次,以创建立方体贴图。

作为优化,我正在尝试使用几何着色器升级到单通道方法,但努力从我的着色器获取任何输出。

绑定立方体贴图纹理时我的问题就开始了。使用多次传递,我一次只能绑定6个FBO中的一个,但是对于单次传递,我需要同时绑定所有6个立方体贴图面,而我没有这样的句柄。在这些情况下,文档建议创建一个包含所有6个面的FrameBufferTexture的FBO。我这样做了吗?

或者,问题可以在几何着色器中进行路由,但是因为我没有得到任何输出,所以在那里进行调试非常困难。

单一通过(无输出)

Fbo创作

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

// Create and bind the cubemap Texture
GL.GenTextures(1, out cubeMapTexture);
GL.BindTexture(TextureTarget.TextureCubeMap, cubeMapTexture);

// Generate each of the single cubemap faces as 2D texture
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);

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

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

几何着色器

#version 330

layout(triangles) in;
layout (triangle_strip, max_vertices=18) out;

uniform mat4 projectionMatrix;
uniform mat4 shadowTransforms[6];
out vec4 frag_position;

void main()
{   
    for(int face = 0; face < 6; face++)
    {
        gl_Layer = face;
        for(int i=0; i<3; i++)
        {
            frag_position = shadowTransforms[face] * gl_in[i].gl_Position;
            gl_Position = projectionMatrix * shadowTransforms[shadowTransforms] * gl_in[i].gl_Position;

            EmitVertex();
        }
        EndPrimitive();
    }
}

渲染

for (int j = 0; j < lights.Count; j++)
{
    // GL setup
    GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowBuffers[j].FBO_handle);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    Matrix4 viewMatrix = Matrix4.Identity;

    // 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 them to the shader
    for (int i = 0; i < 6; ++i)
    {
        Matrix4 shadowTransform = shadowTransforms[i];
        GL.UniformMatrix4(shader.getUniformID("shadowTransforms[" + i + "]"), false, ref shadowTransform);
    }

    // Draw Scene
    for (int r = 0; r < renderables.Count; r++)
        renderables[r].draw(shader);
}

我为大量的代码转储道歉,FBO有点冗长,我相信你知道。对于那些不熟悉OpenTK c#包装器的人,我认为如果我还提供有效的多通道代码可能会有所帮助。

MULTI PASS(正常工作)

Fbo创作

// Create cubemap texture
GL.GenTextures(1, out cubeTex);
GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMaxLevel, 0);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);

// Create cubemap FBOs
GL.GenFramebuffers(6, cubeFBOs);
for (int i = 0; i < 6; i++) 
{
    GL.BindFramebuffer(FramebufferTarget.Framebuffer, cubeFBOs[i]);
    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.TextureCubeMapPositiveX + i, cubeTex, 0);
}

几何着色器

#version 330

layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;

uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
out vec4 frag_position;

void main()
{
    for(int i=0; i<3; i++)
    {
        frag_position = viewMatrix * gl_in[i].gl_Position;
        gl_Position = projectionMatrix * viewMatrix * gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

渲染

for (int j = 0; j < lights.Count; j++)
{
    for (int i = 0; i < 6; ++i)
    {
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowBuffers[j].cubeFBOs[i]);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        Matrix4 viewMatrix = Matrix4.Identity;

        if (i == 0) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0));
        if (i == 1) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0));
        if (i == 2) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, -1));
        if (i == 3) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1));
        if (i == 4) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0));
        if (i == 5) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0));
        GL.UniformMatrix4(shader.getUniformID("viewMatrix"), false, ref viewMatrix);

        // Draw Scene
        for (int r = 0; r < renderables.Count; r++)
            renderables[r].draw(shader);
    }
}

片段着色器

#version 330

precision lowp float;

in vec4 frag_position;

layout (location = 0) out vec4 outColor;

void main() {
    float depth = length( vec3(frag_position) ) / 20;

    float moment1 = depth;
    float moment2 = depth * depth;

    float dx = dFdx(depth);
    float dy = dFdy(depth);
    moment2 += 0.25*(dx*dx+dy*dy);

    outColor = vec4( moment1, moment2, 0.0, 0.0);
}

非常感谢任何见解,谢谢!

1 个答案:

答案 0 :(得分:2)

令人尴尬的是,原因是几何着色器中的拼写错误组合。

shadowTransforms[shadowTransforms]需要shadowTransforms[face]

uniform mat4 shadowTransforms[6]需要uniform mat4 shadowTransforms[]

enter image description here

这标志着我的巨大突破。多个阴影投射点灯以60 fps点亮。感谢所有帮助过我的人。