TA不一样(十二)
前言渲染路径和光源决定了物体如何反应光照是一个比较重要的部分Unity的渲染路径Rending Path1.模式与定义Tags {LightModeValue}Always:无论使用哪种渲染路径该Pass总是会被渲染但不会计算任何光照。ForwardBase: 用于前向渲染。该Pass会计算环境光、最重要的平行光、逐顶点/SH光源和光照贴图(Lightmaps)。Deferred: 用于延迟渲染。该Pass会渲染G-缓冲(G-buffer)。ShadowCaster: 将物体的深度信息渲染到阴影贴图(shadowmap)或者深度纹理中。MotionVectors:用于计算每个对象的运动矢量。PrepassBase:在旧版延迟渲染(legacy Deferred Lighting)中使用该Pass将渲染法线和高光反射的指数部分。PrepassFinal: 在旧版延迟渲染(legacy Deferred Lighting)中使用该Pass将通过组合纹理光照和自发光来渲染得到最后的颜色。Vertex: 当对象没有进行光照映射(lightmap)时在旧版顶点光照(legacy Vertex Litrendering)中使用;所有的顶点光都将被应用到。VerteXLMRGBM: 当对象被光照时在旧版顶点光照(legacy Vertex Lit rendering)中使用;在光照映射(lightmap)是RGBM编码(一般是PC和控制台场景中)时使用。VertexLM: 当对象被光照时在旧版顶点光照(legacy Vertex Lit rendering)中使用;在光照映射(lightmap)是双LDR编码(一般是移动平台场景中)时使用。2.前向渲染路径前向渲染路径有3种处理光照(即照亮物体)的方式而决定一个光源使用哪种处理模式取决于它的类型和渲染模式逐顶点处理逐像素处理球谐函数(Spherical Harmonics, SH)处理渲染一个物体时Unity 会对这些光源进行一个重要度排序场景中最亮的平行光总是按逐像素处理的渲染模式被设置成Not lmportant的光源会按逐顶点或者SH处理渲染模式被设置成lmportant的光源会按逐像素处理如果根据以上规则得到的逐像素光源数量小于QualitySetting中的逐像素光源数量(PixelLightCount)会有更多的光源以逐像素的方式进行渲染前向渲染的两种PassBase PassAdditional Pass3.顶点照明渲染路径是前向渲染路径的一个子集需要添加 Tags {LightModeVertex)float3_ShadeVertexLightsFull (float4 vertex, float3 normal, int lightCount, bool spotLight)4.延迟渲染路径延迟渲染主要包含了两个Pass不进行任何光照计算而是仅仅计算哪些片元是可见的利用G缓冲区的各个片元信息进行真正的光照计算延迟渲染的效率不依赖于场景的复杂度而是和屏幕空间的大小有关延迟渲染的缺点不支持真正的抗锯齿(anti-aliasing)功能不能处理半透明物体对显卡有一定要求。如果要使用延迟渲染的话显卡必须支持MRT(MultipleRenderTargets)、Shader Mode 3.0及以上、深度渲染纹理以及双面的模板缓冲5.代码实现Shader MyCustom/Forward { Properties { _MainTex (Texture, 2D) white {} _Diffuse (_Diffuse, Color) (0.5, 0.5, 0.5, 1) _SpecularPower (_SpecularPower, Range(0, 150)) 20 _SpecularIntensity (_SpecularIntensity, Range(0, 10)) 1.5 } SubShader { CGINCLUDE float _specular(float3 viewDir, float3 lightDir, float3 normal, float power, float intensity) { float3 _viewDir normalize(viewDir); float3 _lightDir normalize(lightDir); float3 _normal normalize(normal); float3 halfVector normalize(_lightDir _viewDir); float hdotn max(0, dot(halfVector, _normal)); float specular pow(hdotn, power) * intensity; return specular; } ENDCG Tags { RenderTypeOpaque } LOD 100 Pass { // ForwardBase采用主要平行光的影响 Tags {LightModeForwardBase} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include UnityCG.cginc #include Lighting.cginc #include AutoLight.cginc struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldPos : TEXCOORD2; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Diffuse; float _SpecularPower; float _SpecularIntensity; v2f vert (appdata v) { v2f o; o.vertex UnityObjectToClipPos(v.vertex); o.uv TRANSFORM_TEX(v.uv, _MainTex); o.worldNormal UnityObjectToWorldNormal(v.normal); o.worldPos mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag (v2f i) : SV_Target { // 高光 float3 lightDir UnityWorldSpaceLightDir(i.worldPos); float3 viewDir UnityWorldSpaceViewDir(i.worldPos); float3 specular _LightColor0.rgb * _specular(viewDir, lightDir, i.worldNormal, _SpecularPower, _SpecularIntensity); // 环境光 float3 ambient UNITY_LIGHTMODEL_AMBIENT.xyz; // 漫反射 float3 diffuse _LightColor0.rgb * _Diffuse.rgb * max(0, dot(i.worldNormal, lightDir)); // 衰减 float atten 1.0; float4 finalColor 1; finalColor.rgb ambient (diffuse specular) * atten; return finalColor; } ENDCG } Pass { // ForwardAdd采用额外逐像素光源的影响 Tags {LightModeForwardAdd} Blend One One CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdadd #include UnityCG.cginc #include Lighting.cginc #include AutoLight.cginc struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldPos : TEXCOORD2; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Diffuse; float _SpecularPower; float _SpecularIntensity; v2f vert (appdata v) { v2f o; o.vertex UnityObjectToClipPos(v.vertex); o.uv TRANSFORM_TEX(v.uv, _MainTex); o.worldNormal UnityObjectToWorldNormal(v.normal); o.worldPos mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag (v2f i) : SV_Target { // 高光 float3 lightDir UnityWorldSpaceLightDir(i.worldPos); float3 viewDir UnityWorldSpaceViewDir(i.worldPos); float3 specular _LightColor0.rgb * _specular(viewDir, lightDir, i.worldNormal, _SpecularPower, _SpecularIntensity); // 漫反射 float3 diffuse _LightColor0.rgb * _Diffuse.rgb * max(0, dot(i.worldNormal, lightDir)); // 衰减 float atten 1.0; #if defined (POINT) // 1. 把世界空间坐标系下的顶点变换到当前的光源空间 float3 lightCoord mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz; // 2. 使用这个坐标的模的平方来采样从而得到衰减值 // (0, 0) 表示与光源位置重合(1, 1)表示距离光源最远 // UNITY_ATTEN_CHANNEL用来得到衰减纹理中衰减值所在的分量 atten tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL; #endif float4 finalColor 1; finalColor.rgb (diffuse specular) * atten; return finalColor; } ENDCG } } }Shader MyCustom/DeferredGBuffer { Properties { _MainTex (Texture, 2D) white {} _Diffuse (_Diffuse, Color) (0.5, 0.5, 0.5, 1) _Specular (_Specular, Color) (1, 1, 1, 1) _SpecularPower (_SpecularPower, Range(0, 150)) 20 _SpecularIntensity (_SpecularIntensity, Range(0, 10)) 1.5 _Gloss (_Gloss, Range(0, 1)) 100 } SubShader { Tags { RenderTypeOpaque } LOD 100 Pass { Tags {LightModeDeferred} CGPROGRAM #pragma target 3.0 #pragma vertex vert #pragma fragment frag #include UnityCG.cginc struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldPos : TEXCOORD2; float4 vertex : SV_POSITION; }; // 延迟渲染输出的数据结构需要输出4个Target struct deferredOutput { // rgb存储的漫反射颜色a存储的遮罩 float4 gBuffer0 : SV_TARGET0; // rgb存储的高光反射颜色a存储的gloss float4 gBuffer1 : SV_TARGET1; // rbg存储的世界空间法线a没用 float4 gBuffer2 : SV_TARGET2; // 自发光lightmapreflection probe float4 gBuffer3 : SV_TARGET3; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Diffuse; float4 _Specular; float _SpecularPower; float _SpecularIntensity; float _Gloss; v2f vert (appdata v) { v2f o; o.vertex UnityObjectToClipPos(v.vertex); o.uv TRANSFORM_TEX(v.uv, _MainTex); o.worldNormal UnityObjectToWorldNormal(v.normal); o.worldPos mul(unity_ObjectToWorld, v.vertex).xyz; return o; } deferredOutput frag (v2f i) { deferredOutput o; float3 color tex2D(_MainTex, i.uv).rgb * _Diffuse.rgb; o.gBuffer0.rgb color; o.gBuffer0.a 1; o.gBuffer1.rgb _Specular.rgb; o.gBuffer1.a _Gloss / 100; o.gBuffer2.rgb i.worldNormal * 0.5 0.5; o.gBuffer2.a 1; o.gBuffer3.rgb 0; o.gBuffer3.a 1; return o; } ENDCG } } }