Deferred Shading延迟渲染

Deferred Shading

传统的渲染过程通常为:1)绘制Mesh;2)指定材质;3)处理光照效果;4)输出。传统的过程Mesh越多,光照处理越费时,多光源时就更慢了。

延迟渲染的步骤:1)Pass0先不做光照处理,将Mesh的Position信息和Normal信息绘制到纹理(RenderTargets,D3D支持多向输出);2)Pass1仅绘制屏幕大小的一个四边形,利用之前得到的Position纹理和Normal纹理对有效地区域选择性地进行光照处理,再输出最后的图像。

分析:由于延迟渲染将光照的处理量由空间转换到了平面,减少了光照等效果的计算量,提高了绘制速度,对多光源的绘制优势更为明显。

 

渲染流程

延迟渲染管线可分为四个阶段:geometry, lighting, composition, post-processing

Post-processing阶段与传统的forward shading没有太大差别,这里不提,只说明一下前三个阶段。

Geometry阶段:将本帧所有的几何信息光栅化到G-buffer。包括位置,法线,贴图等。

Lighting阶段:以G-buffer作为输入(位置,法线)进行逐像素的光照计算,将diffuse lighting和specular

Lighting 结果分别保存在两张RT上作为lighting buffer。

Composition阶段:将G-buffer中的贴图buffer和lighting buffer融合,得到渲染结果。

整体渲染过程并不复杂,但在实际的过程中还是有许多问题需要考虑的,下面一一列举。

G-buffer

Geometry阶段将几何信息渲染到multi render target上(MRT),当前最多支持4个MRT。并且驱动要求4个MRT必须相同的bit宽度。RT对显存占用过大会增加带宽,降低cache命中。而简单格式的RT又会影响画质。因此决定使用32bit的RT(如A8R8G8B8,R16G16F)或64bit宽度的RT(如A16R16G16B16F)。需要在画质和性能间做出折衷。(开发时尽可能可以方便的配置)。[1]中有一些性能比较。

MRT中必须的信息:position(depth), normal, diffuse(texture)

可能需要的信息:specular, power, emissive, ao, material id

这些信息需要在这4个RT上用合理格式,合理的组织。这里还可以就存储空间和shader的复杂性做折衷。如只保存depth,然后在光照时计算position[12]。以及用球面坐标保存法线[13]。以目前的资料得出的结论是应该尽可能地pack数据,减少内存占用,多出来的若干条shader指令不会明显影响性能。

光照计算

使用延迟渲染技术最大的好处就是可以渲染光照极为复杂的场景。这里场景中的光照可以分为两类。

影响整个场景的scene light。如directional light。渲染一个screen quad,逐像素光照计算,没什么好说的。

另一类是只影响一部分区域的local light。如点光源,聚光灯,以及特效等等。这些local light只影响到屏幕上的某些像素,当然不需要逐像素的进行光照计算。最简单的方法是绘制这些光源的包围体(点光源的包围体是球,聚光灯的包围体是圆锥),包围体的大小要大于等于光源的衰减范围。这些包围体经过变换投影到屏幕上的对应区域,随后在pixel shader中计算光照。

优化:

1.       光源包围体的视锥剔除,遮挡剔除。

2.       光源包围体投影后很小时剔除;若干个靠的比较近的小光源合并成一个较大的光源[11]

3.       光源包围体的backface culling

4.       屏幕空间中没有被光源照到的,或者被更近的物体遮挡住的像素不需要光照计算,因此可以逐像素的深度剔除。

a.       使用正确的stencil light volume。类似shadow volume的方案,将渲染light volume的正反两面,得到正确的stencil mask,然后光照计算时使用stencil buffer。这种方法可以得到正确的结果,但是需要渲染每盏灯时频繁改变render state,可能会带来一定性能上的损失。

b 使用z test,可以得到“一定程度上正确”的结果。

阴影

