【URP】Shader绘制棋盘格对比内置管线
以绘制棋盘格为例,对比内置管线和URP中的Shader异同。
【从UnityURP开始探索游戏渲染】
专栏-直达
异同简述
- 面板属性定义Properties一样的
- Tags主要区别在于RenderPipeline的声明
- 这里没涉及到的渲染命令也是一样的。
- 主要区别在Pass中使用CG还是HLSL
- 其中引用的内置变量的库不同,内置引用UnityCG.cginc,而URP中引用URP包中的core.hlsl
- 再有HLSL中定义变量 用静态缓冲宏定义包裹 ,CBUFFER_START(UnityPerMaterial),CBUFFER_END。内置中直接定义变量。
内置渲染管线与URP的基本概念对比
内置渲染管线(Built-in Render Pipeline)
- Unity的默认渲染管线,采用固定架构设计
- 基于传统的前向渲染和延迟渲染模式,代码高度耦合
- 自定义选项有限,修改渲染流程需直接修改Unity源码
- 使用CG语言编写Shader,支持Standard Shader等内置着色器
通用渲染管线(URP)
- 基于可编程渲染管线(SRP)框架的模块化设计
- 核心逻辑通过C#脚本控制,如RenderPipeline和RenderPass
- 轻量且可扩展,专注于跨平台性能优化
- 使用HLSL语言编写Shader,支持Shader Graph可视化编辑
Shader的具体差异对比
对比维度 | 内置渲染管线 | URP |
---|---|---|
编程语言 | 主要使用CG | 主要使用HLSL |
SubShader标签 | 无特殊要求 | 需添加"RenderPipeline"="UniversalPipeline" |
光照处理 | 内置光照模型 | 基于物理渲染(PBS)系统 |
合批流程 | 传统合批 | 支持SRP Batcher |
数据类型 | 支持fixed类型 | 仅支持half/float类型 |
着色器库 | UnityCG.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary |
后处理支持 | 有限支持 | 更强大的后处理系统 |
Shader迁移到URP的步骤
基础修改
- 在SubShader的Tags中添加
"RenderPipeline"="UniversalPipeline"
- 将
CGPROGRAM
/ENDCG
替换为HLSLPROGRAM
/ENDHLSL
- 替换包含文件:
#include "UnityCG.cginc"
→#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
数据类型和函数调整
- 将
fixed
类型改为half
或float
- 更新光照计算函数,使用URP提供的API
- 将属性定义在
CBUFFER_START(UnityPerMaterial)
块中以提高兼容性
使用迁移工具
- Unity官方提供Render Pipeline Converter工具
- 可自动转换大部分标准Shader
- 对于自定义Shader,需要手动调整
验证和优化
- 检查材质在URP下的渲染效果
- 优化性能,利用URP特性如SRP Batcher
- 测试不同平台的表现
迁移注意事项
不兼容功能处理
- 某些高级特效(如曲面细分)在URP中可能不支持
- 需要寻找替代方案或使用HDRP
性能优化
- URP更注重移动端性能,可减少不必要的计算
- 使用URP的批处理功能提高渲染效率
棋盘格Shader实现
内置Checkerboard.shader
Shader "Custom/Checkerboard" { Properties { _GridSize ("Grid Size", Range(1, 100)) = 10 _Color1 ("Color 1", Color) = (1,1,1,1) _Color2 ("Color 2", Color) = (0,0,0,1) _HighlightColor ("Highlight Color", Color) = (1,0,0,1) _HighlightCoord ("Highlight Coordinate", Vector) = (0,0,0,0) } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; float _GridSize; fixed4 _Color1; fixed4 _Color2; fixed4 _HighlightColor; float2 _HighlightCoord; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv * _GridSize; return o; } fixed4 frag (v2f i) : SV_Target { float2 gridPos = floor(i.uv); float pattern = fmod(gridPos.x + gridPos.y, 2.0); // 检查是否是高亮坐标 if (gridPos.x == _HighlightCoord.x && gridPos.y == _HighlightCoord.y) { return _HighlightColor; } return pattern < 1.0 ? _Color1 : _Color2; } ENDCG } } }
URP Checkerboard.shader
Shader "Universal Render Pipeline/Checkerboard" { Properties { _GridSize("Grid Size", Float) = 10 _Color1("Color 1", Color) = (1,1,1,1) _Color2("Color 2", Color) = (0,0,0,1) _HighlightColor("Highlight Color", Color) = (1,0,0,1) _HighlightCoord("Highlight Coordinate", Vector) = (0,0,0,0) } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float2 uv : TEXCOORD0; float4 positionHCS : SV_POSITION; }; CBUFFER_START(UnityPerMaterial) float _GridSize; float4 _Color1; float4 _Color2; float4 _HighlightColor; float2 _HighlightCoord; CBUFFER_END Varyings vert(Attributes IN) { Varyings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.uv = IN.uv * _GridSize; return OUT; } half4 frag(Varyings IN) : SV_Target { float2 gridPos = floor(IN.uv); float pattern = fmod(gridPos.x + gridPos.y, 2.0); if (gridPos.x == _HighlightCoord.x && gridPos.y == _HighlightCoord.y) { return _HighlightColor; } return pattern < 1.0 ? _Color1 : _Color2; } ENDHLSL } } }
【从UnityURP开始探索游戏渲染】
专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)
登录
注册