着色器的麻烦。对象仅从法线的一侧被照亮

Shader trouble. Object is illuminated only from the side of the normal

此着色器有问题

Shader "Diffuse " {
Properties {
_Color("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}

}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 150
Cull Off

CGPROGRAM
#pragma surface surf Lambert noforwardadd

sampler2D _MainTex;
fixed4 _Color;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb * _Color;
o.Alpha = c.a;
}
ENDCG
}

Fallback "Mobile/VertexLit"
}

如果您在对象的 material 上使用此着色器,则对象仅从法线的一侧被照亮,而相反的一侧保持未照亮,即使您将光线直接对准它也是如此。将什么代码添加到着色器,以在相反的法线侧显示灯光?它与 Nature / Tree Soft Occlusion Leaves 着色器完美配合,但是这个着色器非常重并且依赖于另一个着色器,另一个依赖于另一个着色器。而且,叶子着色器在那里包含很多多余的东西。上面的着色器非常轻巧,我想添加一些最小的东西,只是为了覆盖两侧——法线和法线的反面。

您要将其用于什么目的?是为了赏叶吗?

这里有两个选项:要么创建顶点片段着色器而不是表面着色器,然后自己编写光照代码(使用 abs(NdotL) 而不是 saturate(NdotL)),要么实现自己的光照函数.

如果您想坚持使用表面着色器,请像这样创建一个新函数:

#include "UnityCG.cginc"
half4 LightingFoliage(SurfaceOutput s, half3 lightDir, half atten) {
    half NdotL = abs(dot(s.Normal, lightDir));
    half4 color;
    color.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten);
    color.a = s.Alpha;

    return color;
}

然后改变这个:

#pragma surface surf Lambert noforwardadd

为此:

#pragma surface surf Foliage noforwardadd

现在您有了基本的朗伯照明,您可以根据需要在此函数的基础上进行构建。请注意,使用 abs(NdotL) 仅适用于像叶子这样的扁平物体;您可以通过使用 VFACE 语义来确定您是否正在渲染背面并将法线与 VFACE 值相乘(-1 如果背面,1 如果正面)来制作更通用的双面着色器。您可以在此处阅读有关 VFACE 的更多信息:https://docs.unity3d.com/Manual/SL-ShaderSemantics.html