光照计算的同时计算阴影。使用传统的shadow map,预先生成一张阴影图。考虑在编辑场景的时候指定那些重要的光源才会产生阴影。在计算shadow map时要针对光源的binding volume进行剔除。

方向光和聚光灯可以使用基本的shadow map投影(正交投影,透视投影)。点光源会复杂一些,需要使用cubic shadow map。(考虑unwrapping method[14])

半透明

由于在延迟渲染的过程中只计算离屏幕距离最近的那个像素的光照,因此无法处理半透明物体的光照。

方案1

延迟渲染的过程中只处理不透明的物体,将所有半透明的物体放在渲染过程的最后,使用传统的forward shading渲染。

方案2

在Geometry阶段将半透明的物体和背景逐像素的交织起来,将透明度放在一个单独的通道中。按一般的方法计算光照。随后在composition阶段再根据透明度将透明物体和背景逐像素的混合起来。

优点:

光照一致性。半透明的物体也参加延迟渲染,可以接受多光源的光照。

简单并且健壮。不需要单独区分不透明物体和半透明物体,不需要单独的半透明渲染管道。

速度快。只增加了7到10条ps指令,两张贴图,只有约2%的性能损失。

缺点:

模糊。在半透明的物体上会有一点模糊,原因是在交织的过程中会有一定信息损失。

边缘锯齿。反交织的过程中半透明物体的边缘会产生一些锯齿。

只能有一层半透明。

多种材质

在延迟光照的过程中支持多种材质需要如下方案:

在G-buffer阶段输出材质的ID到G-buffer的一个通道中,随后在lighting阶段和composition阶段根据材质ID使用不同的光照函数计算光照。这种方案在sm 3.0中使用动态分支的前提下可以很好的工作。

反锯齿

Dx9 API不支持反锯齿的MRT,Dx10支持。

一种方案是使用超采样,先渲染到大的RT上,再downsample到正常的大小,得到没有锯齿的结果。延迟渲染的效率跟分辨率有很大关系,因此这种方法会极大的降低性能,基本不可取。

另一种方案是使用“intelligent blur”,只模糊物体边缘的像素:

根据相邻像素的深度和法线提取物体边界,然后对提取出的边界进行模糊。模糊时要避免不正确的泄露。如后面物体的颜色泄露到前面的物体上[11]。 总体而言实现会较为复杂。

另一种方案pre-lighting [8][9][17]

一种pre-z rendering 和deferred rendering的结合。G-buffer阶段只保存depth和normal,然后计算光照信息到lighting buffer,格式如下

LightColor.r * N.L * Att
LightColor.g * N.L * Att
LightColor.b * N.L * Att
R.V^n * N.L * Att

最后使用传统的forward shading再将整个场景渲染一遍,期间查询lighting buffer。

与普通的deferred shading相比:

优点:

占用带宽小,第一遍渲染只输出normal,depth是自动获得的。

可以用在较老的硬件平台上,不需要MRT支持。

对现有forward shading管道改动较小,比较容易实现。

缺点:

整个场景需要渲染两遍,相当于在pre-z和forward shading中间加了一个lighting stage。

时间: 2024-12-24 06:14:54

Deferred Shading延迟渲染的相关文章

Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】

Deferred Shading,看过<Gems2> 的应该都了解了.最近很火的星际2就是使用了Deferred Shading. 原帖位置:   http://blog.csdn.net/noslopforever/archive/2009/03/03/3951273.aspx 这篇文章是对GEMS2里<Deferred Shading in S.T.A.L.K.E.R.>(中文译名<S.T.A.L.K.E.R.中的延期着色>,原作者Oles Shishkovtsov

延迟渲染(Deferred Shading)技术详解

http://blog.csdn.net/xiajun07061225/article/details/7680895 一.Deferred shading技术简介 Deferred shading是这样一种技术:将光照/渲染计算推迟到第二步进行计算.我们这样做的目的是为了避免多次(超过1次)渲染同一个像素. 其基本思想如下: 1.在第一步中,我们渲染场景,但是与通常情况下应用反射模型计算片断颜色不同的是,我们只是简单的将几何信息(位置坐标,法线向量,纹理坐标,反射系数等等)存储在中间缓冲区中,

