Unity Shader编程入门与实战案例解析

Unity Shader编程是游戏开发中不可或缺的一部分,它能够显著增强游戏画面的表现力。Shader作为图形渲染的核心,通过编写Shader代码,可以实现各种复杂的材质效果和光影效果。本文将带领读者从入门到实战,深入解析Unity Shader编程。

Unity Shader编程基础

在Unity中,Shader主要分为两类:表面着色器(Surface Shaders)和顶点/片段着色器(Vertex/Fragment Shaders)。表面着色器是一种高级抽象,通过简单的语法即可实现复杂的渲染效果;而顶点/片段着色器则提供了更底层的控制,适合实现自定义渲染逻辑。

表面着色器

表面着色器主要使用HLSL(高级着色语言)编写,通过定义一些属性如光照模型、颜色、法线等,Unity会自动生成相应的顶点/片段着色器代码。以下是一个简单的表面着色器示例:

Shader "Custom/SimpleSurfaceShader" { Properties { _Color ("Color", Color) = (1,1,1,1) _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; sampler2D _BumpMap; half4 _Color; half _Glossiness; half _Metallic; struct Input { float2 uv_MainTex; float2 uv_BumpMap; }; // Adding a second light source void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and glossiness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }

顶点/片段着色器

顶点/片段着色器提供了更灵活的渲染控制,适用于需要自定义渲染逻辑的场景。以下是一个简单的顶点/片段着色器示例:

Shader "Custom/SimplePassThroughShader" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata_t { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float3 normal : TEXCOORD0; }; v2f vert (appdata_t v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.normal = UnityObjectToWorldNormal(v.normal); return o; } fixed4 frag (v2f i) : SV_Target { // 返回一个简单的颜色值 return fixed4(i.normal * 0.5 + 0.5, 1.0); } ENDCG } } }

实战案例解析

案例一:实现简单的水波效果

通过顶点/片段着色器,可以实现一个简单的水波效果。以下是实现该效果的Shader代码:

Shader "Custom/WaterWaveShader" { Properties { _WaveSpeed ("Wave Speed", Float) = 1.0 _WaveHeight ("Wave Height", Float) = 0.1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; float _WaveSpeed; float _WaveHeight; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { float2 uv = IN.uv_MainTex; float wave = sin(_Time.y * _WaveSpeed + uv.x * 10.0) * _WaveHeight; uv.y += wave; fixed4 c = tex2D(_MainTex, uv); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }

案例二:实现卡通渲染效果

卡通渲染效果是游戏开发中常用的一种渲染风格,通过调整光照模型和颜色,可以实现简洁明快的画面效果。以下是实现该效果的Shader代码:

Shader "Custom/ToonShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.02 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float3 normal : TEXCOORD0; }; sampler2D _MainTex; float4 _OutlineColor; float _OutlineWidth; v2f vert (appdata_t v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.normal = UnityObjectToWorldNormal(v.normal); return o; } fixed4 frag (v2f i) : SV_Target { // 计算轮廓线 float3 viewDir = normalize(WorldSpaceViewDir(i.pos)); float outline = step(_OutlineWidth, abs(dot(i.normal, viewDir))); // 采样纹理颜色 fixed4 col = tex2D(_MainTex, i.pos.xy / i.pos.w); // 应用轮廓线颜色 col = lerp(col, _OutlineColor, outline); // 应用卡通渲染效果(简单色调分离) float3 toneMapped = step(0.5, col.rgb) * fixed3(1, 0.7, 0.5); return fixed4(toneMapped, col.a); } ENDCG } } FallBack "Diffuse" }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485