问题描述
我对着色器非常陌生,请耐心等待。我有一个网格,我想在世界空间位置y(例如10)下放置沙子纹理,否则应该是草纹理。显然,它似乎忽略了我输入的任何内容,仅选择草的纹理。之所以发生这种情况,是因为与我只返回相同纹理的情况相比,使用此功能时我的vert和tris计数会爆炸。无论我的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;
让我们从列表中走下来并分别进行测试。
- 检查
input.positionWS.y
是否实际包含我们期望包含的值。为此,我们可以将任何RGB通道设置为其值,然后直接将其返回即可。
return float4(input.positionWS.y,1);
现在,如果input.positionWS.y
不是规范化值(也就是0到1的值),则几乎可以保证仅将纹理返回为完全红色。为了对其进行归一化,我们将其值除以最大值,让max = 100
作为示例。
return float4(input.positionWS.y / 100,1);
现在这应该使纹理的顶部为全红色(input.positionWS.y / 100
为1),底部为黑色(其中input.positionWS.y / 100
为零),其间从黑色到全红色的渐变。 (请注意,由于其在世界空间中的位置,您可能需要向上/向下移动纹理以查看颜色偏移)。如果这种情况没有发生,例如,它始终保持黑色或全红色,那么您的问题很可能是input.positionWS.y
。
- if语句。您的语句
(input.positionWS.y < _SandStart)
可能总是返回true
或false
,这意味着它永远不会拆分。通过注释掉当前的返回纹理,我们可以很容易地进行测试,而只需返回如下的纯色即可:
if(input.positionWS.y < _SandStart)
{
return float4(1,1);
}
else
{
return float4(0,1,1);
}
如果我们在步骤1中测试input.positionWS.y
是正确的,并且_SandStart
设置正确,我们应该看到纹理分为红色部分(如果为true)和另一部分蓝色(如果为false) )(同样,由于我们基于世界位置,因此可能需要稍微更改材质的高度才能看到它)。如果没有发生这种颜色划分,则可能的原因是_SandStart
设置不正确或设置为错误的值。 (假设这是一个属性,您可以在材质编辑器中检查其值)
- 如果以上两个步骤均产生预期结果,则
return tex2D(_MainTex,input.uv)* mainLight.shadowAttenuation;
可能是罪魁祸首。要对此进行调试,我们可以返回不带if语句和shadowAttenuation的纹理之一,看看它是否应用了纹理,然后通过更改注释的行来返回另一个纹理。
return tex2D(_MainTex,input.uv);
//return tex2D(_SandTex,input.uv);
如果分别正确地应用了这些纹理中的每一个,则可能不是您的原因,而是留下了shadowAttenutation(只需将乘积添加到上面的测试中)或其他完全未被您的代码覆盖的东西问题。
- 奖金回合。如果您要调试着色器 property ,则实际上也可以使用
material.Get<type>
函数从C#中进行此操作(受支持的类型可以在docs here中找到,并且也包括数组变体,以及Get
和Set
)。一个小例子:
Properties
{
_Foo ("Foo",Float) = 2
_Bar ("Bar",Color) = (1,1)
}
可以使用C#从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)