opengl透明网格
opengl transparent mesh
我正在使用 GLSL 渲染一个立方体,使用纯白色材质和一个网格作为参考地板。出于某种原因,有时(大约 10 次中有 1 次)立方体呈现大约 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);
}
我可能在这里做错了什么?
看来肯定是着色器了。
您的设置不会为您提供功能深度缓冲区。问题在于此调用:
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 之间。指定此范围之外的值不是错误。这些值被限定,如规范中所定义:
The parameters n and f are clamped to the range [0,1], as are all arguments of type clampd or clampf.
夹紧第二个参数 100
后,您的调用相当于:
glDepthRange(1.0, 1.0);
这意味着所有内容都映射到深度值 1.0,这几乎就像根本没有深度缓冲区一样。
除非您有充分的理由选择不同的值,否则您根本不需要调用 glDepthRange()
。默认值适用于最常见的用例。
根据您使用的值,您可能期望它们是 world/eye 坐标中的深度范围。但该范围由投影变换的 near 和 far 参数定义,负责将 [near, far] 范围映射到 [-1, 1] NDC 范围。我们在这里使用 glDepthRange()
参数查看的内容稍后会在管道中发生。
我正在使用 GLSL 渲染一个立方体,使用纯白色材质和一个网格作为参考地板。出于某种原因,有时(大约 10 次中有 1 次)立方体呈现大约 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);
}
我可能在这里做错了什么? 看来肯定是着色器了。
您的设置不会为您提供功能深度缓冲区。问题在于此调用:
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 之间。指定此范围之外的值不是错误。这些值被限定,如规范中所定义:
The parameters n and f are clamped to the range [0,1], as are all arguments of type clampd or clampf.
夹紧第二个参数 100
后,您的调用相当于:
glDepthRange(1.0, 1.0);
这意味着所有内容都映射到深度值 1.0,这几乎就像根本没有深度缓冲区一样。
除非您有充分的理由选择不同的值,否则您根本不需要调用 glDepthRange()
。默认值适用于最常见的用例。
根据您使用的值,您可能期望它们是 world/eye 坐标中的深度范围。但该范围由投影变换的 near 和 far 参数定义,负责将 [near, far] 范围映射到 [-1, 1] NDC 范围。我们在这里使用 glDepthRange()
参数查看的内容稍后会在管道中发生。