请注意,OP发现他们的具体问题不是由问题中的代码引起的,而是他们的几何函数错误,这个答案只是关于“有没有办法调试着色器值”,因为这种调试方法帮助 OP 找到了问题
调试着色器代码可能是一项相当具有挑战性的任务,具体取决于您需要调试的内容,并且有多种方法可以解决此问题。我个人最喜欢的方法是使用颜色。
如果我们将其分解,您的代码中可能存在三个方面的问题:
-
input.positionWS.y的值
- if 语句
(input.positionWS.y < _SandStart)
- 返回你的纹理
return tex2D(_MainTex, input.uv)* mainLight.shadowAttenuation;
让我们逐个列出并单独测试。
- 检查
input.positionWS.y 是否真的包含我们期望它包含的值。为此,我们可以将任何 RGB 通道设置为其值,然后直接返回该值。
return float4(input.positionWS.y, 0, 0, 1);
现在,如果input.positionWS.y 不是标准化值(也就是范围从 0 到 1 的值),这几乎可以保证将您的纹理返回为完全红色。为了规范化它,我们将值除以其最大值,我们以max = 100 为例。
return float4(input.positionWS.y / 100, 0, 0, 1);
现在应该使纹理在顶部(input.positionWS.y / 100 为 1)为全红色,在底部为黑色(input.positionWS.y / 100 为 0),以及从黑色到全红色的渐变。 (请注意,由于它在世界空间中的位置,您可能需要向上/向下移动纹理以查看颜色变化)。如果这没有发生,例如它始终保持黑色或全红色,那么您的问题很可能是 input.positionWS.y。
- if 语句。可能您的语句
(input.positionWS.y < _SandStart) 总是返回true 或false,这意味着它永远不会分裂。我们可以通过注释掉当前返回的纹理来很容易地测试这一点,而不是像这样返回一个平面颜色:
if(input.positionWS.y < _SandStart)
{
return float4(1,0,0,1);
}
else
{
return float4(0,0,1,1);
}
如果我们在步骤 1 中测试了 input.positionWS.y 是正确的,并且 _SandStart 设置正确,我们应该看到纹理被分为红色部分(如果为真)和另一部分蓝色(如果为假)(再次因为我们基于世界位置,我们可能需要稍微改变材质的高度才能看到它)。如果这种颜色划分没有发生,那么可能的原因是_SandStart 设置不正确,或者设置了不正确的值。 (假设这是一个属性,您可以在材质编辑器中检查其值)
- 如果上述两个步骤都产生了预期的结果,那么
return tex2D(_MainTex, input.uv)* mainLight.shadowAttenuation; 可能是罪魁祸首。为了调试这一点,我们可以在不使用 if 语句和 shadowAttenuation 的情况下返回其中一个纹理,查看它是否应用了该纹理,然后通过更改注释的行返回另一个纹理。
return tex2D(_MainTex, input.uv);
//return tex2D(_SandTex, input.uv);
如果这些纹理中的每一个都被分别正确应用,那么这不太可能是您的原因,留下 shadowAttenutation(只需将乘法添加到上述测试中)或完全不同的东西,您的代码中没有涵盖问题。
- 奖金回合。如果你有一个想要调试的着色器property,你实际上可以从 C# 中执行此操作,也可以使用
material.Get<type> 函数(支持的类型可以在 docs here 中找到,并包括数组变体以及Get 和Set)。一个小例子:
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)