UnityShader中级篇——使物体接受阴影
2018-02-25 15:55
453 查看
Shader "Unity Shaders Book/Chapter 9/Shadow" { Properties { _Diffuse("Diffuse", Color) = (1,1,1,1) //控制高光反射的颜色 _Specular("Specular", Color) = (1,1,1,1) //控制高光区域的大小 _Gloss("Gloss", Range(8.0,256)) = 20 } SubShader { //BasePass,渲染环境光和最重要的平行光 Pass { //指明光照模式为前向渲染模式 Tags{ "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag //确保光照衰减等光照变量可以被正确赋值 #pragma multi_compile_fwdbase //包含引用的内置文件 #include "Lighting.cginc" #include "AutoLight.cginc" //声明properties中定义的属性 fixed4 _Diffuse; fixed4 _Specular; float _Gloss; //定义输入与输出的结构体 struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; //存储世界坐标下的法线方向和顶点坐标 float3 worldNormal : TEXCOORD0; float3 worldPos : TEXCOORD1; //添加内置宏,声明一个用于阴影纹理采样的坐标,参数是下一个可用的插值寄存器的索引值 SHADOW_COORDS(2) }; //在顶点着色器中,计算世界坐标下的法线方向和顶点坐标,并传递给片元着色器 v2f vert(a2v v) { v2f o; //转换顶点坐标到裁剪空间 o.pos = UnityObjectToClipPos(v.vertex); //转换法线坐标到世界空间,直接使用_Object2World转换法线,不能保证转换后法线依然与模型垂直 o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject); //转换顶点坐标到世界空间 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; //添加另一个内置宏,用于在顶点着色器中计算上一步中声明的阴影纹理坐标 TRANSFER_SHADOW(o); return o; } //在片元着色器中计算光照模型 fixed4 frag(v2f i) : SV_Target { //获取环境光 ,只计算一次,在之后的Additional Pass中不会再计算这个部分 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldNormal = normalize(i.worldNormal); fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); //计算漫反射光照 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir)); //获取视角方向 = 摄像机的世界坐标 - 顶点的世界坐标 fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz); //计算新矢量h fixed3 halfDir = normalize(viewDir + worldLightDir); //计算高光光照 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfDir)),_Gloss); //平行光的衰减值为1 fixed atten = 1.0; //使用内置宏计算阴影值 fixed shadow = SHADOW_ATTENUATION(i); return fixed4(ambient +(diffuse+specular) * atten * shadow,1.0); } ENDCG } //Additional Pass,渲染其他光源 Pass { //指明光照模式为前向渲染模式 Tags{ "LightMode" = "ForwardAdd" } //开启混合模式,将计算结果与之前的光照结果进行叠加 Blend One One CGPROGRAM #pragma vertex vert #pragma fragment frag //确保光照衰减等光照变量可以被正确赋值 #pragma multi_compile_fwdadd //包含引用的内置文件 #include "Lighting.cginc" //声明properties中定义的属性 fixed4 _Diffuse; fixed4 _Specular; float _Gloss; //定义输入与输出的结构体 struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; //存储世界坐标下的法线方向和顶点坐标 float3 worldNormal : TEXCOORD0; float3 worldPos : TEXCOORD1; }; //在顶点着色器中,计算世界坐标下的法线方向和顶点坐标,并传递给片元着色器 v2f vert(a2v v) { v2f o; //转换顶点坐标到裁剪空间 o.pos = UnityObjectToClipPos(v.vertex); //转换法线坐标到世界空间,直接使用_Object2World转换法线,不能保证转换后法线依然与模型垂直 o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject); //转换顶点坐标到世界空间 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; return o; } //在片元着色器中计算光照模型 fixed4 frag(v2f i) : SV_Target { fixed3 worldNormal = normalize(i.worldNormal); //计算不同的光源方向 #ifdef USING_DIRECTIONAL_LIGHT fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); #else fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz); #endif //计算漫反射光照 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir)); //获取视角方向 = 摄像机的世界坐标 - 顶点的世界坐标 fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz); //计算新矢量h fixed3 halfDir = normalize(viewDir + worldLightDir); //计算高光光照 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfDir)),_Gloss); //处理不同的光源衰减 #ifdef USING_DIRECTIONAL_LIGHT fixed atten = 1.0; #else /*float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz; fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;*/ float distance = length(_WorldSpaceLightPos0.xyz - i.worldPos.xyz); //线性衰减 fixed atten = 1.0 / distance; #endif return fixed4((diffuse + specular) * atten,1.0); } ENDCG } } Fallback"Specular" }
相关文章推荐
- UnityShader中级篇——顶点动画的阴影效果
- unity 动态改变所有子物体的shader
- [Unity Shader]光照模型对物体的假设
- Unity使用Shader动态的剪切物体
- unity在定制的shader里面如何添加阴影
- UnityShader中级篇——前向渲染中Base Pass 与Additional Pass
- 关于Unity动态物体无法向使用使用custom shader和lightmap的物体投射阴影
- Unity优化大全(五)之 GPU-动态阴影和Shader
- Unity优化大全(六)之 GPU-动态阴影和Shader
- 【Unity&2.5D&Shader】2.5D阴影资料总览
- UnityShader从入门到放弃(三)将法线的颜色填充给物体
- 【Unity Shader】结合Projector和Rendertexture实现实时阴影
- 【Unity&UGUI&Shader】创建材质球Material&代码控制更换物体材质球
- Unity用shader显示物体线框
- UnityShader中级篇——滚动的背景
- [Unity Shader]光照模型对物体的假设
- Shader 1:能接受阴影的透明shader
- 【Unity&2.5D&Shader】2D2.5D精灵实时阴影怎么使用
- Unity Shader Example 23 (透明物体描边)
- UnityShader中级篇——反射