当前位置: 首页 > news >正文

Unity Shader 入门教程:从零开始编写你的第一个 Shader

引言

光照模型是 Shader 编程的核心部分,它决定了物体表面如何与光线交互,从而影响最终的视觉效果。在 Unity 中,常见的光照模型包括 Lambert 漫反射模型Phong 高光反射模型Blinn-Phong 模型
本文将详细介绍这些光照模型的原理,并展示如何在 Unity Shader 中实现它们。


1. Lambert 光照模型

1.1 基本原理

Lambert 光照模型是最基础的漫反射模型,基于 Lambert 余弦定律,模拟光线在粗糙表面的均匀散射效果。其核心公式为:
$$
I = I_0 \cdot \cos(\theta)
$$
其中:

  • $I$ 是反射光强度。
  • $I_0$ 是入射光强度。
  • $\theta$ 是光线入射方向与表面法线方向的夹角。

1.2 Unity Shader 实现

以下是 Lambert 光照模型的实现代码:

Shader "LightModel/LambertShader"
{Properties{_MainTex("Texture", 2D) = "white" {}_Color("Color", Color) = (1,1,1,1)}SubShader{Tags { "RenderType" = "Opaque" }LOD 200Pass{CGPROGRAM#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;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;float4 _Color;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);  // 顶点变换o.worldNormal = UnityObjectToWorldNormal(v.normal);  // 法线变换o.uv = TRANSFORM_TEX(v.uv, _MainTex);  // 纹理坐标变换return o;}fixed4 frag(v2f i) : SV_Target{float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 光源方向float3 normal = normalize(i.worldNormal);  // 法线方向float diff = max(dot(normal, lightDir), 0);  // 漫反射强度fixed4 col = tex2D(_MainTex, i.uv) * _Color * diff;  // 最终颜色return col;}ENDCG}}FallBack "Diffuse"
}

Lambert模型实现效果如图:
在这里插入图片描述


2. Phong 光照模型

2.1 基本原理

Phong 光照模型在 Lambert 模型的基础上增加了 高光反射,模拟光线在光滑表面的镜面反射效果。其核心公式为:
$$
I = I_{\text{diffuse}} + I_{\text{specular}}
$$
其中:

  • $I_{\text{diffuse}}$ 是漫反射强度(Lambert 模型)。
  • $I_{\text{specular}}$ 是高光反射强度,计算公式为:
    $$
    I_{\text{specular}} = I_0 \cdot (\mathbf{R} \cdot \mathbf{V})^n
    $$
  • $\mathbf{R}$ 是反射方向。
  • $\mathbf{V}$ 是视线方向。
  • $n$ 是高光指数,控制高光的集中程度。

2.2 Unity Shader 实现

以下是 Phong 光照模型的实现代码:

Shader "LightModel/PhongShader"
{Properties{_MainTex ("Texture", 2D) = "white" {}_Color("Color", Color) = (1,1,1,1)_SpecularColor("Specular Color", Color) = (1,1,1,1)  // 高光颜色_Gloss("Gloss", Range(1, 256)) = 32   // 高光指数(控制高光集中程度}SubShader{Tags { "RenderType"="Opaque" }LOD 200Pass{CGPROGRAM#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;};sampler2D _MainTex;float4 _MainTex_ST;float4 _Color;float4 _SpecularColor;float _Gloss;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);  // 法线变换o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  // 顶点变换到世界空间o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 光源方向float3 normal = normalize(i.worldNormal);              // 法线方向float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);  // 视线方向float3 reflectDir = reflect(-lightDir, normal);        // 反射方向float diff = max(dot(normal, lightDir), 0);            // 漫反射强度float spec = pow(max(dot(reflectDir, viewDir), 0), _Gloss);  // 高光强度fixed4 texColor = tex2D(_MainTex, i.uv); // 纹理颜色fixed4 col = texColor * _Color * diff + spec;  // 最终颜色return col;}ENDCG}}
}

Phong模型实现效果如图:
在这里插入图片描述


3. Blinn-Phong 光照模型

3.1 基本原理

Blinn-Phong 模型是 Phong 模型的改进版,通过引入 半角向量 简化了高光反射的计算。其核心公式为:
$$
I = I_{\text{diffuse}} + I_{\text{specular}}
$$
其中:

  • $I_{\text{specular}}$ 的计算公式为:
    $$
    I_{\text{specular}} = I_0 \cdot (\mathbf{N} \cdot \mathbf{H})^n
    $$
  • $\mathbf{H}$ 是半角向量,计算公式为:
    $$
    \mathbf{H} = \frac{\mathbf{L} + \mathbf{V}}{|\mathbf{L} + \mathbf{V}|}
    $$

# 3.2 Unity Shader 实现

以下是 Blinn-Phong 光照模型的实现代码:

Shader "LightModel/BlinnPhongShader"
{Properties{_MainTex("Texture", 2D) = "white" {}_Color("Color", Color) = (1,1,1,1)_SpecularColor("Specular Color", Color) = (1,1,1,1)  // 高光颜色_Gloss("Gloss", Range(1, 256)) = 32   // 高光指数(控制高光集中程度}SubShader{Tags { "RenderType" = "Opaque" }LOD 200Pass{CGPROGRAM#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;};sampler2D _MainTex;float4 _MainTex_ST;float4 _Color;float4 _SpecularColor;float _Gloss;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);  // 法线变换o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  // 顶点变换到世界空间o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag(v2f i) : SV_Target{float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 光源方向float3 normal = normalize(i.worldNormal);              // 法线方向float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);  // 视线方向float3 halfDir = normalize(lightDir + viewDir);        // 半角向量float diff = max(dot(normal, lightDir), 0);            // 漫反射强度float spec = pow(max(dot(normal, halfDir), 0), _Gloss);  // 高光强度fixed4 texColor = tex2D(_MainTex, i.uv); // 纹理颜色fixed4 col = texColor * _Color * diff + spec;  // 最终颜色return col;}ENDCG}}
}

Blinn-Phong模型实现效果如图:
在这里插入图片描述


4. 光照模型的对比与选择

4.1 对比

  • Lambert 模型:简单高效,适合粗糙表面,但缺乏高光反射。
  • Phong 模型:增加了高光反射,适合光滑表面,但计算量较大。
  • Blinn-Phong 模型:高光计算更高效,适合大多数场景。

4.2 选择建议

  • 如果需要快速实现基础光照效果,选择 Lambert 模型
  • 如果需要表现光滑表面的高光效果,选择 Phong 模型Blinn-Phong 模型
  • 在性能要求较高的场景中,优先选择 Blinn-Phong 模型

http://www.zskr.cn/news/42796.html

相关文章:

  • 实用指南:Linux内核架构浅谈2- Linux内核与硬件交互的底层逻辑:硬件抽象层的作用
  • 英伟达DCGM说明和安装
  • 阿卡德付费文章:让每个普通人的知识,都能变成真金白银
  • Mysql杂志(三十)——索引失效情况 - 指南
  • 84用python命令查看安装了那些库
  • 手把手教你在unity中实现一个视觉小说系统(一)
  • 2025 东莞外贸独立站公司最新推荐榜:全链路服务商测评解析与优质品牌优选指南东莞/广州/深圳/佛山/中山/惠州外贸独立站运营公司推荐
  • 2025年深圳刑事辩护律师权威推荐榜单:医疗纠纷案/婚姻家庭案/知识产权案法律服务专家精选
  • 2025年真空润滑脂厂家权威推荐榜单:无尘室润滑脂/位移平台润滑脂/电子显微镜润滑脂源头厂家精选
  • 2025年无火焰泄压阀厂家权威推荐榜单:无火焰泄爆装置/重复式无火焰泄爆装置/重复式无火焰泄爆阀源头厂家精选
  • CF1834E
  • 2025 年 11 月机制板厂家推荐排行榜,机制板,机制板厂家,机制板销售厂家,机制板公司推荐,专业品质与高效供应口碑之选
  • 2025年11月杜甫研究学者专家推荐榜:程韬光教授跨界传播实绩排行
  • 2025年11月固定资产管理系统评价榜:政企校医场景选型参考
  • CF53E Dead Ends 分析
  • 开源MQTT协议记录
  • P7620 Zero-XOR Array
  • 2025年11月专利申请公司推荐榜:五家对比解析与口碑盘点
  • 5641
  • 稳联技术Profinet转DeviceNet协议转换网关在丹弗斯变频器控制集成中的应用方案
  • 实用指南:(17)100天python从入门到拿捏《正则表达式》
  • RPM打包es
  • 2025年11月北京生殖咨询公司排行:美月国际咨询深度评测报告
  • 2025年11月中国短视频制作公司推荐榜:五强评测助你精准选型
  • 前端工程化中Less第三方库中@Import的“~”和“@”用法
  • B1. Reverse Card (Easy Version)
  • 2025年11月纯粮白酒品牌推荐榜:久久十强对比全析
  • 2025年11月销量第一证明机构权威榜:尚普与华信人深度对比评测
  • 前端设计模式 - 树对象结构与订阅发布者模式 Unity与Qt【极简版】
  • 2025年11月园区车辆管理系统推荐榜:五强对比评测与选型指南