Unity - 如何重新着色纹理网格的各个面?
Unity - How to recolor individual faces of a textured mesh?
我有一个带纹理的网格,其中包含特定的三角形列表,这些三角形对应于网格上的面,这些面在运行时使用如下代码重新着色:
_mesh = GetComponent<MeshFilter>().mesh;
...
var colors = _mesh.colors;
foreach (int n in trianglesIndexList)
{
colors[n] = Color.blue;
}
_mesh.colors = colors;
效果很好,但我原本打算将这些面孔设为亮蓝色。不幸的是,颜色似乎与我在 Unity 中分配给网格的 material 的纹理混合在一起。在这里你可以看到纹理上的绿草混合了相当绿色的外观 "blue":
我试过使用灯光,但这似乎不是问题所在。我得到的网格着色需要使用特定的着色器,因此我已将 Particles / Standard Surface
着色器分配给网格。
有没有什么方法可以在运行时为纹理的各个部分重新着色并使这些面看起来呈亮蓝色?
好的,没关系,我通过在大约 3 小时内学习着色器代码的工作原理并编写自定义着色器找到了自己的解决方案。只需使用 Unity 的默认标准着色器作为起点并添加 worldNormal 和 worldPos 输入,如下所示:
struct Input
{
float2 uv_MainTex;
float3 worldNormal;
float3 worldPos;
};
然后在 surf 函数中,您可以过滤到仅朝上的法线(在这种情况下这是我想要的)并再次通过世界 space 坐标过滤这些网格坐标。
void surf(Input IN, inout SurfaceOutputStandard o)
{
float2 UV;
fixed4 c;
if (abs(IN.worldNormal.x) > 0.5)
{
// normals facing the left and right side
UV = IN.worldPos.yz;
c = tex2D(_MainTex, IN.uv_MainTex);
}
else if (abs(IN.worldNormal.z) > 0.5)
{
// normals facing forward and backward
UV = IN.worldPos.xy;
c = tex2D(_MainTex, IN.uv_MainTex);
}
else
{
// normals facing up and down
if (abs(IN.worldPos.x) > 0.5)
{
UV = IN.worldPos.xz;
// COLOR IT BLUE
c = tex2D(_MainTex, IN.uv_MainTex) + (_Color * _SinTime.y);
}
else
{
UV = IN.worldPos.xz;
c = tex2D(_MainTex, IN.uv_MainTex);
}
}
显然可以将其简化很多,但这就是我想知道的全部。我什至想出了如何使用内置的 SinTime 变量随时间重新着色。超级简单。
我有一个带纹理的网格,其中包含特定的三角形列表,这些三角形对应于网格上的面,这些面在运行时使用如下代码重新着色:
_mesh = GetComponent<MeshFilter>().mesh;
...
var colors = _mesh.colors;
foreach (int n in trianglesIndexList)
{
colors[n] = Color.blue;
}
_mesh.colors = colors;
效果很好,但我原本打算将这些面孔设为亮蓝色。不幸的是,颜色似乎与我在 Unity 中分配给网格的 material 的纹理混合在一起。在这里你可以看到纹理上的绿草混合了相当绿色的外观 "blue":
我试过使用灯光,但这似乎不是问题所在。我得到的网格着色需要使用特定的着色器,因此我已将 Particles / Standard Surface
着色器分配给网格。
有没有什么方法可以在运行时为纹理的各个部分重新着色并使这些面看起来呈亮蓝色?
好的,没关系,我通过在大约 3 小时内学习着色器代码的工作原理并编写自定义着色器找到了自己的解决方案。只需使用 Unity 的默认标准着色器作为起点并添加 worldNormal 和 worldPos 输入,如下所示:
struct Input
{
float2 uv_MainTex;
float3 worldNormal;
float3 worldPos;
};
然后在 surf 函数中,您可以过滤到仅朝上的法线(在这种情况下这是我想要的)并再次通过世界 space 坐标过滤这些网格坐标。
void surf(Input IN, inout SurfaceOutputStandard o)
{
float2 UV;
fixed4 c;
if (abs(IN.worldNormal.x) > 0.5)
{
// normals facing the left and right side
UV = IN.worldPos.yz;
c = tex2D(_MainTex, IN.uv_MainTex);
}
else if (abs(IN.worldNormal.z) > 0.5)
{
// normals facing forward and backward
UV = IN.worldPos.xy;
c = tex2D(_MainTex, IN.uv_MainTex);
}
else
{
// normals facing up and down
if (abs(IN.worldPos.x) > 0.5)
{
UV = IN.worldPos.xz;
// COLOR IT BLUE
c = tex2D(_MainTex, IN.uv_MainTex) + (_Color * _SinTime.y);
}
else
{
UV = IN.worldPos.xz;
c = tex2D(_MainTex, IN.uv_MainTex);
}
}
显然可以将其简化很多,但这就是我想知道的全部。我什至想出了如何使用内置的 SinTime 变量随时间重新着色。超级简单。