opengl deferred shading

原文地址:http://www.verydemo.com/demo_c284_i6147.html 一.Deferred shading技术简介 Deferred shading是这样一种技术:将光照/渲染计算推迟到第二步进行计算.我们这样做的目的是为了避免多次(超过1次)渲染同一个像素. 其基本思想如下: 1.在第一步中,我们渲染场景,但是与通常情况下应用反射模型计算片断颜色不同的是,我们只是简单的将几何信息(位置坐标,法线向量,纹理坐标,反射系数等等)存储在中间缓冲区中,这样的缓冲区我们称之

延迟渲染之由深度重建世界位置

前面一篇文章介绍了混合方式的延迟渲染(Hybrid deferred shading),本文来讲解一下其中的一个细节,由深度构建世界位置,我们这里假定使用D3D9以及左手坐标系. 我在这里介绍两种方式,这两种方式也就跟实现方式有一定的关系. 方法1: 如果我们在第一遍中写深度时使用的是经过透视除法的z值 1 // 第一遍时输出深度 2 float4x4 matViewProjection; 3 struct VS_INPUT 4 { 5 float4 Position : POSITION0;

《Deferred Shading》

原文地址:https://learnopengl-cn.github.io/05%20Advanced%20Lighting/08%20Deferred%20Shading/ 原文 Deferred Shading 作者 JoeyDeVries 翻译 Meow J 校对 KenLee 我们现在一直使用的光照方式叫做正向渲染(Forward Rendering)或者正向着色法(Forward Shading),它是我们渲染物体的一种非常直接的方式,在场景中我们根据所有光源照亮一个物体,之后再渲染下

引擎设计跟踪(九.14.3.1) deferred shading: Depthstencil as GBuffer depth

问题汇总 1.Light support for Editor编辑器加入了灯光工具, 可以添加和修改灯光. 问题1. light object的用户互交.point light可以把对应的volume (wireframe sphere/cone)画出来用于用户选中, 但是光源太多的时候, 球就有点凌乱了. 所以使用了HUD, 只要选中HUD就会选中灯光, 只有灯光被选中的时候才显示volume. 另外, 编辑器里面的很多"不可见"的逻辑对象都有这种需求, 虽然现在还没有. 另外, 可

引擎设计跟踪(九.14.3.2) Deferred shading的后续实现和优化

最近完成了deferred shading和spot light的支持, 并作了一部分优化. 之前forward shading也只支持方向光, 现在也支持了点光源和探照光. 对于forward shading, 可以在渲染每个对象之前, 用对象的包围盒, 查询空间内的光源, 然后填入shader cosntant里. 因为空间一般是基于四叉树或者八叉树的划分, 所以查询不会慢.现在透明物体也能通过forward shading 正常光照了. Deferred shading optimizat

vue-lazy-render: 延迟渲染大组件,增强页面切换流畅度

最近用element来做项目,在开发的过程中,突然发现页面的操作和切换在数据量大的时候相当卡,后来提了个issue,在furybean解答后才知道,我每个单元格都加了tooltip,会生成大量的节点,造成页面操作卡顿.后来将tooltip去掉,操作流畅多了. 但是,由于我是将页面的数据存在vuex中的,在路由切换回来的时候,发现在数据量大的时候,页面渲染得很慢,大概两三秒才能切换过来,用户体验相当不好. 这时,我就在想,能不能让页面切换完成之后才开始渲染数据量大的组件,用户起码不会感知到路由切换

延迟渲染 deferred Shading

流程: 1.先渲染一遍物体的位置,法线  和颜色  到三张纹理 2.在根据这三张纹理渲染一遍灯光 3.合成颜色图和灯光图  (ssao图) 看上去好像灯光不多,其实我在这里加了200个灯,明天继续...