
目录一、渲染管线概述GPU图形管线典型阶段引擎渲染管线Unity SRP二、实时渲染大致流程三、CPU端准备渲染命令1、场景遍历2、可见性剔除 Culling3、排序 Sorting4、合批 Batching5、命令缓存 Command Buffer四、GPU几何阶段1、输入装配 Input Assembler2、顶点着色器 Vertex Shader3、细分阶段 Tessellation4、几何着色器 Geometry Shader5、网格着色器 Mesh Shader6、计算着色器 Compute Shader五、裁剪、背面剔除、视口变换1、裁剪 Clipping2、透视除法 Perspective Divide3、视口变换 Viewport Transform4、背面剔除 Backface Culling六、光栅化1、插值 Interpolation2、Fragment 和 Pixel 的区别七、片元着色器 Pixel / Fragment Shader八、材质系统与PBR常见的 PBR 光照结构九、输出合并阶段 Output Merger1、深度测试 Depth Test2、ZWrite3、混合 Blending十、向前渲染 Forward Rendering十一、延迟渲染 Deferred Rendering1、GBuffer Pass2、Lighting Pass十二、现代管线渲染1、Tiled Forward2、Clustered Forward十三、现代引擎渲染一帧包含的 Pass1、阴影 Shadow Pass2、深度预通道 Depth Prepass3、不透明物体 Opaque Pass4、贴花 Decal Pass5、光照 Lighting Pass6、天空盒 Skybox / 大气散射 Atmosphere7、透明物体 Transparent Pass8、后处理 Post Processing9、UI Pass十四、HDR、Tone Mapping 与显示输出1、HDR Render Target2、Bloom3、Tone Mapping4、Gamma 编码一、渲染管线概述渲染管线分为两部分底层GPU图形管线例如顶点着色器、光栅化、像素着色器上层引擎渲染管线例如URP、HDRP、UE Deferred Renderer可以将渲染管线理解为把场景里的模型、材质、灯光、相机、特效经过CPU、GPU处理最终变成屏幕上一张图像的全过程。GPU图形管线典型阶段顶点数据↓输入装配Input Assembler↓顶点着色器Vertex Shader↓可选细分Tessellation↓可选几何处理器Geometry/Mesh Shader↓光栅化Rastertzation↓像素(片元)着色器Fragment/Pixel Shader↓Stencil - Depth - Blending↓帧缓冲Frame Buffer引擎渲染管线Unity SRP场景数据收集↓剔除Culling↓阴影Shadow Pass↓深度测试Depth PrePass↓GBuffer / Forward Opaque Pass↓Lighting Pass↓透明物体 Pass↓后处理↓UI↓最终显示二、实时渲染大致流程CPU准备↓GPU几何阶段↓光栅化↓像素着色↓光照计算↓后处理↓显示输出三、CPU端准备渲染命令1、场景遍历引擎需要在场景中收集需要画哪些MeshRender(网格渲染器)/SkinnedMeshRenderer(蒙皮网格渲染器)每个物体用什么Mesh、Material当前相机在哪有哪些灯光、阴影有哪些特效、粒子、后期处理需要执行unity中渲染一个物体需要考虑如下信息Camera: 摄像机附近的才渲染Layer: 配合Camera的Culling Mask使用来显示或隐藏一类物体Culling Mask: Camera希望或不希望看到哪一类物体Renderer.enabled: 物体渲染器是否开启Material: 用什么材质进行渲染Shader Pass: 这个Shader有无适合当前渲染阶段的PassRender Queue: 决定什么时候渲染2、可见性剔除 Culling视锥剔除Frustum Culling: 剔除不在视角场景内的物体遮挡剔除Occlusion Culling: 剔除被完全挡住的物体距离剔除Distance Culling: 剔除太远的物体LOD选择3、排序 SortingUnity引擎中Render Queue对场景中的物体分为5个大类Background 1000Geometry 2000Alphatest 2450Transparent 3000Overlay 4000Unity引擎中的渲染顺序BackgroundOpaque / Geometry由远及近AlphaTestSkyboxTransparent由近及远Overlay / UI4、合批 BatchingCPU提交 Draw Call 有成本所以现代引擎会想办法合批Static Batching: 适合静态不动的物体多个静态 Mesh 合并减少 Draw CallDynamic Batching: 适合小模型但是限制较多GPU Instancing: 同一个 Mesh 同一个 Material但位置不同、颜色、参数不同。GPU实例是技术美术最常用的一个技术在植被、粒子、程序化生成时常用。5、命令缓存 Command Buffer现代引擎不会直接“立刻画”而是先记录一堆渲染命令。在现代引擎里这些 Pass 之间的依赖越来越复杂所以很多引擎使用Render Graph / Frame Graph来管理。Render Graph的作用是自动管理哪个Pass先执行哪些RenderTexture可以复用哪些资源需要保留哪些资源需要释放哪些Pass可以异步执行四、GPU几何阶段CPU提交命令后GPU开始处理顶点和几何。1、输入装配 Input Assembler输入装配阶段负责把顶点缓冲(Vertex Buffer)和索引缓冲(Index Buffer)组织成图元供应给后续管线。最常见的图元是三角形(triangle)还有线(line)、点(point)。2、顶点着色器 Vertex Shader顶点着色器每次处理一个顶点它的职责是坐标变换(从一个坐标系变换到另一个坐标系)Object Space↓ Model MatrixWorld Space↓ View MatrixVIew Space↓ Projection MatrixClip Space常见的坐标系空间坐标空间含义技术美术常见用途Object Space模型空间顶点动画、局部溶解World Space世界空间世界坐标扫描、全局风场View Space相机空间深度、屏幕特效Clip Space裁剪空间GPU裁剪前的位置NDC归一化设备坐标屏幕映射Screen Space屏幕空间后处理、描边、屏幕扭曲Tangent Space切线空间法线贴图Vertex Shader常见工作顶点位移、骨骼蒙皮、Morph Target、风吹草动、水面波动、UV动画、顶点色读取、世界空间位置计算、法线变换3、细分阶段 Tessellation细分阶段可以把低面数模型在GPU上细分成更多三角形流程大致为低模三角形↓外壳着色器 Hull Shader↓细分器 Tessallator↓域着色器 Domain Shader↓高密度三角形用途地形细分、近景石头、水面细分、位移贴图Displacement Mapping不过在现代游戏里传统 Tessellation 的使用比以前少了一些场景会改用 Nanite、Mesh Shader、预烘焙高模、虚拟几何等方案。4、几何着色器 Geometry Shader几何着色器功能输入一个图元输出新的图元。例如输入一个点输出一个四边形。在以前常用于毛发、草片、粒子Billboard、法线可视化但是Geometry Shader 性能通常不太理想现代项目里很多场景会用 Compute Shader、Mesh Shader 或 Instancing 替代。5、网格着色器 Mesh ShaderMesh Shader 是更现代的几何阶段方案。DirectX 的 Mesh Shader 规范把它描述为 D3D12 中 Vertex Shader 和 Geometry Shader 的下一代替代方案目标是提高几何管线的灵活性和性能并且可以在光栅化前进行几何放大和剔除。传统流程Mesh Shader第一步Input AssemblerMeshlet第二步Vertex ShaderAmplification Shader 可选第三步GeometryMesh Shader第四步RasterizerRasterizerMesh Shader适合海量小三角形、GPU驱动渲染、Meshlet Culling、大规模场景、程序化几何、复杂LOD。6、计算着色器 Compute Shader普通shader主要服务于渲染流程但是Compute Shader的主要作用是并行计算若干数据例如模拟水波、模拟粒子、生成噪声纹理、处理图像、计算布料、计算群体行为、生成程序化地形、做GPU排序。五、裁剪、背面剔除、视口变换1、裁剪 Clipping位于相机近平面、远平面之外的三角形图元会被裁剪裁剪发生在Clip Space。即太近的面裁掉太远的面。裁掉在视锥体四棱台外的面会被剔除掉。2、透视除法 Perspective Divide// 四维空间坐标x,y,z,w float4 positionCS; // 进行透视除法 float3 NDC; NDC.x positionCS.x / positionCS.w; NDC.y positionCS.y / positionCS.w; NDC.z positionCS.z / positionCS.w;其中positionCS.w通常被称为齐次坐标中的其次分量或者透视除法前的深度因子。3、视口变换 Viewport TransformNDC坐标范围通常是x,y∈[-1, 1]然后映射到屏幕像素Screen.x∈[0, width], Screen.y∈[0, height]。视口变换就是一个线性映射从[-1,1]到[0,width]和[0,height]。4、背面剔除 Backface Culling三角形有正面和背面GPU根据顶点绕序判断三角形朝向如果开启背面剔除背对摄像机的三角形则不会渲染。六、光栅化光栅化是一个非常关键的阶段它负责把三角形变成屏幕上的片元 Fragment。它将图元转换成二维图像每个离散位置包含深度、颜色或其他属性片元随后会被Fragment Shader处理。1、插值 Interpolation通过插值算法将由若干顶点组成的图元转换成屏幕上的像素位置。每个像素的UV、颜色、法线就是由插值得到。在顶点着色器中直接使用的UV、法线、位置等都是从顶点阶段传过来再被光栅化阶段插值出来。2、Fragment 和 Pixel 的区别Fragment 可以理解成“待处理像素”它并不是最终呈现在屏幕上的像素因为它还要经过模板测试深度测试Alpha TestBlendingMSAA Sample 处理所以一个Fragment 最后并不一定真实地写入屏幕。七、片元着色器 Pixel / Fragment Shader片元着色器决定每个片元最终输出什么颜色它地工作通常是采样 BaseMap基础色贴图采样 Normal Map法线贴图采样 Metallic / Roughness / AO金属度、光滑度、环境光遮蔽贴图计算光照计算阴影计算 Fresnel菲涅尔反射计算透明度输出最终颜色如下面的代码所示这是 Unity 中一个最基础的片元着色器代码float4 frag(Varyings i) : SV_Target { // 采样基础色贴图得到反照率 float3 albedo SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv).rgb; // 顶点着色器采样或计算法线贴图传入并归一化 float3 normal normalize(i.normalWS); // 归一化光照方向 float3 lightDir normalize(_MainLightDirection); // 法线和光照方向点积 float ndotl saturate(dot(normal, lightDir)); // 计算漫反射颜色 float3 color albedo * ndotl; return float4(color, 1.0); }八、材质系统与PBR现代实时渲染大多使用PBR也就是Physically Based Rendering。PBR材质常见输入Base Color / Albedo基础色/反照率贴图Matallic金属度贴图Roughness / Smoothness粗糙度贴图Normal法线贴图AO环境光遮蔽贴图Emission自发光贴图Alpha透明度贴图核心思想材质不再随便调一个“看起来差不多”的高光而是用更接近物理规律的方式描述表面反射。常见的 PBR 光照结构一个常见地PBR BRDF可以拆解成漫反射 Diffuse镜面反射 Specular镜面反射部分通常包含DNormal Distribution Fuction 法线分布函数GGeometry Function 几何遮蔽函数FFresnel 菲涅尔项Cook-Torrance BRDF D * G * F / (4 * NdotL * NdotV)九、输出合并阶段 Output MergerPixel Shader 算出颜色后不是马上变成最终颜色它还要经过 Output Merger。Output Merger为结合 Fragment Shader 输出、Render Target 内容、Depth/Stencil Buffer 和管线状态来生成最终像素颜色的阶段它负责深度/模板测试和混合等最终可见性与颜色合成工作。主要包括Depth TestStencil TestBlendingColor MaskRender Target Write1、深度测试 Depth Test每个像素会记录一个深度值如果新 Fragment 比旧 Fragment 更靠近相机就通过近的不透明物体遮挡住远的Depth Buffer:像素 A 当前深度 0.3新 fragment 深度 0.5因为 0.5 更远所以被丢弃2、ZWriteZWrite On 表示写入深度。不透明物体通常ZWrite OnZTest LEqual透明物体通常ZWrite OffBlend SrcAlpha OneMinusSrcAlpha透明物体如果写深度可能会错误遮挡后面的透明层。3、混合 Blending透明效果需要设置 Blending 模式// 正常透明度混合 Blend SrcAlpha OneMinusSrcAlpha // 柔和相加 Blend OneMinusDstColor One // 正片叠底 Blend DstColor Zero // 两倍相乘 Blend DstColor SrcColor // 变暗 BlendOp Min Blend One One // 变亮 BlendOp Max Blend One One // 滤色 Blend OneMinusDstColor One // 等价滤色 Blend One OneMinusDstColor // 线性减淡 Blend One One十、向前渲染 Forward RenderingForward Rendering 是最直观的渲染方式流程为每个物体↓执行材质 Shader↓在 Shader 中计算灯光↓直接输出最终颜色就是 Geometry Material Lighting 在同一个Pass中完成。优点简单直观对透明物体更友好支持 MSAA移动平台常用Shader 逻辑更容易理解缺点灯光很多时成本高每个物体都要处理灯光多灯光时 Shader 变复杂后处理和屏幕空间效果依赖额外的 Buffer十一、延迟渲染 Deferred RenderingDeferred Rendering 是现代主机、PC 游戏中非常常见的管线它把“材质信息”和“光照计算”拆开。延迟渲染的优点多灯光更友好适合复杂光照多动态点光、多聚光灯、屏幕空间反射、SSAO、Decal、延迟光照体积Decal 很方便延迟渲染的缺点GBuffer 占现存和带宽透明物体不好处理多数引擎里不透明物体使用 Forward 渲染MSAA支持困难1、GBuffer Pass先不直接算最终光照而是把材质属性写入多张 RenderTexture这些 RenderTexture 叫 GBuffer。例如GBuffer0: BaseColor Occlusion // 这个像素是什么材质GBuffer1: Normal // 这个像素的法线是什么GBuffer2: Metallic Roughness // 这个像素有多粗糙GBuffer3: Emission / Specular // 这个像素是不是金属Depth: 深度 // 这个像素在世界空间的哪里2、Lighting Pass然后再屏幕空间做光照读取 GBuffer↓读取灯光↓计算每个屏幕像素的光照↓输出最终颜色Deferred Shading 的核心逻辑材质把属性写入 GBuffer光照 Pass 再读取每像素材质属性并执行光照计算。十二、现代管线渲染Forward 和 Deferred 各有问题于是现代管线常用 Forward 或 Clustered Rendering。核心思想不再让每个物体遍历所有灯光而是先把屏幕或空间切成小块每个小块只记录会影响它的灯光。1、Tiled Forward把屏幕分成很多 tile例如 16 * 16 像素一个 tile每个 tile 建立一个灯光列表Tile 0: Light 1, Light 5Tile 1: Light 2, Light 4, Light 8Tile 2: Light 3然后 Pixel Shader 只遍历当前 tile 的灯光。2、Clustered ForwardClustered 更进一步不只是屏幕二维切块还加上深度方向形成 3D cluster。同样每个 3D cluster 建立一个影响这个空间块的灯光列表。适合大量点光大量局部光VRForward 渲染透明物体光照十三、现代引擎渲染一帧包含的 Pass一个比较典型的现代实时渲染帧包含以下结构1、阴影 Shadow Pass先从灯光视角渲染场景深度得到 Shadow Map。然后 Main Camera 渲染时查询当前像素在灯光视角下是否被遮挡住如果被遮挡住就是阴影。Shadow Map 不是颜色图它本质上是一张深度图记录每个在该光源视角下每一个像素位置离得最近的片元的距离。主相机渲染的时候如果当前片元到灯的深度 Shadow 中记录的深度说明它被其他物体挡住了。常见的阴影技术Shadow MappingCascaded Shadow Maps级联阴影PCFPercentage Closer FilteringVSMVariance Shadow MapContact ShadowRay Traced Shadow2、深度预通道 Depth PrepassDepth Prepass 会先只画深度不算复杂颜色。先记录 Depth后面正式渲染时被遮挡像素可以提前丢弃。适合像素 Shader 很复杂场景 Overdraw 很高有大量复杂材质但它也会多一次几何绘制所以并不是任何场景都一定划算。3、不透明物体 Opaque Pass不透明物体通常最先正式渲染Forward 管线Opaque Pass 直接输出颜色Deferred 管线Opaque Pass 写入 GBuffer4、贴花 Decal Pass贴花用于弹孔、血迹、污渍、路面标线、墙面破损、水迹等。Deferred 中 Decal 可以修改 GBufferBaseColor、Normal、Roughness、Metallic等Render Texture。Forward 中 Decal 通常需要额外方案比如投影、Mesh Decal、DBuffer 等。5、光照 Lighting Pass在 Deferred 管线中Lighting Pass 很关键它会读取GBuffer、Depth、ShadowMap、Light Data、Reflection Probe、IBL最终输出HDR Scene Color。6、天空盒 Skybox / 大气散射 Atmosphere天空盒、体积云、大气散射通常在不透明物体附近处理。常见内容Skybox、Procedural Sky、Atmospheric Scattering、Volumetric Cloud、Sun Disk、Fog7、透明物体 Transparent Pass透明物体通常晚于不透明物体渲染例如水、玻璃、烟雾、粒子、能量盾、半透明UI、魔法特效透明物体难点1、排序问题2、深度写入问题3、多层混合问题4、折射问题5、阴影问题8、后处理 Post Processing后处理是在整张屏幕图像上做效果输入通常是Scene Color、Depth Texture、Normal Texture、Motion Vector、Exposure常见后处理Bloom、Tone Mapping、Color Grading、Vignette、Depth of Field、Motion Blur、SSAO、SSR、TAA、FXAA、Film Grain、Chromatic Aberration9、UI Pass最后画 UI通常 UI 不受场景光照影响Scene↓PostProcess↓UI↓Final Present十四、HDR、Tone Mapping 与显示输出现代渲染通常不是直接输出 0 到 1 的颜色场景内部一般使用 HDR。例如太阳高光 15.0灯光反射 8.0普通墙面 0.8这些值超过 1普通显示器不能直接显示所以需要 Tone Mapping。1、HDR Render Target场景颜色可能存储在RGBA16FR11G11B10FRGBA32F这些格式可以表示超过 1 的亮度。2、BloomBloom 会提取高亮区域然后模糊再叠回原图Scene Color↓Bright Pass↓Blur↓Add Back3、Tone MappingTone Mapping 把 HDR 映射到显示器能显示的范围例如HDR 0 ~ 20↓Tone MappingLDR 0 ~ 1最常见的 Tone MappingReinhard、ACES、Filmic、Custom Curve4、Gamma 编码现代 PBR 渲染通常在线性空间中计算光照然后输出到显示器时进行 gamma 编码。大致流程为sRGB 贴图↓ 解码到 Linear在线性空间计算光照↓ Tone Mapping↓ Gamma / sRGB 输出显示器显示