opengl透明网格

时间:2015-01-27 11:52:52

标签: c++ opengl glsl

使用GLSL渲染立方体,使用纯白色材质,使用网格作为参考地板。出于某种原因,有时(约10次),立方体的透明度约为50%。我最初认为它是深度缓冲区问题(例如禁用深度缓冲区),但我找不到任何关于它的信息。代码中只有一个位置触及深度缓冲区,并且它正在初始化它。 我甚至强迫GLSL着色器为Alpha设置固定值1,但仍然没有。

以下是我用来说明问题的截图:

以下是着色器代码:

Lighting.vs

#version 300 es

in vec3 VertexPosition;
uniform mat4 MVP;
in vec2 TexCoord;
out vec2 TexCoord0;

void main()
    {
    gl_Position = MVP * vec4(VertexPosition, 1.0);
    TexCoord0 = TexCoord;
    }

Lighting.fs

#version 300 es

precision lowp float;
in vec2 TexCoord0;
out vec4 FragColor;
uniform sampler2D TextureSampler;

uniform struct
    {
    bool Textured;
    bool Litable;
    }Flags;

uniform struct
    {
    vec4 Diffuse;
    }Material;

uniform struct
    {
    vec3 Color;
    float Intensity;
    }AmbientLight;

vec4 ApplyTexturing ( vec4 Input )
    {
    Input *= texture(TextureSampler, TexCoord0);
    return Input;
    }

vec4 ApplyLighting ( vec4 Input )
    {
    Input *= vec4(AmbientLight.Color * AmbientLight.Intensity, 1.0f );
    return Input;
    }

void main()
    {
    vec4 TempFragColor = vec4 ( Material.Diffuse.xyz, 1.0f );
    if ( Flags.Textured )
    TempFragColor = ApplyTexturing( TempFragColor );

    if ( Flags.Litable )
    TempFragColor = ApplyLighting ( TempFragColor );

    FragColor = vec4(TempFragColor.xyz, 1.0f);
    }

这是代码中唯一接触深度缓冲区的地方:

glEnable ( GL_CULL_FACE );
glCullFace ( GL_BACK );
glFrontFace ( GL_CCW );
glEnable ( GL_DEPTH_TEST );
glDepthMask ( GL_TRUE );
glDepthFunc ( GL_LEQUAL );
glDepthRange ( 1, 100 );

现在,正如我写的那样,我想知道我是否应该使用glClearDepth()来设置默认值?我假设驱动程序会使用一个不错的默认值,所以我没有指定。

编辑:好的,所以我改变了代码以使用glClearDepth。没变。但这绝对看起来像透明度问题。看看这个镜头,带有纹理立方体。

bool CGLWindow::StartFrame ( void )
{
    glfwMakeContextCurrent ( MyGLFWWindow );
    glfwPollEvents();
    glEnable ( GL_CULL_FACE );
    glCullFace ( GL_BACK );
    glFrontFace ( GL_CCW );
    glEnable ( GL_DEPTH_TEST );
    glDepthMask ( GL_TRUE );
    glDepthFunc ( GL_LEQUAL );
    glDepthRange ( 1, 100 );
    glClearColor ( 0, 0, 0, 1.0f );
    glClearDepth ( 1.0f );

    Clear();
    glfwGetCursorPos ( MyGLFWWindow, & ( MouseCursor.CursorPos.X ), & ( MouseCursor.CursorPos.Y ) );
    return glfwWindowShouldClose ( MyGLFWWindow );
}

bool CGLWindow::Clear ( void )
{
    glViewport ( 0, 0, Size.X, Size.Y );
    glScissor ( 0, 0, Size.X, Size.Y );
    glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    return glCheckError();
}

编辑: 好的,有些突破。 我切换到一个简单的片段着色器:

#version 300 es
precision lowp float;

out vec4 FragColor;
in vec4 Color;

void main()
    {
    FragColor.r = FragColor.g = FragColor.b = FragColor.a = 1.0f;
    }

这不是确定性的,但就像我说的,每隔一段时间,我就会得到一个透明的立方体。现在,它停止了这样做。现在一切都好。

所以,我开始减少片段着色器。这是我得到的最小值,因为它没有透明的立方体。

#version 300 es

precision lowp float;
in vec2 TexCoord0;
out vec4 FragColor;
uniform sampler2D TextureSampler;

uniform struct
    {
    vec4 Diffuse;
    }Material;

void main()
    {
    vec4 TempFragColor = vec4 ( Material.Diffuse.xyz, 1.0f );

    FragColor = vec4(TempFragColor.xyz, 1.0f);
    }

我可能在这里做错了什么? 它似乎绝对是着色器。

1 个答案:

答案 0 :(得分:4)

您的设置不会为您提供功能深度缓冲区。问题在于这个电话:

glDepthRange ( 1, 100 );

深度缓冲区的范围为0.0到1.0。这些值确定从NDC(标准化设备坐标)到深度缓冲区范围的映射。默认值对应于:

glDepthRange(0.0, 1.0);

表示NDC中的深度范围(从-1.0到1.0)映射到整个可用深度缓冲区范围。 glDepthRange()只能减少 NDC范围映射到的深度值范围。您无法将深度缓冲区的范围扩展到其默认的完整范围之外。

因此,glDepthRange()的两个参数都需要介于0.0和1.0之间。指定此范围之外的值不是错误。这些值被限制,如规范中所定义:

  

参数n和f被钳制到[0,1]范围,夹钳或夹钳类型的所有参数也是如此。

第二个参数100被限制,您的通话相当于:

glDepthRange(1.0, 1.0);

这意味着所有内容都映射到深度值1.0,这就像没有深度缓冲区一样。

除非您有充分的理由要求不同的价值观,否则您很少需要致电glDepthRange()。默认值适用于最常见的用例。

根据您使用的值,您可能希望它们是世界/眼睛坐标的深度范围。但是该范围由投影变换的近和远参数定义,其涉及将[近,远]范围映射到[-1,1] NDC范围。我们在这里使用glDepthRange()参数查看的内容会在管道中稍后发生。