- 在Unity URP渲染管线中,光栅化阶段的片元着色器(Fragment Shader)是决定像素最终颜色的核心环节。
【从UnityURP开始探索游戏渲染】专栏-直达
核心功能:
- 纹理采样:通过UV坐标从贴图获取颜色数据
- 光照计算:结合材质属性和光源信息计算逐像素光照
- 特效处理:实现透明度混合、边缘检测等后处理效果
可配置:
- 重写片元函数(#pragma fragment frag)。语义、纹理用途、
语义体系
输入结构体(v2f)语义
- SV_POSITION:裁剪空间顶点位置(必需),由顶点着色器输出
- TEXCOORD0-7:通用插值寄存器,存储UV坐标/自定义数据(如法线、视向量)
- COLOR0-1:顶点颜色通道,常用于渐变效果或数据传递
- NORMAL:世界空间法线向量(需手动计算后传递)
输出语义
- SV_Target:写入渲染目标(默认颜色缓冲)
- SV_Depth:自定义深度值输出(需显式启用)
TEXCOORD0-7和COLOR0-1语义的常用数据存储内容
语义常用存储数据典型应用场景TEXCOORD0主纹理UV坐标采样漫反射贴图(_MainTex)TEXCOORD1次要纹理UV坐标光照贴图、细节纹理叠加TEXCOORD2世界空间法线向量法线贴图计算、光照模型处理TEXCOORD3世界空间切线向量切线空间转换、法线映射TEXCOORD4世界空间视线方向高光反射计算、视差效果TEXCOORD5世界空间顶点位置动态雾效、距离衰减计算TEXCOORD6-7自定义数据或额外UV集顶点动画参数、流动贴图、多纹理混合COLOR0顶点颜色主通道顶点着色效果、渐变色处理(如植被/地形)COLOR1顶点颜色辅助通道特殊效果遮罩、动态参数传递(如溶解阈值)关键说明:
- 数据复用性
TEXCOORD语义本质上是通用插值寄存器,实际用途根据Shader需求动态分配4。例如简单着色器可能仅用TEXCOORD0,而复杂PBR材质会占用更多通道。
- 优化建议
URP推荐将关联数据打包到同一寄存器(如法线/切线共用TEXCOORD2-3),减少插值计算开销。
- 通道限制
移动端平台最多支持8个TEXCOORD和2个COLOR通道,超限需通过数据压缩或纹理烘焙解决
内容映射表
核心纹理变量
纹理变量名来源类/脚本用途说明_MainTexMaterial属性面板基础颜色/Albedo贴图(通过[MainTexture]特性标记)_BaseMapURP Shader内置变量替代_MainTex的标准化命名(URP 7.0+版本推荐使用)_NormalMapStandard Shader/自定义Shader切线空间法线贴图(需配合BUMP关键字启用)_MetallicGlossMapPBR材质系统金属度(R)和光滑度(A)通道存储_EmissionMapMaterial发光属性自发光纹理(需启用_EMISSION关键字)特殊功能纹理
纹理变量名来源类/脚本用途说明_OcclusionMap光照探针系统环境光遮蔽贴图(通常存储在G通道)_DetailAlbedoMap细节层材质表面微结构纹理(通过_DETAIL宏控制)_ParallaxMap高度图效果视差偏移贴图(需启用_PARALLAXMAP)_SpecGlossMap旧版高光工作流高光颜色(RGB)和光滑度(A)替代金属度贴图渲染管线专用纹理
纹理变量名来源类/脚本用途说明_CameraColorTextureURP RendererFeature相机颜色缓冲(后处理输入)_CameraDepthTextureURP DepthTexture模式场景深度图(需在URP Asset中启用)_ScreenSpaceOcclusionSSAO效果屏幕空间环境遮蔽图(通过SSAO Renderer Feature生成)脚本动态引用示例
- hlsl
- // C#脚本中通过Material类设置纹理
- material.SetTexture("_MainTex", Resources.Load<Texture2D>("Albedo"));
复制代码
- 该代码通过Material.SetTexture方法动态绑定纹理
- 纹理变量命名遵循URP核心库规范(Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl),其中WS后缀表示世界空间坐标,RWS为相机相对坐标。移动端需注意通过SAMPLER宏声明采样器以兼容GLES2.0平台
纹理数组高级应用
- Texture2DArray _TextureArray; // 声明纹理数组
- float _LayerIndex; // 动态切换纹理层
- fixed4 frag(v2f i) : SV_Target {
- return tex2DArray(_TextureArray, float3(i.uv, _LayerIndex));
- }
复制代码 该技术适用于地形系统(不同区块材质切换)或角色换装系统
片元着色器中的导数信息
每次片元着色器处理片元时都独立处理单个片元,因此片元在处理时无法得到临近片元信息。
实际GPU在运行时并不是只运行一个片元着色器,而是将其2x2的一组片元块,同时运行4个片元着色器。 通过ddx和ddy(URP中可通过ddx/ddy函数获取屏幕空间导数)两个偏导函数求得临近片元的差值。(偏导函数时纹理mipmaps实现的基础)
作用:
- 边缘检测:通过颜色/深度突变识别物体轮廓
- Mipmap层级选择:动态调整纹理采样精度
- 屏幕空间特效:如SSAO、运动模糊等
URP中基于导数的边缘检测示例
- 使用HLSL标准导数函数ddx/ddy
- 通过颜色梯度检测边缘
- 可调节阈值控制边缘灵敏度
- 兼容URP渲染管线
- EdgeDetection.shader
- Shader "Custom/EdgeDetection" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- _EdgeColor ("Edge Color", Color) = (1,0,0,1)
- _Threshold ("Threshold", Range(0,1)) = 0.1
- }
- SubShader {
- Pass {
- HLSLPROGRAM
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
-
- TEXTURE2D(_MainTex);
- SAMPLER(sampler_MainTex);
- float4 _EdgeColor;
- float _Threshold;
- struct v2f {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- };
- v2f vert(Attributes v) {
- v2f o;
- o.pos = TransformObjectToHClip(v.positionOS);
- o.uv = v.uv;
- return o;
- }
- half4 frag(v2f i) : SV_Target {
- half3 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv).rgb;
-
- // 计算屏幕空间导数
- half3 dx = ddx(col);
- half3 dy = ddy(col);
- float edge = sqrt(dot(dx,dx) + dot(dy,dy));
-
- // 边缘检测
- edge = step(_Threshold, edge);
- return lerp(float4(col,1), _EdgeColor, edge);
- }
- ENDHLSL
- }
- }
- }
复制代码 在延迟渲染中,片元着色器会利用G缓冲中的深度/法线信息进行更精确的光照计算,而前向渲染则直接在每个Pass中处理光照(内置管线每个pass处理灯光,URP中将所有灯光汇聚在一个Pass中处理)。URP通过优化后的着色器变体减少重复计算,提升多光源场景性能。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |