Unity——基于ShaderLab实现光照系统 (3)

片元着色器中添加:

//反射方向 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir); //uv取样高光遮罩纹理*高光范围 fixed3 specularMask = tex2D(_SpecularMask,i.uv).r *_SpecularScale; //高光结果混合遮罩纹理 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(tangentNormal,halfDir)),_Gloss) * specularMask;

效果对比:

四、透明物体 1.透明测试

AlphaTest只决定画不画,不做颜色混合,给定一个阈值_Cutoff,透明度小于这个值都不画;

透明测试需要关闭背面裁剪,以及加上透明测试三套件;

Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="Transparent"}

//渲染队列,忽略投影器,渲染类型 Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="Transparent"} //关闭裁剪 Cull Off Pass{ ... fixed4 frag (v2f i) : SV_Target{ ... //alpha值小于_Cutoff的都不画 clip(texColor.a - _Cutoff); ... } ... }

修改Culloff值大小的效果:

2.透明颜色混合

AlphaBlend透明混合要关闭深度写入,否则会被剔除;

同时要选择混合模式,多种混合模式有点像ps里的透明图层叠加;

//三套件 Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} Pass{ //关闭深度吸入,打开深度测试,选择颜色混合模式 Tags{"LightMode"="ForwardBase"} ZWrite Off Blend SrcAlpha OneMinusSrcAlpha ... fixed4 frag (v2f i) : SV_Target{ ... //返回着色是,加上透明度 return fixed4(ambient +diffuse,texColor.a*_AlphaScale); } }

3.复杂模型双Pass颜色混合

模型复杂的时候会有自己遮挡自己的问题;用双Pass解决,第一个pass提前做好深度写入且只做深度入;

Pass{ ZWrite On ColorMask 0 //RGBA任意|,选择需要写入的通道,只做深度缓冲,0不输出颜色 }

4.透明混合渲染双面

同一个透明物体,我需要需要从正面看到透明物体的背面;

使用两个Pass;一个Cull Front,一个Cull Back;

背面和正面分开画,先画背面,用正面和背面混合;

五、复杂光照处理 1.复杂光照

Unity光源分为垂直光,点光源,锥形射光灯,面光源和探照灯都是烘焙后生效的不讨论;

Unity中普通Forwad前向渲染,没多一个灯光要加一个Pass单独处理;

Deffer延迟渲染,多个灯光也指渲染一次,有个G-Buffer存储了图像,在G-Buffer上处理光照;

点光源,锥形射光灯——光线方向由光源到顶点的方向;光线的衰减值也不同;

Unity系统提供的点光源和锥形射光灯的光线衰减纹理图,减少了计算;

Tags{"LightMode" = "ForwardAdd"} #pragma multi_compile_fwdadd #include "Lighting.cginc" #include "AutoLight.cginc" fixed4 frag (v2f i) : SV_Target { fixed3 worldNormal = normalize(i.worldNormal); //deal with different light,get worldLightDir; #ifdef USING_DIRECTIONAL_LIGHT fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed atten = 1.0; #else fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz); //Get light attenuation #if defined (POINT) float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz; fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL; #elif defined (SPOT) float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)); fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL; #else fixed atten = 1.0; #endif #endif ... return fixed4((diffuse+specular)*atten,1.0); }

2.阴影处理

Untiy中MeshRender组件上有两个选项:

CastShadows——是否投射阴影,以及双面投射;

Receive Shadows——接受其他物体投射的阴影;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgxzfy.html