Unity基础光照shader总结

《Unity Shader 入门精要读书笔记–初级篇–第六章》

      • 光照理论与光照模型
      • 相关案例与详细代码


光照理论与光照模型

详细的光照理论和光照模型在我另一篇文章中有比较详细的阐释,这里就不再赘述。
详见:3D游戏与计算机图形学中的数学方法读书笔记–第七章–光照部分

在这里我做几点简要补充:

  • 光源与物体表面相交只会有两个结果:散射吸收。散射到物体内部的现象被称为折射散射,而散射到物体外部的现象称为反射;其余部分则被吸收。散射不改变光线密度和颜色,只会改变方向;而吸收不改变方向,只会改变密度和颜色。

  • 计算机图形学第一定律:如果它看起来是对的,那么它就是对的。

  • 漫反射兰伯特定律计算如下: c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) m a x ( 0 , n ^ ⋅ l ^ ) c_{diffuse}=(c_{light}\cdot m_{diffuse})max(0,\hat n\cdot \hat l ) cdiffuse=(clightmdiffuse)max(0,n^l^)

  • 高光反射计算

    • Phong模型: r ^ = 2 ( n ^ ⋅ l ^ ) n ^ − l ^ \hat r=2(\hat n\cdot \hat l)\hat n-\hat l r^=2(n^l^)n^l^
      c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , v ^ ⋅ r ^ ) m g l a s s c_{specular}=(c_{light}\cdot m_{specular})max(0,\hat v\cdot \hat r)^{m_{glass}} cspecular=(clightmspecular)max(0,v^r^)mglass
    • Blinn-Phong模型: h ^ = v ^ + l ^ ∣ v ^ + l ^ ∣ \hat h=\frac {\hat v+\hat l}{|\hat v+\hat l|} h^=v^+l^v^+l^
      c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , n ^ ⋅ h ^ ) m g l a s s c_{specular}=(c_{light}\cdot m_{specular})max(0,\hat n\cdot \hat h)^{m_{glass}} cspecular=(clightmspecular)max(0,n^h^)mglass

