我的着色器忽略了我的世界空间高度

my shader is ignoring my worldspace height

我对着色器还很陌生,所以请多多包涵。我有一个网格,我想将沙子纹理放在世界空间位置 y 的下方,例如 10,否则它应该是草纹理。显然,它似乎忽略了我放入的任何内容,只选择了草纹理。与我只是 return 相同的纹理相比,我的垂直和三角形计数随着此功能爆炸,发生了一些事情。无论我的 sandStart 值是多少,我都看不到任何东西

这是我的 frag 函数:

if (input.positionWS.y < _SandStart) {
return tex2D(_MainTex, input.uv)* mainLight.shadowAttenuation;
} else {
return tex2D(_SandTex, input.uv) * mainLight.shadowAttenuation;
}

是否还有一种方法可以轻松调试某些值?

请注意,OP 发现他们的具体问题不是由问题中的代码引起的,而是他们的几何函数错误,这个答案只是关于问题“是否存在一种调试着色器值的方法”,因为这种调试方法帮助 OP 找到了问题


调试着色器代码可能是一项非常具有挑战性的任务,具体取决于您需要调试的内容,并且有多种方法可以解决。我个人最喜欢的方法是使用颜色。

如果我们对其进行分解,您的代码中可能存在三个方面的错误:

  • input.positionWS.y的价值
  • if 语句 (input.positionWS.y < _SandStart)
  • 返回你的纹理return tex2D(_MainTex, input.uv)* mainLight.shadowAttenuation;

让我们沿着列表逐一进行测试。

  1. 检查 input.positionWS.y 是否确实包含我们期望它包含的值。为此,我们可以将任何 RGB 通道设置为它的值,然后直接 returning 那个。
return float4(input.positionWS.y, 0, 0, 1);

现在,如果 input.positionWS.y 不是标准化值(a.k.a 范围从 0 到 1 的值),这几乎可以保证 return 您的纹理完全是红色的。为了对其进行归一化,我们将值除以其最大值,让我们以 max = 100 为例。

return float4(input.positionWS.y / 100, 0, 0, 1);

现在应该使纹理顶部全红(input.positionWS.y / 100 为 1),底部全黑(input.positionWS.y / 100 为零),以及从黑色到全的渐变中间红色。 (请注意,由于它在世界中的位置 space,您可能需要移动纹理 up/down 才能看到颜色偏移)。如果这没有发生,例如它始终保持黑色或全红色,那么您的问题很可能是 input.positionWS.y.

  1. if 语句。可能是你的语句 (input.positionWS.y < _SandStart) 总是 return 是 truefalse,这意味着它永远不会分裂。我们可以很容易地通过注释掉当前的 return 纹理来测试这一点,而只是 return 像这样的平面颜色:
if(input.positionWS.y < _SandStart)
{
    return float4(1,0,0,1);
}
else
{
    return float4(0,0,1,1);
}

如果我们在步骤 1 中测试 input.positionWS.y 是正确的,并且 _SandStart 设置正确,我们应该看到纹理被分为红色部分(如果为真)和另一部分蓝色(如果为 false)(再次因为我们基于世界位置,我们可能需要稍微改变 material 的高度才能看到它)。如果这种颜色划分没有发生,那么可能的原因是 _SandStart 设置不正确,或者设置的值不正确。 (假设这是一个 属性 你可以在 material 编辑器中检查它的值)

  1. 如果以上两个步骤都产生了预期的结果,那么 return tex2D(_MainTex, input.uv)* mainLight.shadowAttenuation; 可能是罪魁祸首。要对此进行调试,我们可以 return 一个不带 if 语句和 shadowAttenuation 的纹理,看看它是否应用该纹理,然后 return 通过更改注释行来 return 另一个纹理。
return tex2D(_MainTex, input.uv);
//return tex2D(_SandTex, input.uv);

如果这些纹理中的每一个都单独正确应用,那么这不太可能是你的原因,留下 shadowAttenutation(只需将乘法添加到上面的测试)或完全不同的代码未涵盖的东西在你的问题中。

  1. 奖励回合。如果你有一个着色器 属性 你想调试你实际上可以从 C# 中使用 material.Get<type> 函数来做这个(支持的类型可以在docs here,也包括数组变体,以及 GetSet)。一个小例子:
Properties 
{
_Foo ("Foo", Float) = 2
_Bar ("Bar", Color) = (1,1,1,1)
}

可以使用

从 C# 进行调试
Material mat = getComponent<Material>();
Debug.LogFormat("_Foo value: {0}",  mat.GetFloat("_Foo"); //prints 2
Debug.LogFormat("_Bar value: {0}",  mat.GetFloat("_Bar"); //prints (1,1,1,1)