【问题标题】:draw the depth value in opengl using shaders使用着色器在opengl中绘制深度值
【发布时间】:2011-06-20 08:57:19
【问题描述】:

我想在片段着色器中绘制深度缓冲区,我这样做:

顶点着色器:

varying vec4 position_;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position_ = gl_ModelViewProjectionMatrix * gl_Vertex;

片段着色器:

float depth = ((position_.z / position_.w) + 1.0) * 0.5;

gl_FragColor = vec4(depth, depth, depth, 1.0);

但我打印的都是白色的,我做错了什么?

【问题讨论】:

  • 我想了解更多上下文;着色器说明,因为它们对我来说看起来不错。您为顶点指定什么颜色?我唯一能想到的是,着色器没有完全加载,并且您正在运行默认的固定管道设置,这会顺便绘制写入图元。用于调试设置 glColor3f(1,0,0);在你的主程序和 gl_FragColor = vec4(0, depth, 0, 1.0);在着色器中区分固定函数和着色器管道。
  • 我在 gDebugger 中进行了一些调试,我的代码是正确的,一切都是白色的原因是深度值非常接近 1,0.999、0.98888。 gl_fragcolor 将纹理中的颜色设置为 256
  • 由于深度值的非线性分布,这在透视投影情况下是可以预料的。请参阅@Nicol Bolas 的回答。
  • 仔细想想,这些值表明近距和远距剪裁平面距离的选择并不理想。理想情况下,近和远剪辑平面“接触”场景,即近剪辑平面尽可能远,远剪辑平面尽可能靠近。如果你的裁剪平面是这样设置的,你应该会看到至少有一些深度值接近 0。
  • 感谢您的精彩解释

标签: opengl shader


【解决方案1】:

您想在哪个空间绘制深度?如果要绘制窗口空间深度,可以这样做:

gl_FragColor = vec4(gl_FragCoord.z);

但是,这不会特别有用,因为大多数数字将非常接近 1.0。只有非常接近的物体才会可见。这是使用标准透视投影的深度缓冲区的深度值分布的本质。

或者,换句话说,这就是你变白的原因。

如果您希望这些值在线性空间中,则需要执行以下操作:

float ndcDepth = ndcPos.z =
    (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
    (gl_DepthRange.far - gl_DepthRange.near);
float clipDepth = ndcDepth / gl_FragCoord.w;
gl_FragColor = vec4((clipDepth * 0.5) + 0.5); 

【讨论】:

  • gl_FragColor = vec4(...) 也会将 alpha 值设置为深度值。您不太可能想要混合深度片段,但在 Alpha 通道中放置深度有点不寻常。
  • 也不是更容易(在 GPU 上实现)确定与眼睛空间深度范围相关的深度吗?它进行线性插值,从而在片段阶段保存一些指令。
  • @datenwolf 剪辑空间 Z 只是眼睛空间 Z 的线性变换。由于我们正在讨论渲染为您可以查看的图像,因此两者之间没有区别将剪辑空间 Z 映射到 [0, 1] 并将眼睛空间 Z 映射到 [0, 1]。
  • 不管怎样,我说在顶点着色器中做这件事是优雅的解决方案。
【解决方案2】:

确实,片段的“深度”值可以从它在剪辑空间中的 z 值中读取(即在所有矩阵变换之后)。说的很对。

但是,您的问题在于w 的除法。 除以w 称为透视除法。是的,透视投影必须正常工作。

但是。在这种情况下,除以w 会“聚集”所有值(如您所见),非常接近 1.0。这有一个很好的理由:在perspective projectionw= (some multiplier) *z。也就是说,您将 z 值(无论计算出的值是多少)除以原始 z 的(某个因子)。难怪你总是得到接近 1.0 的值。您几乎将 z 除以自身。

作为一个非常简单的解决方法,尝试将z 仅除以远平面,并将其作为深度发送到片段着色器。

顶点着色器

varying float DEPTH ;

uniform float FARPLANE ;  // send this in as a uniform to the shader

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
DEPTH = gl_Position.z / FARPLANE ; // do not divide by w

片段着色器:

varying float DEPTH ;
// far things appear white, near things black
gl_Color.rgb=vec3(DEPTH,DEPTH,DEPTH) ;

结果是一个不错的、非常线性的渐变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 2013-01-03
    • 1970-01-01
    • 2017-05-16
    相关资源
    最近更新 更多