崔竹 发表于 5 天前

【URP】[投影Projector]解析与应用

Unity中的投影系统主要包括传统Projector组件和URP Decal Projector两种实现方式。
【从UnityURP开始探索游戏渲染】专栏-直达
发展历史与技术演进


[*]传统Projector组件:Unity早期内置的通用投影系统,通过摄像机空间矩阵计算实现材质投影,但存在性能开销大、与URP管线兼容性差的问题
[*]URP Decal Projector:自URP 12(Unity 2021)引入的专用贴花系统,采用延迟渲染路径和屏幕空间计算,性能优化显著
核心实现原理

传统Projector:


[*]继承自Behaviour的UnityEngine.Projector类实现
[*]基于视锥体裁剪和投影矩阵变换
[*]通过MaterialPropertyBlock动态修改着色器参数
URP Decal Projector:


[*]使用DecalRendererFeature扩展URP管线
[*]采用Deferred Decals技术,在GBuffer阶段后处理
[*]通过DecalProjector组件管理投影参数
[*]Projector组件的工作只是检测了所有范围内的模型,并传递了投影空间矩阵。
[*]投影着色器,用这个投影矩阵,左乘齐次裁剪空间的点,得到的坐标作为uv坐标传递给片元着色器。
[*]片元着色器中使用tex2Dproj(_MainTex, i.texc)获取实际纹理。这里的tex2Dproj实际上是将 $i.texc = i.texc/i.texc.w$ 透视除法
[*]tex2D(_MainTex, i.texc) 获取纹理文素
实际应用对比

传统Projector示例:

csharp
// 动态调整投影参数
Projector proj = GetComponent<Projector>();
proj.nearClipPlane = 0.5f;
proj.material.SetFloat("_Falloff", 0.8f);URP Decal Projector工作流:


[*]创建Decal Material:使用Shader Graphs/Decal着色器
[*]配置Decal Projector:调整Size/Depth等参数
[*]通过脚本动态生成:
csharp
// 在碰撞点生成弹孔
DecalProjector CreateBulletHole(Vector3 position) {
    GameObject decal = Instantiate(decalPrefab, position, Quaternion.LookRotation(-hit.normal));
    return decal.GetComponent<DecalProjector>();实践

典型应用场景:

URP Decal Projector基础配置

[*]环境准备:

[*]创建URP Asset并配置到Graphics Settings
[*]通过Package Manager安装Universal RP 12.1.6+版本

[*]核心组件添加:
csharp
// 添加Decal Renderer Feature
var renderer = URP资产中的Renderer数据;
renderer.AddFeature(new DecalRendererFeature());环境细节:墙面涂鸦、地面污渍(URP Decal)


[*]墙面涂鸦实现:

[*]创建Decal Material:使用Shader Graphs/Decal着色器,配置Albedo贴图为涂鸦图案
[*]调整Projector参数:Size=(2,2,0.5), Fade Factor=0.8
[*]层过滤:设置Affected Layers仅包含Wall层

[*]地面污渍效果:

[*]材质配置:混合Albedo(污渍贴图)和Normal Map(凹凸细节)
[*]投影参数:Depth=0.3, Angle Fade=(0.8,1.0)
[*]动态生成代码:
csharp
void CreateMudDecal(Vector3 position) {
    var decal = Instantiate(decalPrefab);
    decal.transform.position = position + Vector3.up*0.1f;
    decal.GetComponent<DecalProjector>().size =
      new Vector3(Random.Range(0.5f,1.5f), 0.2f, Random.Range(0.5f,1.5f));
}

动态效果:弹孔、血迹(两种方案均可)


[*]弹孔效果高级实现:

[*]预制体配置:包含Decal Projector和Particle System
[*]命中点生成逻辑:
csharp
void CreateBulletHole(RaycastHit hit) {
    var decal = Instantiate(bulletHolePrefab,
      hit.point + hit.normal*0.01f,
      Quaternion.LookRotation(-hit.normal));
    decal.transform.Rotate(Vector3.forward, Random.Range(0,360));
    Destroy(decal, 10f);// 10秒后自动消失
}

[*]血迹效果优化方案:

[*]材质混合:使用Multiply混合模式增强真实感
[*]动态渐隐控制:
csharp
IEnumerator FadeDecal(DecalProjector decal, float duration) {
    float startTime = Time.time;
    while(Time.time < startTime + duration) {
      float t = (Time.time - startTime) / duration;
      decal.fadeFactor = Mathf.Lerp(1, 0, t);
      yield return null;
    }
    Destroy(decal.gameObject);
}

[*]特殊光照:投影阴影(传统Projector)
性能优化:


[*]传统Projector:限制影响范围,使用简单材质
[*]URP Decal:

[*]启用Layer Mask过滤,控制Fade Distance
[*]批处理设置:对静态Decal启用Batching
[*]视锥体裁剪:调整Projector的Far Clip Plane避免过度绘制
[*]动态控制:非可见区域暂停Decal更新
[*]材质复用:相同类型效果共享材质实例
[*]实际项目建议采用分层管理系统,对不同类型Decal进行分类管理,例如:

[*]永久性Decal(涂鸦):使用单独Layer并启用Occlusion Culling
[*]临时性Decal(弹孔):使用对象池技术减少实例化开销
[*]环境Decal(污渍):烘焙到Lightmap中减少运行时消耗


参数配置要点:


[*]投影角度:通过旋转控制投影方向
[*]衰减控制:使用Falloff参数平滑边缘
[*]混合模式:Alpha Blend/Multiply选择
当前URP项目推荐优先使用Decal Projector系统,其性能表现和视觉效果更优,特别是在需要大量动态贴花的场景中。传统Projector仍适用于需要实时阴影投影等特殊需求场景.
【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 【URP】[投影Projector]解析与应用