在Unity3D中,渲染路徑(Rendering Paths)和光照模式(LightMode)是決定場景如何渲染和光照如何計算的關鍵因素。理解這些概念對于優化渲染性能、實現特定視覺效果至關重要。本文將深入探討Unity3D中的Rendering Paths和LightMode,并通過示例分析它們在實際項目中的應用。
Rendering Paths決定了Unity如何計算和渲染光照。Unity支持多種渲染路徑,每種路徑都有其特定的優勢和適用場景。
Forward Rendering(前向渲染)是Unity中最常用的渲染路徑之一。它逐像素計算光照,適用于大多數場景,尤其是移動設備和低端硬件。
特點: - 逐像素光照計算 - 支持多種光源類型 - 適用于移動設備和低端硬件
適用場景: - 移動游戲 - 低端硬件 - 需要實時動態光照的場景
Deferred Rendering(延遲渲染)是一種更復雜的渲染路徑,適用于需要處理大量光源的場景。它將光照計算延遲到幾何渲染之后,通過G-Buffer存儲幾何信息。
特點: - 延遲光照計算 - 支持大量光源 - 需要較高的硬件性能
適用場景: - 高端PC游戲 - 需要大量動態光源的場景 - 復雜的光照效果
Legacy Deferred Lighting(傳統延遲光照)是Unity早期版本的延遲渲染路徑,現已不推薦使用。它使用不同的G-Buffer格式和光照計算方式。
特點: - 舊版延遲渲染 - 不推薦使用 - 兼容性較差
適用場景: - 舊版Unity項目 - 需要兼容舊版硬件的場景
Legacy Vertex Lit(傳統頂點光照)是Unity早期版本的頂點光照渲染路徑,現已不推薦使用。它逐頂點計算光照,適用于低端硬件。
特點: - 逐頂點光照計算 - 不推薦使用 - 兼容性較差
適用場景: - 舊版Unity項目 - 需要兼容舊版硬件的場景
LightMode是Shader中的一個標簽,用于指定Shader在特定渲染路徑下的行為。不同的LightMode決定了Shader如何處理光照和陰影。
Always
模式表示Shader在所有渲染路徑下都會執行,不受光照影響。
適用場景: - 不需要光照的Shader - 全屏特效 - UI元素
ForwardBase
模式用于Forward Rendering中的基礎通道,處理環境光和主方向光。
適用場景: - Forward Rendering中的基礎光照 - 環境光和主方向光
ForwardAdd
模式用于Forward Rendering中的附加通道,處理額外的逐像素光源。
適用場景: - Forward Rendering中的附加光源 - 逐像素光源
Deferred
模式用于Deferred Rendering中的幾何通道,將幾何信息寫入G-Buffer。
適用場景: - Deferred Rendering中的幾何通道 - G-Buffer寫入
ShadowCaster
模式用于生成陰影貼圖,計算物體的陰影。
適用場景: - 陰影生成 - 陰影貼圖計算
PrepassBase
模式用于Legacy Deferred Lighting中的基礎通道,處理環境光和主方向光。
適用場景: - Legacy Deferred Lighting中的基礎光照 - 環境光和主方向光
PrepassFinal
模式用于Legacy Deferred Lighting中的最終通道,計算最終光照。
適用場景: - Legacy Deferred Lighting中的最終光照 - 最終光照計算
Vertex
模式用于Legacy Vertex Lit中的頂點光照計算。
適用場景: - Legacy Vertex Lit中的頂點光照 - 頂點光照計算
VertexLMRGBM
模式用于Legacy Vertex Lit中的頂點光照計算,使用RGBM編碼。
適用場景: - Legacy Vertex Lit中的頂點光照 - RGBM編碼
VertexLM
模式用于Legacy Vertex Lit中的頂點光照計算,使用LDR編碼。
適用場景: - Legacy Vertex Lit中的頂點光照 - LDR編碼
Rendering Paths和LightMode密切相關,不同的渲染路徑決定了Shader中LightMode的行為。例如,在Forward Rendering中,ForwardBase
和ForwardAdd
模式分別處理基礎光照和附加光源;而在Deferred Rendering中,Deferred
模式負責將幾何信息寫入G-Buffer。
在Forward Rendering中,ForwardBase
模式處理環境光和主方向光,ForwardAdd
模式處理附加光源。以下是一個簡單的Forward Rendering Shader示例:
Shader "Custom/ForwardRenderingExample" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(0, dot(worldNormal, lightDir));
fixed4 finalColor = texcol * _Color * NdotL;
return finalColor;
}
ENDCG
}
Pass {
Tags { "LightMode"="ForwardAdd" }
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(0, dot(worldNormal, lightDir));
fixed4 finalColor = texcol * _Color * NdotL;
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
在Deferred Rendering中,Deferred
模式負責將幾何信息寫入G-Buffer。以下是一個簡單的Deferred Rendering Shader示例:
Shader "Custom/DeferredRenderingExample" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
Tags { "LightMode"="Deferred" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
void frag (v2f i, out half4 outDiffuse : SV_Target0, out half4 outSpecular : SV_Target1, out half4 outNormal : SV_Target2, out half4 outEmission : SV_Target3) {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
outDiffuse = texcol * _Color;
outSpecular = fixed4(0, 0, 0, 0);
outNormal = fixed4(worldNormal * 0.5 + 0.5, 1);
outEmission = fixed4(0, 0, 0, 0);
}
ENDCG
}
}
FallBack "Diffuse"
}
在Legacy Deferred Lighting中,PrepassBase
和PrepassFinal
模式分別處理基礎光照和最終光照。以下是一個簡單的Legacy Deferred Lighting Shader示例:
Shader "Custom/LegacyDeferredLightingExample" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
Tags { "LightMode"="PrepassBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(0, dot(worldNormal, lightDir));
fixed4 finalColor = texcol * _Color * NdotL;
return finalColor;
}
ENDCG
}
Pass {
Tags { "LightMode"="PrepassFinal" }
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(0, dot(worldNormal, lightDir));
fixed4 finalColor = texcol * _Color * NdotL;
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
在Legacy Vertex Lit中,Vertex
模式用于逐頂點光照計算。以下是一個簡單的Legacy Vertex Lit Shader示例:
Shader "Custom/LegacyVertexLitExample" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
Tags { "LightMode"="Vertex" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
float3 worldNormal = normalize(i.worldNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(0, dot(worldNormal, lightDir));
fixed4 finalColor = texcol * _Color * NdotL;
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
Unity3D中的Rendering Paths和LightMode是決定場景渲染和光照計算的關鍵因素。通過理解這些概念,開發者可以更好地優化渲染性能,實現特定的視覺效果。本文詳細介紹了Unity3D中的各種Rendering Paths和LightMode,并通過示例展示了它們在實際項目中的應用。希望本文能為Unity開發者提供有價值的參考,幫助他們在項目中更好地應用這些技術。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。