WebGL片段着色器未在if语句上正确分支

时间:2013-11-26 14:51:49

标签: opengl-es glsl webgl shader

我正在开发一个实现阴影贴图的WebGL程序。在计算每个片段的深度值之后,我在末尾有一个if语句,根据片段是否在阴影中来计算光照。

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1);
if (light_tex_coord.z - depth <= 0.0) {
  gl_FragColor += vec4
      ( calcLighting(light1, eye_dir, eye_dir_norm, normal)
      , 0.0
      );
}

Shadows not being correctly computed, branch never taken

其中depth是阴影贴图的深度,light_tex_coord是片段在light1的场景空间中的位置。 light1是围绕模型旋转的点光源,light0是静态定位在相机处的点光源。

这里的问题是从不采用if分支,因此场景只应用了light0。我已检查depthlight_tex_coordcalculateLighting是否正常工作。

但是,这是奇怪的事情,用以下代码替换上面的内容:

if (light_tex_coord.z - depth <= 0.0) {
  gl_FragColor = vec4(0,1,0,1);
} else {
  gl_FragColor = vec4(1,0,0,1);
}

Shadowed fragments correctly computed and drawn as red and green

使阴影区域以红色正确绘制,并且不带阴影以绿色绘制。也就是说,正确评估分支。用它替换它:

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1);
gl_FragColor += vec4
    ( calcLighting(light1, eye_dir, eye_dir_norm, normal)
    , 0.0
    );

Lighting computed without shadows

导致正确计算光照(尽管没有阴影)。看来,当我在if语句中调用更昂贵的calcLighting函数时,它甚至不打扰它。

此外,我尝试过以多种方式应用照明,包括使用clamp功能;总是进行添加并使用三元运算符将第二个calcLighting调用乘以1或0,并以不同的方式排列我的if语句。似乎没什么用。

对于webgl中的分支是如何工作的,我有什么遗漏吗?

3 个答案:

答案 0 :(得分:0)

也许WebGl上下文不支持深度。然后使用它的表达式将被忽略。

您可以使用getContextAttributes()

进行检查

答案 1 :(得分:0)

而不是分支,你是否考虑过像这样激进的东西:

gl_FragColor += vec4 (
    calcLighting(light1, eye_dir, eye_dir_norm, normal)
    , 0.0
    ) * abs (min (sign (light_tex_coord.z - depth), 0.0));

这不是世界上最漂亮的解决方案,但它可能会让你得到更多符合你所寻找的东西。它基本上采用你的light_tex_coord.z - depth <= 0.0条件表达式并使其成为一个漂亮的浮点 0.0 1.0 ,你可以将灯光乘以 keep 丢弃分支结果。在引入动态流控制之前,着色器 使用 的方式有效。

答案 2 :(得分:0)

主题是2岁,但这是我的2美分:

我遇到了类似的问题,并在互联网上找到了一个包含以下句子的讨论页面:

  

[...](除非你做像条件中的图像写入等疯狂的东西   块)。 [...]

所以我尝试将像素颜色放在临时变量

vec4 col;

本地到main(),在“if”语句中我只修改了col,并且我只在最后设置了像素颜色:

gl_FragColor = col;

这解决了我的问题。当然,可能需要烦人的额外编程才能使流量在每种情况下都到达最后一行。