后处理实现细节:从“整张画面“到“逐像素加工“的完整拆解
开场一个效果出来了但不懂原理的困惑小王照着教程加了个 Bloom效果是出来了但他心里没底“我知道后处理是’加工整张画面’……但具体是怎么加工的画面怎么就’交’给我的 Shader 了我的 Shader 又怎么’画’回屏幕那个Blit、_MainTex、全屏三角形……到底在干嘛”老鸟说“好问题只会调参数不算懂。今天把后处理从头到尾的实现链路拆给你看——你会发现它本质就是一次’画满屏幕的贴图操作’” 第一幕后处理的核心机制——Blit什么是 BlitBlit 把一张纹理,用某个Shader,画到另一张纹理上 这是后处理最核心的操作! ↓ 输入: 源纹理(当前画面) 处理: 一个后处理Shader 输出: 目标纹理(处理后的画面)Blit 的本质画一个铺满屏幕的矩形Blit具体在干嘛 1. 画一个铺满整个屏幕的矩形(全屏Quad) 2. 把源纹理当贴图贴上去 3. 用后处理Shader处理每个像素 4. 结果输出到目标纹理 ↓ 本质: 就是画一个贴了图的全屏矩形!生动比喻投影加滤镜Blit像把画面投到墙上,中间加片滤镜 源纹理(原画面) 幻灯片 后处理Shader 中间的滤镜片 目标纹理 墙(投出的结果) ↓ 光穿过滤镜,墙上就是处理后的画面 ↓ 画全屏矩形 让整面墙都被投到 第二幕全屏矩形是怎么来的后处理不需要普通的3D模型普通渲染: 顶点着色器处理3D模型的顶点 后处理: 只需要一个铺满屏幕的平面 不需要复杂模型! ↓ 就是屏幕大小的一个矩形(或三角形) 覆盖整个屏幕即可方式1全屏四边形(Quad)用2个三角形拼成一个矩形,盖满屏幕 (-1,1)────(1,1) │ ╲ │ │ ╲ │ │ ╲ │ (-1,-1)───(1,-1) ↓ 4个顶点,覆盖整个屏幕(NDC坐标-1到1)方式2全屏三角形(更优)⭐用1个超大三角形盖住屏幕(现代做法) (-1,3) │╲ │ ╲ │ ╲ (-1,-1)──(3,-1) ← 超出屏幕 ↓ 1个大三角形,超出屏幕的部分被裁掉 剩下正好盖满屏幕 ↓ 比四边形少1个顶点,还避免了 两个三角形交界处的重复计算 ↓ 现代引擎(URP)多用这个!生动理解为什么三角形更优四边形(2三角形): 中间对角线处 相邻像素可能被处理两次(边界重复) 大三角形(1个): 没有内部边界 每个像素只处理一次 ↓ 一个大三角形更高效! (这是个小而精妙的优化) 第三幕后处理 Shader 的结构顶点着色器几乎什么都不做后处理的顶点着色器超简单 v2f vert(appdata v) { v2f o; // 顶点已是屏幕空间,直接输出 o.pos v.vertex; // 传递UV(用来采样源纹理) o.uv v.uv; return o; } ↓ 不用做复杂的3D变换! 顶点就是全屏矩形的角片元着色器真正干活的地方每个像素运行一次,处理颜色 half4 frag(v2f i) : SV_Target { // 采样源纹理(当前画面的这个像素) half4 color tex2D(_MainTex, i.uv); // 在这里加工! (调色、模糊等) color.rgb * 1.2; // 例:提亮 return color; // 输出处理后的颜色 } ↓ _MainTex就是输入的画面 i.uv是当前像素在画面上的位置关键_MainTex 和 uv_MainTex: Blit时自动传入的源画面纹理 你要处理的那张画面 i.uv: 当前像素的纹理坐标(0~1) (0,0)左下角 (1,1)右上角 ↓ tex2D(_MainTex, i.uv) 取出画面上这个位置的原始颜色 ↓ 然后你对它做各种加工! 第四幕完整实现一个后处理调色最简单的后处理整体调色Shader PostProcess/ColorAdjust { Properties { _MainTex (Texture, 2D) white {} _Brightness (Brightness, Float) 1.0 _Saturation (Saturation, Float) 1.0 } SubShader { // 后处理不需要深度测试、剔除 Cull Off ZWrite Off ZTest Always 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 pos : SV_POSITION; }; sampler2D _MainTex; float _Brightness; float _Saturation; v2f vert(appdata v) { v2f o; o.pos UnityObjectToClipPos(v.vertex); o.uv v.uv; return o; } half4 frag(v2f i) : SV_Target { // 1. 采样原始画面 half4 color tex2D(_MainTex, i.uv); // 2. 亮度调整 color.rgb * _Brightness; // 3. 饱和度调整 half gray dot(color.rgb, half3(0.299, 0.587, 0.114)); color.rgb lerp(gray.xxx, color.rgb, _Saturation); return color; } ENDCG } } }关键点解读Cull Off ZWrite Off ZTest Always 后处理是全屏矩形,不需要: - 剔除(Cull Off) - 写深度(ZWrite Off) - 深度测试(ZTest Always,总是通过) ↓ 这几行是后处理Shader的标配! 采样 → 加工 → 输出 frag里的三步就是后处理核心逻辑️ 第五幕C# 端如何驱动后处理老式做法OnRenderImage// 内置管线的经典后处理入口publicclassPostEffect:MonoBehaviour{publicMaterialpostMaterial;// 系统会自动调用,src是当前画面voidOnRenderImage(RenderTexturesrc,RenderTexturedst){// 把src用postMaterial处理,输出到dstGraphics.Blit(src,dst,postMaterial);// ↑ 这就是那个核心Blit操作!}}OnRenderImage流程 src 场景渲染好的画面(自动传入) Blit(src, dst, mat) 用材质处理src→dst dst 最终显示的画面 ↓ 系统自动把dst显示到屏幕多个效果串联多次 BlitvoidOnRenderImage(RenderTexturesrc,RenderTexturedst){// 申请临时RT做中间结果RenderTexturetempRenderTexture.GetTemporary(src.width,src.height);// 第1个效果: src → tempGraphics.Blit(src,temp,blurMaterial);// 第2个效果: temp → dstGraphics.Blit(temp,dst,colorMaterial);// 释放临时RTRenderTexture.ReleaseTemporary(temp);}⚠️ 注意: 每个Blit都是一次RT切换! 多个效果 多次切换 移动端贵! (所以前面讲要合并效果)现代做法URP 的 Render FeatureURP用ScriptableRenderPass - 继承ScriptableRenderPass - 在Execute里用CommandBuffer.Blit - 通过Render Feature注入管线 ↓ 更灵活,能精确控制在管线哪个阶段插入 更好地管理RT和Load/Store ↓ 移动端优先用URP的方式! 第六幕进阶——Bloom 的完整实现逻辑Bloom 的多步流程Bloom(泛光)不是一次Blit能搞定的 1. 提取亮部(阈值) 只保留很亮的像素 2. 降分辨率 模糊(多次) 在小图上高斯模糊(省!) 3. 逐级模糊(金字塔) 多个分辨率级别模糊叠加 4. 合成回原图 模糊的亮部 原画面 ↓ 多步 多次Blit(要合理管理)Bloom 实现拆解详细步骤(每步一次Blit) 原图 ↓ 提取亮部Shader(降到1/2分辨率) 亮部图(小) ↓ 水平模糊Shader ↓ 垂直模糊Shader (高斯分两次做,更快) 模糊亮部 ↓ (可能逐级降采样再升采样) ↓ 合成Shader(原图 模糊亮部) 最终Bloom效果 ↓ 关键优化: 在低分辨率做模糊!高斯模糊分离优化✅ 二维高斯模糊 水平模糊 垂直模糊 ❌ 直接2D模糊: N×N次采样(如9×981次) ✅ 分离成两次1D: NN次(如9918次) ↓ 一个像素采样从81次降到18次! ↓ 这是模糊类后处理的关键优化生动理解分离模糊2D模糊像擦一个方形区域 要擦N×N个格子 分离模糊像先横擦一道,再竖擦一道 横擦N个 竖擦N个 两道横竖交叉,效果等价于方形! ↓ 从乘法变加法,省一大截! 第七幕后处理数据流全景图完整数据流【单个效果】 场景画面(RT) ↓ Blit(全屏三角形 后处理Shader) frag: 采样_MainTex → 加工 → 输出 处理后画面(RT) → 屏幕 【多个效果(未合并)】 场景 → Blit效果1 → RT1 → Blit效果2 → RT2 → 屏幕 (切换!) (切换!) ↓ 每次Blit都是RT切换,移动端贵! 【多个效果(合并优化)】 场景 → Blit(一个Uber Shader做完多效果) → 屏幕 (只切换一次!) ↓ 移动端推荐!关键概念串联Blit 用Shader把纹理画到纹理 全屏三角形 覆盖屏幕的绘制载体 _MainTex 输入的源画面 frag采样加工 逐像素处理逻辑 临时RT 中间结果存放 RT切换 每次Blit的隐藏开销(移动端痛) ↓ 理解这几个就理解了后处理实现!✅ 后处理实现理解检查清单核心机制 □ 明白Blit是用Shader把纹理画到纹理 □ 明白后处理是画全屏矩形/三角形 □ 明白全屏三角形比四边形优在哪 Shader结构 □ 明白顶点着色器几乎不做事 □ 明白frag里采样→加工→输出三步 □ 明白_MainTex是输入画面 □ 明白i.uv是像素位置 □ 知道Cull Off ZWrite Off ZTest Always C#驱动 □ 明白OnRenderImage/Blit的作用 □ 明白多效果多次Blit多次切换 □ 知道URP用ScriptableRenderPass 进阶 □ 明白Bloom是多步流程 □ 明白高斯模糊分离优化(2D→1D×2) □ 明白低分辨率做模糊的意义 一句话总结后处理的实现本质它就是一次Blit操作——画一个铺满屏幕的三角形或矩形把当前画面当作纹理_MainTex贴上去用后处理 Shader 逐像素加工结果输出到目标纹理。Shader 结构极简顶点着色器几乎不做事片元着色器做核心三步——采样 _MainTex、加工、输出。C# 端通过 OnRenderImage/Blit或 URP 的 RenderPass驱动多个效果 多次 Blit 多次 RT 切换移动端要合并优化复杂效果如 Bloom 是多步流程靠低分辨率和分离模糊来省性能。核心口诀后处理即Blit画个全屏三角形采样_MainTex加工输出多效果合并减切换模糊分离降分辨率 后处理实现要点速查表概念作用要点Blit纹理→Shader→纹理后处理核心操作全屏三角形覆盖屏幕的载体比四边形优_MainTex输入源画面Blit自动传入i.uv像素位置(0~1)用于采样frag三步采样→加工→输出核心逻辑Cull/ZWrite Off后处理标配不需深度剔除临时RT中间结果用完Release分离模糊2D→1D×2采样量骤减降分辨率模糊类优化反正是糊的 一句话记住核心后处理 “拿整张画面当贴图画个全屏三角形逐像素重新加工”。理解了 Blit 这个核心操作所有后处理调色、模糊、Bloom都只是frag 里加工逻辑的不同而已 延伸从实现细节回看优化【实现细节解释了为什么要那样优化】 现在你懂了实现,就懂了优化的道理: 合并效果 → 因为每次Blit都要RT切换 合并 少切换 少搬运带宽 ✓ 降分辨率 → 因为frag要处理每个像素 小图 像素少 采样少 ✓ 分离模糊 → 因为2D采样量是平方级 分离 采样从乘法变加法 ✓ 用LUT → 因为frag里复杂计算贵 LUT 复杂计算变一次采样 ✓ ↓ 理解实现 → 优化不再是死记,而是自然推导!

相关新闻

Neolink电池摄像头优化:7个实用技巧延长续航与低功耗设置指南

Neolink电池摄像头优化:7个实用技巧延长续航与低功耗设置指南

Neolink电池摄像头优化:7个实用技巧延长续航与低功耗设置指南 【免费下载链接】neolink An RTSP bridge to Reolink IP cameras 项目地址: https://gitcode.com/gh_mirrors/neo/neolink Neolink作为一款连接Reolink IP摄像头的RTSP桥接工具,不仅提…

2026/10/14 12:54:27 阅读更多 →
精选实战攻略:BT下载没速度?一份公共Tracker使用指南,5分钟找回满速

精选实战攻略:BT下载没速度?一份公共Tracker使用指南,5分钟找回满速

精选实战攻略:BT下载没速度?一份公共Tracker使用指南,5分钟找回满速 【免费下载链接】trackerslist Updated list of public BitTorrent trackers 项目地址: https://gitcode.com/GitHub_Trending/tr/trackerslist 半夜 12 点&#xf…

2026/10/14 12:55:07 阅读更多 →
合并网格后如何保证正确渲染?揭秘渲染管线底层逻辑

合并网格后如何保证正确渲染?揭秘渲染管线底层逻辑

🎬 开场:一个"合并后错乱"的疑问 上一讲我们说"合并网格能减少DrawCall"。 小王照做了,把100块砖合并成1个网格。 但他突然疑惑: “等等!每块砖原本有自己的位置、旋转、UV坐标… 合并成1个网格后,GPU怎么知道哪块砖该画在哪? 怎么保证每块砖的贴图…

2026/10/14 12:55:51 阅读更多 →

最新新闻

ECharts玫瑰图如何同时展示两个维度百分比?三种实现方案详解

ECharts玫瑰图如何同时展示两个维度百分比?三种实现方案详解

看到这个标题,你应该也在做类似的需求:一张玫瑰图里,要展示两个维度的数据,而且两个维度都要体现各自所占的百分比。这个场景在实际业务里太常见了——比如某公司报表里既要看“各产品线销售额占总销售额的比例”,又要…

2026/10/14 15:15:04 阅读更多 →
精灵标注助手导入XML数据全攻略:从预处理到批量导入的工程化实践

精灵标注助手导入XML数据全攻略:从预处理到批量导入的工程化实践

1. 从一份“打不开”的XML说起:精灵标注助手导入功能的真实使用场景第一次接触精灵标注助手的人,多半是被它“轻量、离线、支持多格式”这几个特点吸引过来的。尤其是做目标检测、图像分类或者文本实体识别的朋友,手里往往已经积累了一批标注…

2026/10/14 15:15:04 阅读更多 →
580集PS教程深度拆解:从软件操作到设计决策的系统学习路径

580集PS教程深度拆解:从软件操作到设计决策的系统学习路径

1. 这套580集PS教程到底值不值得啃第一次看到“580集”这个数字,我的反应跟大多数人一样:要么是标题党,要么就是把一个十分钟的小技巧拆成三集来凑数。但真正把这套内容翻了一遍之后,我发现它跟市面上那种“三天学会PS”“七天接单…

2026/10/14 15:15:04 阅读更多 →
游戏目标检测实战:3000张6类MOBA数据集从标注转换到YOLO训练全流程

游戏目标检测实战:3000张6类MOBA数据集从标注转换到YOLO训练全流程

简介:本资源为LOL英雄联盟角色检测数据集,面向计算机视觉方向的目标检测学习者与算法工程师,可用于训练和验证游戏场景下的多目标识别模型。数据集共3000张jpg图片,每张均配有对应的VOC格式xml标注与YOLO格式txt标注,标…

2026/10/14 15:15:04 阅读更多 →
Java开发实战:从基础到框架的常见问题解析

Java开发实战:从基础到框架的常见问题解析

1. Java学习中的常见困惑与解决思路最近在技术社区看到不少Java初学者提出的共性问题,让我回想起自己当年踩过的坑。从环境配置到框架选择,从语法理解到性能优化,每个阶段都会遇到不同的"拦路虎"。今天就把这些典型问题做个系统梳理…

2026/10/14 15:15:04 阅读更多 →
单片机毕设项目:基于51单片机的老人跌倒报警定时定位上报系统设计 基于单片机的老人安全定位监护与跌倒报警系统设计(032602)

单片机毕设项目:基于51单片机的老人跌倒报警定时定位上报系统设计 基于单片机的老人安全定位监护与跌倒报警系统设计(032602)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/14 15:14:02 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →