c# - OpenGL - 单 channel 立方体贴图不产生输出

标签 c# opengl glsl opentk

enter image description here

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

作为一种优化,我尝试使用几何着色器升级到单 channel 方法,但很难从着色器获得任何输出。

我的问题是在绑定(bind)立方体贴图纹理时开始的。使用多 channel 时,我只需一次绑定(bind) 6 个 FBO 中的 1 个,但是使用单 channel 时,我需要一次绑定(bind)所有 6 个立方体贴图面,但我没有相应的句柄。在这些情况下,文档建议使用包含所有 6 个面的 FrameBufferTexture 创建单个 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# 包装器的人来说,我认为如果我还提供有效的多遍代码,可能会有所帮助。

多次通过(工作正常)

固定基地台创建

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

如有任何见解,我们将不胜感激,谢谢!

最佳答案

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

shadowTransforms[shadowTransforms] 需要是 shadowTransforms[face]

uniform mat4shadowTransforms[6] 需要是uniform mat4shadowTransforms[]

enter image description here

这对我来说标志着一个巨大的突破。 60 fps 的多个阴影转换点光源。感谢一路以来帮助过我的所有人。

关于c# - OpenGL - 单 channel 立方体贴图不产生输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40222125/

相关文章:

C#给字符串变量添加函数或变量的方法

c# - 将右键单击菜单项添加到图片框

c# - 我可以传递查询字符串之类的 Web 方法参数吗?

c++ - 适用于 OSX 和 Linux 的 OpenGL 头文件

c++ - 控制像素着色器的键盘输入

c++ - GLSL:将字符数组传递给片段着色器

C# - 从子类中获取属性值

opengl - 缩放、平移和旋转如何工作?

用于 opengl 的 C++ nuget 包

java - OpenGL ATI 与 NVIDIA GLSL 问题