TA100 L2.4

一、光照模型

定义:光线与空间中物体表面之间的交互模型

分类:1.基于物理理论的光照模型(PBR)2.经验光照模型

意义:现实光照对于电脑来说过于复杂,影响因素也过多。光照模型通过对现实中的光照情况进行总结和简化,得出一套用于计算机计算光照的方案

历史:

二、局部光照模型

定义:只考虑直接光照的光线

1.漫反射

光线均匀反射,通过吸收和散射改变颜色和方向

符合Lambert理论:

DiffCol = LightCol * BaseCol * nDotl

2.高光反射

理论:

反光只会在圆锥的范围内被观察到,圆锥体顶角的大小表示着反射的集中程度

SpecCol = LightCol * mSpec * (dot(v , r) ^ mGloss)

r= 1 - 2 * ndotl * n

mSpec即反射光强度,mGloss即SpecPow

mGloss(SpecPow)越大,镜面反射越集中

3.环境光

AmbientCol = AO * BaseCol

4.自发光

三、经典光照模型

1.Lambert

DiffCol

2.Phong

DiffCol + SpecCol + AOCol + EmitCol

3.Blinn-Phong

 

 将镜面反射中的vdotr改为hdotn,h为半角向量(光照方向和视线方向的角平分线)

开销相对Phong小

反光度低时,大部分区域都能发射反射光并被人眼接收到,而当lDir和vDir在nDir的同一侧时,Phong判定为暗,产生断层

4.Gourand

 以顶点为单位来计算光照然后插值得到像素亮度

优点:很好表现物体光滑性 缺点:镜面高光不集中

 好丑。。。

5.Flat

一个面片只有一个颜色,不平滑

多用于low poly风格

DLC:先行版

UnpackNormal:

(0,1)变换到(-1,1)

Cubemap:

给反射光安排个贴图

lod越大,看起来越粗糙(经常用roughness控制lod)

IBL:基于图像的光照,以贴图为光源加入到光照计算中

TRICKS:

 ndotl决定是用AO来乘还是LightCol来乘

 

 金属只有镜面反射

一个lerp来决定法线强度(是用模型本身的法线还是法线贴图)

作业:

1.能量守恒理念在基础光照中的作用

能量守恒:E(入射光)>E(出射光)(除非材质自带自发光)

光照照射到表面上,分为折射和反射,折射部分进入物体内部后会被吸收或者散射(产生漫反射)。反射光和折射光互斥,故入射光减去反射光等于进入材质内部的折射光

PBR简化折射光,将折射光是做完全吸收而不散开。金属材质吸收所有折射光,因此只有镜面反射而无折射光的漫反射

随着粗糙度的上升,光照逐渐变散,反射到的区域面积增加,但镜面反射的亮度会减小。(如果亮度恒定,那么反射面积增加的时候,反射出的能量会增加,最终超过入射能量)

2.光照模型coding

先上效果

 

 Blinn-Phong

Phong

 CubeMap

 然后上代码,从庄老师的11课的OldschoolPro起手改的

