Unity Shader - VS/PS 添加接受阴影处理

141 篇文章 33 订阅

Code

//jave.lin 2019.06.17
//simple illumination
Shader "Custom/MyReflection"
{
	Properties{
		[NoScaleOffset] _MainTex("Main Tex", 2D) = "white" {}
		[NoScaleOffset] _ReflectCube("Reflect Cube", Cube) = "white" {}
		_ReflectIntensity("Reflection Intensity", Range(0,1)) = 0.5
		_ReflectBrightness("Reflection Brightness", Range(1,2)) = 1
		_SpecularIntensity("Specular Intensity", Range(0,1)) = 1
		_AmbientIntensity("Ambient Intensity", Range(0,1)) = 1
		_SelfShadowColor("Self Shadow Color", Color) = (0.5,0.5,0.5,0.5)
		[Toggle] _HalfLambert("Half Lambert", Float) = 1
	}
	SubShader{
		Pass{
			Tags {"Queue" = "Opaque" "LightMode"="ForwardBase"} // shadow setup1:"LightMode"="ForwardBase"
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase 	// shadow setup2:fwdbase
			#include "UnityCG.cginc"
			#include "Lighting.cginc" 		// shadow setup3:#include "Lighting.cginc"
            #include "AutoLight.cginc" 		// shadow setup4:#include "AutoLight.cginc"
			struct a2v{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};
			struct v2f{
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                fixed4 tc : TEXCOORD1;
				LIGHTING_COORDS(2,3)		// shadow setup5:LIGHTING_COORDS(n,n+1)
                float3 worldNormal : TEXCOORD4;
                float3 worldPos : TEXCOORD5;
				float3 eyeDir : TEXCOORD6;
				float3 lightDir : TEXCOORD7;
            };
			sampler2D _MainTex;
			samplerCUBE _ReflectCube;
			float _ReflectIntensity;
			float _ReflectBrightness;
			float _SpecularIntensity;
			float _AmbientIntensity;
			fixed4 _SelfShadowColor;
			bool _HalfLambert;
			v2f vert(a2v v){
                v2f o = (v2f)0;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				o.eyeDir = normalize(_WorldSpaceCameraPos.xyz - o.worldPos).xyz;
				o.lightDir = normalize(_WorldSpaceLightPos0.xyz);
				TRANSFER_VERTEX_TO_FRAGMENT(o);	// shadow setup6:TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
			fixed4 frag(v2f i):SV_TARGET{
				float3 normalDir = normalize(i.worldNormal);
				float3 reflectDir = reflect(-i.eyeDir,normalDir);
				fixed3 specularDir = reflect(-i.lightDir,normalDir);
				
                fixed4 c = tex2D(_MainTex, i.uv); // albedo
				fixed4 r = texCUBE(_ReflectCube, reflectDir); // enviroment cubemap
				
				if(_HalfLambert){
					c.xyz *= (dot(i.lightDir,normalDir) + 1) * 0.5; // diffuse
				}else{
					c.xyz *= dot(i.lightDir,normalDir); // diffuse
				}
				c.xyz += c.xyz * UNITY_LIGHTMODEL_AMBIENT.rgb; // ambient

				float specularDotEye = max(0, dot(specularDir, i.eyeDir));
				c.xyz += (_LightColor0.rgb) * specularDotEye * _SpecularIntensity; // specular
				fixed3 skyDir = reflect(float3(0,-1,0),normalDir);
				c.xyz += unity_AmbientSky.rgb * unity_AmbientSky.a * max(0, dot(skyDir, i.eyeDir)) * _AmbientIntensity; // ambient sky
				fixed3 equatorDir = normalize(float3(_WorldSpaceCameraPos.x, i.worldPos.y, _WorldSpaceCameraPos.z) - i.worldPos).xyz;
				equatorDir = reflect(-equatorDir,normalDir);
				c.xyz += unity_AmbientEquator.rgb * unity_AmbientEquator.a * max(0, dot(equatorDir, i.eyeDir)) * _AmbientIntensity; // ambient equator
				fixed3 groundDir = reflect(float3(0,1,0),normalDir);
				c.xyz += unity_AmbientGround.rgb * unity_AmbientGround.a * max(0, dot(groundDir, i.eyeDir)) * _AmbientIntensity; // ambient ground
				c.xyz = lerp(c.xyz,c.xyz*r.xyz*_ReflectBrightness,_ReflectIntensity); // reflection

				UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos); // shadow setup7:UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos)
				atten = (atten + 1) * 0.5;
				c.xyz *= atten; // lighting and shadow attenuation
                return c;
            }

			ENDCG
		}
	}
	Fallback "Diffuse"
}

