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的效果如下:在这里插入图片描述
      在这里插入图片描述
  • 高光反射案例

    • 逐顶点高光反射
    	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效果如下:
      在这里插入图片描述
      在这里插入图片描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值