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

Shader 学习 21:自定义 Render Feature

为什么有些效果一定要用feature实现?

  • 当效果需要在“相机渲染流程的某个时机”拿到或改写整张屏幕的渲染结果时。

    例如:

    • 全屏后处理:模糊、调色、描边、像素化、镜头特效

    • 依赖相机深度/法线的效果:SSAO、基于深度的雾、屏幕空间描边

    • 需要渲染一张额外全局纹理:角色遮罩、扭曲贴图、分层结果

    • 必须控制执行顺序:在不透明物体后、透明物体前,或最终画面之后执行

但“全局数据”不一定都需要 Feature。比如某个全局 Shader 参数、全局贴图,只要脚本用Shader.SetGlobal...设置即可;材质在绘制时自然能读到它。


框架实现

需要打通Camera → Feature → Pass → Shader → GPU这条链路

ScriptableRendererFeature这个类的核心函数是:CreateAddRenderPasses负责feature自己的构造函数,以及将某些自定义pass加入到渲染队列中

  • Create:同步new一个Pass,并把feature的配置数据给它

  • AddRenderPasses:将Pass加入队列

既然要new pass与配置,就需要在该Feature中,创建两个SettingsScriptableRenderPass

  • Settings:这个配置内容会显示在 UniversalRenderData 的 Inspector 的对应 feature 上

  • ScriptableRenderPass:要有自己的构造函数,以及执行内容

    • Execute:写 CommandBuffer

using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace MiniRenderer.Rendering { public class FullscreenTintRendererFeature : ScriptableRendererFeature { // 1. // 会显示在 Renderer Feature 的 Inspector 中,供你调参。 // 这里只是声明了一个 Serializable 的类,真正让这个Feature有该序列化数据,还需要下面new一个 [System.Serializable] public class Settings { public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents; public Color tintColor = Color.cyan; [Range(0f, 1f)] public float intensity = 0.2f; } [SerializeField] private Settings settings = new Settings(); // 2. // 这是该feature持有的一个pass // 这个类将来会录制“全屏滤镜”的 GPU 命令。 // 这个pass会做什么,都写在Execute中 private class TintPass : ScriptableRenderPass { private readonly Settings settings; public TintPass(Settings settings) { this.settings = settings; } public override void Execute( ScriptableRenderContext context, ref RenderingData renderingData) { // 在这里写 CommandBuffer。 } } // 3. // feature调度pass加到渲染队列中 private TintPass tintPass; public override void Create() { // Feature 负责注册;真正干活的是 Pass。 // 所以在feature的构造函数中,用我们的配置setting,new一个要干活的Pass tintPass = new TintPass(settings) // 存下来,不用每帧创建 { // 把 Inspector 选的渲染时机交给 URP。 renderPassEvent = settings.renderPassEvent }; } public override void AddRenderPasses( ScriptableRenderer renderer, ref RenderingData renderingData) { // 每次相机渲染时,把 Pass 加进 URP 队列。 renderer.EnqueuePass(tintPass); } } }

临时 Render Target 的必要性

必要性在于:读取相机颜色 A → 处理 → 立刻写回同一张 A的操作,如果GPU同时读写同一张纹理 不安全,结果可能不确定,所以正确的行为是要“乒乓”一次:

相机颜色 A → 临时纹理 B → 处理后的结果写回 A

// 1. 创建一张与来源画面兼容的临时纹理 B。 var temporary = AllocateCompatibleTarget(source); // 2. 第一次 Blit:把来源画面 A 复制到 B。 cmd.Blit(source, temporary); // 3. 第二次 Blit:读取 B,执行材质/Shader,并写入管线指定的输出目标。 cmd.Blit(temporary, destination, material); // 4. 释放 B。 Release(temporary);
  • commandBuffer.Blit(src, dest, mat, pass)

URP框架提供的封装写法

在 URP 的ScriptableRenderPass中,如果不需要手动管理临时 RT,可以调用它提供的Blit封装。传入效果材质后,URP 会在内部选择相机颜色的前后 Buffer,并在渲染完成后交换它们。

这行代码的内部逻辑仍是“读取当前颜色 Buffer → 写入另一颜色 Buffer → 交换 Buffer”。区别是临时 Buffer 的选择、写入目标和交换操作都由 URP 管理,因此不需要手动创建和释放临时 RT。

// 注意:这是 ScriptableRenderPass 的 Blit, // 不是 commandBuffer.Blit。 Blit(commandBuffer, ref renderingData, tintMaterial);

http://www.jsqmd.com/news/1319002/

相关文章:

  • agent学习——基础概念2
  • C#进制转换原理与实现详解
  • 【微科普】根除全部衰老疾病就能永生?npj Aging 2026建模解读:人类中位理论寿命156年,极限不超过557年
  • NVIDIA Profile Inspector中文界面实战:3步深度解锁显卡隐藏性能
  • 从《超星神》水瓶赛沙吃瘪看战斗系统设计与角色成长逻辑
  • 基于Wio Terminal的物联网数据看板:从API获取到屏幕显示的完整实践
  • WINDLX流水线实验:深入理解数据冒险与转发机制优化
  • 2027届开题季必读:计算机毕业设计选题避坑指南与高分选题推荐
  • 专业电动门厂家怎么选?3大核心优势+避坑技巧
  • 评委评分都可以用哪些评分设备?盘点高端评分系统能支持的硬件
  • 2026年 苏州数控机床厂家推荐榜单:CNC加工中心,钻攻机床,精密机械机床,汽车零部件制造设备源头工厂优选 - 优企名品
  • Presto 查询引擎内核详解:基于多级反馈队列思想的 Worker 调度模型
  • Spring Boot集成Druid连接池配置失效排查与解决方案
  • 鸿蒙物理 108 篇 第一百零五篇 高阶物象超变机制
  • 从硬编码到配置化:可配置按钮系统的设计与工程实践
  • 零基础接入名人名言 API:POST 请求、参数说明与返回结构全解析
  • RAG 文档切分(Chunking)策略与实现细节 —— 全网技术汇总
  • AI一站式平台如何重塑游戏开发流程:从概念到实战
  • SpringBoot+Vue学生求职系统开发实践
  • LangGraph实战:让Agent从脚本变成生产级可控系统
  • GEO软件哪个好到底怎么选?头部GEO机构硬核实测横评与企业选型避坑指南 - 趣闻早乐评
  • Python爬虫进阶:结合JS逆向与AI技术破解数据采集难题
  • 如何实现智能文档文字识别:AnythingLLM OCR功能的完整指南
  • Minecraft 1.8.9轻量化UI模组开发:Vibe Coding实践指南
  • 如何一键搞定60多种语言的字幕下载难题?OpenSubtitlesDownload实战指南
  • NVIDIA Profile Inspector终极指南:解锁显卡隐藏设置,优化游戏性能
  • 2026年南宁美术培训大揭秘,究竟哪家技术实力更胜一筹?
  • 阿里后端实习面试:从八股文到系统设计的深度工程实践
  • 如何在绝对标准的C编译器和系统(比如DOS)写出无阻塞输入
  • Godot引擎GDScript反编译实战:从PCK/APK恢复源码的完整指南