Steps

在代码中查看setupN,了解说明查看下面的References链接
也可以参考我之后写的一篇:Unity Shader - Toon Shading - 卡通渲染 - 添加阴影 - 里头的注释写的很清楚:每一步的基本作用

  • shadow setup1:“LightMode”=“ForwardBase”
  • shadow setup2:fwdbase
  • shadow setup3:#include “Lighting.cginc”
  • shadow setup4:#include “AutoLight.cginc”
  • shadow setup5:LIGHTING_COORDS(n,n+1)
  • shadow setup6:TRANSFER_VERTEX_TO_FRAGMENT(o)
  • shadow setup7:UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos)

另外参考

Adding Shadows to a Unity Vertex/Fragment Shader in 7 Easy Steps

Shader "Custom/SolidColor" {
    SubShader {
        Pass {
         
            // 1.) This will be the base forward rendering pass in which ambient, vertex, and
            // main directional light will be applied. Additional lights will need additional passes
            // using the "ForwardAdd" lightmode.
            // see: http://docs.unity3d.com/Manual/SL-PassTags.html
            Tags { "LightMode" = "ForwardBase" }
         
            CGPROGRAM
 
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
 
            // 2.) This matches the "forward base" of the LightMode tag to ensure the shader compiles
            // properly for the forward bass pass. As with the LightMode tag, for any additional lights
            // this would be changed from _fwdbase to _fwdadd.
            #pragma multi_compile_fwdbase
 
            // 3.) Reference the Unity library that includes all the lighting shadow macros
            #include "AutoLight.cginc"
 
 
            struct v2f
            {
                float4 pos : SV_POSITION;
                 
                // 4.) The LIGHTING_COORDS macro (defined in AutoLight.cginc) defines the parameters needed to sample 
                // the shadow map. The (0,1) specifies which unused TEXCOORD semantics to hold the sampled values - 
                // As I'm not using any texcoords in this shader, I can use TEXCOORD0 and TEXCOORD1 for the shadow 
                // sampling. If I was already using TEXCOORD for UV coordinates, say, I could specify
                // LIGHTING_COORDS(1,2) instead to use TEXCOORD1 and TEXCOORD2.
                LIGHTING_COORDS(0,1)
            };
 
 
            v2f vert(appdata_base v) {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                 
                // 5.) The TRANSFER_VERTEX_TO_FRAGMENT macro populates the chosen LIGHTING_COORDS in the v2f structure
                // with appropriate values to sample from the shadow/lighting map
                TRANSFER_VERTEX_TO_FRAGMENT(o);
                 
                return o;
            }
 
            fixed4 frag(v2f i) : COLOR {
             
                // 6.) The LIGHT_ATTENUATION samples the shadowmap (using the coordinates calculated by TRANSFER_VERTEX_TO_FRAGMENT
                // and stored in the structure defined by LIGHTING_COORDS), and returns the value as a float.
                float attenuation = LIGHT_ATTENUATION(i);
                return fixed4(1.0,0.0,0.0,1.0) * attenuation;
            }
 
            ENDCG
        }
    }
     
    // 7.) To receive or cast a shadow, shaders must implement the appropriate "Shadow Collector" or "Shadow Caster" pass.
    // Although we haven't explicitly done so in this shader, if these passes are missing they will be read from a fallback
    // shader instead, so specify one here to import the collector/caster passes used in that fallback.
    Fallback "VertexLit"

Runtime

在这里插入图片描述

Project

SurfaceShaderTest_SampleScene_测试环境反射 提取码: 3sng
unity version : 2019.1.7f1 运行SampleScene

References

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值