相关案例与详细代码

  • 漫反射案例

    • 逐顶点漫反射光照
    	Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level"{
    	Properties{
    		_Diffuse("Diffuse",color) = (1,1,1,1)
    	}
    	SubShader{
    		Pass{
    			Tags{"LightMode" = "ForwardBase"}//设置前向渲染
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#include "Lighting.cginc"
    			fixed4 _Diffuse;
    			struct a2v{
    				float4 vertex:POSITION;
    				float3 normal:NORMAL;
    			};
    			struct v2f{
    				float4 pos:SV_POSITION;
    				fixed3 color:COLOR;
    			};
    
    			v2f vert(a2v v){
    				v2f o;
    				o.pos=UnityObjectToClipPos(v.vertex);
    				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
    				fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject));
    				fixed3 worldLight=normalize(_WorldSpaceLightPos0.xyz);
    				fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLight));
    				o.color=ambient+diffuse;
    				return o;
    			}
    
    			fixed4 frag(v2f i):SV_Target{
    				return fixed4(i.color,1.0);
    			}
    
    			ENDCG
    		}
    	}
    	Fallback "Diffuse"
    }
    • 逐像素漫反射光照
    Shader "Unity Shaders Book/Chapter 6/Diffuse Pixel-Level"{
    	Properties{
    		_Diffuse("Diffuse",color) = (1,1,1,1)
    	}
    	SubShader{
    		Pass{
    			Tags{"LightMode" = "ForwardBase"}
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#include "Lighting.cginc"
    			fixed4 _Diffuse;
    			struct a2v{
    				float4 vertex:POSITION;
    				float3 normal:NORMAL;
    			};
    			struct v2f{
    				float4 pos:SV_POSITION;
    				fixed3 worldNormal:TEXCOORD0;
    			};
    
    			v2f vert(a2v v){
    				v2f o;
                    			o.pos=UnityObjectToClipPos(v.vertex);
                   			o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
    				return o;
    			}
    
    			fixed4 frag(v2f i):SV_Target{
    				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 color=ambient+diffuse;
                    		return fixed4(color,1.0);
    			}
    
    			ENDCG
    		}
    	}
    
    	Fallback "Diffuse"
    }
    • 半兰伯特光照模型(通过改变点积结果范围,使背光面也可以有一定变化)
    	Shader "Unity Shaders Book/Chapter 6/Diffuse Half_Lambert"{
    	Properties{
    		_Diffuse("Diffuse",color) = (1,1,1,1)
    	}
    	SubShader{
    		Pass{
    			Tags{"LightMode" = "ForwardBase"}
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#include "Lighting.cginc"
    			fixed4 _Diffuse;
    			struct a2v{
    				float4 vertex:POSITION;
    				float3 normal:NORMAL;
    			};
    			struct v2f{
    				float4 pos:SV_POSITION;
    				fixed3 worldNormal:TEXCOORD0;
    				};
    
    			v2f vert(a2v v){
    				v2f o;
                    		o.pos=UnityObjectToClipPos(v.vertex);
                    		o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
    				return o;
    			}
    
    			fixed4 frag(v2f i):SV_Target{
    				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                       		fixed3 worldNormal=normalize(i.worldNormal);
                       		fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                        		fixed halfLambert=dot(worldLightDir,worldNormal)*0.5+0.5;
                        		fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*halfLambert;
                        		fixed3 color=ambient+diffuse;
                        		return fixed4(color,1.0);
    				}
    
    				ENDCG
    			}
    		}
    	
    	Fallback "Diffuse"
    }
    • 以上三个shader的效果如下:Unity基础光照shader总结_第1张图片
      Unity基础光照shader总结_第2张图片
  • 高光反射案例

    • 逐顶点高光反射
    	Shader "Unity Shaders Book/Chapter 6/Specular Vertex-Level"{
        	Properties{
            	_Diffuse("Diffuse",Color)=(1,1,1,1)
            	_Specular("Specular",Color)=(1,1,1,1)
            	_Gloss("Gloss",Range(8.0,256))=20
        	}
        	SubShader{
            	pass{
                	Tags{"LightMode"="ForwardBase"}
                	CGPROGRAM
    
                	#pragma vertex vert
                	#pragma fragment frag
                	#include "Lighting.cginc"
    
                	fixed4 _Diffuse;
                	fixed4 _Specular;
                	float _Gloss;
    
                	struct a2v{
                    	float4 vertex:POSITION;
                    	float3 normal:NORMAL;
                	};
    
                	struct v2f{
                    	float4 pos:SV_POSITION;
                    	fixed3 color:COLOR;
                	};
    
                	v2f vert(a2v v){
                    	v2f o;
                    	o.pos=UnityObjectToClipPos(v.vertex);
                    	fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                    	fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject));
                    	fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                    	fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLightDir));
    
                    	fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal));
                    	fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-mul(unity_ObjectToWorld,v.vertex).xyz);
                    	fixed3 specular=_LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)),_Gloss);
    
                    	o.color=ambient+diffuse+specular;
                    	return o;
                	}
    
                	fixed4 frag(v2f i):SV_TARGET{
                    	return fixed4(i.color,1.0);
                	}
    
                	ENDCG
            	}	
        	}
        	Fallback "Specular"
    }
    • 逐像素高光反射
    Shader "Unity Shaders Book/Chapter 6/Specular Pixel-Level"{
        Properties{
            _Diffuse("Diffuse",Color)=(1,1,1,1)
            _Specular("Specular",Color)=(1,1,1,1)
            _Gloss("Gloss",Range(8.0,256))=20
        }
        SubShader{
            pass{
                Tags{"LightMode"="ForwardBase"}
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
                #include "Lighting.cginc"
    
                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);//pos is the type of float4 while worldPos is float3,so worldPos have the extra .xyz 
                    o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
                    o.worldPos=mul(v.vertex,(float3x3)unity_WorldToObject).xyz;
                    return o;
                }
    
                fixed4 frag(v2f i):SV_TARGET{
                    fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                    fixed3 worldNormal=normalize(i.worldNormal);
                    fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                    fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldLightDir,worldNormal));
                    
                    fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal));
                    fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
                    fixed3 specular=_LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)),_Gloss);
    
                    return fixed4(ambient+diffuse+specular,1.0);
    
                }
    
                ENDCG
            }
        }
        Fallback "Specular"
    }
    • Blinn-Phong光照模型
    Shader "Unity Shaders Book/Chapter 6/Specular BlinnPhong"{
        Properties{
            _Diffuse("Diffuse",Color)=(1,1,1,1)
            _Specular("Specular",Color)=(1,1,1,1)
            _Gloss("Gloss",Range(8.0,256))=20
        }
        SubShader{
            pass{
                Tags{"LightMode"="ForwardBase"}
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
                #include "Lighting.cginc"
    
                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);//pos is the type of float4 while worldPos is float3,so worldPos have the extra .xyz 
                    o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
                    o.worldPos=mul(v.vertex,(float3x3)unity_WorldToObject).xyz;
                    return o;
                }
    
                fixed4 frag(v2f i):SV_TARGET{
                    fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                    fixed3 worldNormal=normalize(i.worldNormal);
                    fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                    fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldLightDir,worldNormal));
                    
                    fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
                    fixed3 newDir=normalize(viewDir+worldLightDir);
                    fixed3 specular=_LightColor0.rgb*_Specular.rgb*pow(saturate(dot(newDir,worldNormal)),_Gloss);
    
                    return fixed4(ambient+diffuse+specular,1.0);
    
                }
    
                ENDCG
            }
        }
        Fallback "Specular"
    }
    • 则上述三个shader效果如下:
      Unity基础光照shader总结_第3张图片
      Unity基础光照shader总结_第4张图片

你可能感兴趣的:(Unity,Shader)