Shader "L10/OldschoolPro" {									//路径 
    Properties {
    	[Header(Texture)]
    		_MainTex	("基础颜色+透明遮罩", 2D)			="gray"{}
    		_NormTex	("法线贴图", 2D)					="white"{}
    		_AOTex		("AO", 2D)							="white"{}
			_CubeMap	("CubeMap", CUBE)					="_Skybox"{}
			_LightCol	("LightColor", COLOR)				=(1.0, 1.0, 1.0, 1.0)
			_NormInt	("Normal Int", range(0,1))			=1
			_SpecInt	("SpecInt", range(0,10))			=1
			_Gloss		("Gloss", range(1,60))				=30 //一定程度上反应金属度 
			_EnvInt		("EnvInt", range(0, 1))				=1
			[Toggle] _specswitch	("Use Blinn-Phong", float)	=0
			    }														//面板参数 
    SubShader {		
        Tags {												//格式{ 
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0								//}格式 
            uniform sampler2D _MainTex;
            uniform sampler2D _NormTex;
            uniform sampler2D _AOTex;
            uniform samplerCUBE _CubeMap;
            uniform float4 _LightCol;
            uniform float _NormInt;
            uniform float _SpecInt;
			uniform float _Gloss;
			uniform float _EnvInt;
			uniform float _specswitch;
            
            struct VertexInput {
                float4 vertex : POSITION;
                float2 uv0	  : TEXCOORD0;
                float4 normal : NORMAL;
                float4 tangent: TANGENT;
                
            };	//输入结构 
            struct VertexOutput {
                float4 pos    : SV_POSITION;
                float2 uv0 	  : TEXCOORD0;
                float3 posWS  : TEXCOORD1;
                float3 nDirWS : TEXCOORD2;
                float3 tDirWS : TEXCOORD3;
                float3 bDirWS : TEXCOORD4;
                LIGHTING_COORDS(5,6)
            };	//输出结构 
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.pos 	= UnityObjectToClipPos( v.vertex );
                o.uv0 	= v.uv0;
                o.posWS = mul(unity_ObjectToWorld, v.vertex);
                o.nDirWS= UnityObjectToWorldNormal(v.normal);
                o.tDirWS= normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );
                o.bDirWS= normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }	//vertex shader 
            float4 frag(VertexOutput i) : COLOR {
            	//向量准备
				float3 nDirTS 	= UnpackNormal(tex2D(_NormTex, i.uv0));
            	float3x3 TBN 	= float3x3(i.tDirWS, i.bDirWS, i.nDirWS);
            	float3 nDirWS 	= normalize(mul(nDirTS, TBN));
            	float3 nDirMWS  = i.nDirWS;
            	float3 vDirWS 	= normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);
            	float3 finalNorm= lerp(nDirMWS, nDirWS, _NormInt);
            	
            	float3 vrDirWS 	= reflect(-vDirWS, finalNorm);
            	float3 lDirWS 	= _WorldSpaceLightPos0.xyz;
            	float3 lrDirWS 	= reflect(-lDirWS, finalNorm);
            	float3 hDir		= normalize(vDirWS+lDirWS);
            	float3 ndoth	= saturate(dot(finalNorm, hDir));
				//中间量准备
				float ndotl = max(0, dot(finalNorm,lDirWS));
				float vdotr = max(0, dot(vDirWS,lrDirWS));
				float vdotn = max(0, dot(vDirWS,finalNorm));
				//纹理采样
				float3 var_MainTex	= tex2D(_MainTex,i.uv0);
				float3 var_NormTex	= tex2D(_NormTex,i.uv0);
				float  var_AO		= tex2D(_AOTex,i.uv0).r;
  				//光照模型
					//LAMBERT 	
					float3 dirDiff	= lerp(var_MainTex*var_AO, var_MainTex*_LightCol, ndotl);
					//PHONG
					float3 PCol 	= lerp(dirDiff*pow(vdotr, _Gloss), pow(vdotr, _Gloss), _Gloss/60)*_Gloss/60*_SpecInt*_LightCol;
					//Blinn-Phong
					float3 BPCol	= lerp(dirDiff*pow(ndoth, _Gloss), pow(ndoth, _Gloss), _Gloss/60)*_Gloss/60*_SpecInt*_LightCol;
					//Env
					float3 EnvRef	= texCUBElod(_CubeMap,float4(vrDirWS,(60-_Gloss)/60*8))*_EnvInt;
					//MIX
					float3 specCol	= lerp(PCol,BPCol,_specswitch);
					half3  finalCol	= dirDiff+specCol+EnvRef;
				//返回值
                return float4(EnvRef,0.0);
            }	//fragment shader
            ENDCG
        }
    }
    FallBack "Diffuse"
}

猜你喜欢

转载自blog.csdn.net/qq_15972907/article/details/120387091
TA