不同几种剔除(Culling)在渲染流程中的使用总结

前提
最近在阅读《Real-Time Rendering》Third Edition时,发现对于渲染管线中不同剔除部分的具体含义和生效阶段不甚明了,遂做了一点研究,在这里做一个记录。

涉及到的剔除方法包括:
视椎体剔除
遮挡剔除
裁剪Clipping
背面剔除
深度剔除
以下对于这几种剔除方法分别进行分析:
视椎体剔除
发生在应用程序阶段(Application Stage),一般由游戏引擎内部实现或者自己编写对应的算法来实现,运行在CPU上。裁剪的依据主要是根据摄像机的视野(field of view)以及近裁减面和远裁剪面的距离,将可视范围外的物体排除出渲染,被剔除的物体将不会进入渲染的几何阶段(Geometry Stage)。视椎体剔除是减少渲染消耗的最有效手段之一,可以在不影响渲染效果的情况下大幅减少渲染涉及到的顶点数和面数。

根据不同引擎的的实现,实际时候时可能有一些需要注意的地方。经过测试,Unity中默认ShadowMap的生成会大幅影响视椎体剔除的范围,对于移动平台不使用实时阴影的情况下,可以尝试关闭灯的阴影投射或者去掉简单sheder中的FallBack(通常会含有ShadowCaster),就会使同屏渲染面数大幅减小。

遮挡剔除
发生在应用程序阶段(Application Stage),由游戏引擎实现,运行在CPU上。以Unity为例,需要根据场景中Static物体的位置预先生成场景OcclusionCulling数据,运行时就可以剔除对应静态物体之后的其他物体。遮挡剔除是减少渲染消耗的有效手段之一,可以和视椎体剔除同时生效,进一步减少渲染的消耗。

针对Unity中遮挡剔除中的使用和研究,https://blog.csdn.net/cartzhang/article/details/52684127 中总结的很好。

随着硬件技术的提升,目前GPU已经可以支持在没有应用程序阶段额外数据的支持下在硬件侧面实现遮挡剔除(在光栅化之后,像素着色器之前,优于渲染管线末尾才进行的深度剔除) 
https://blog.csdn.net/cartzhang/article/details/72420731 一文中提到

现代GPU中运用了Early-Z的技术,在Vertex阶段和Fragment阶段之间(光栅化之后,fragment之前)进行一次深度测试,如果深度测试失败,就不必进行fragment阶段的计算了,因此在性能上会有很大的提升。但是最终的ZTest仍然需要进行,以保证最终的遮挡关系结果正确。

裁剪Clipping
发生在几何阶段(Geometry Stage)后期,投影变换之后屏幕映射之前,是渲染管线的必要一环。只有当图元完全或部分存在于规范立方体内部(摄像机视野内)的时候,才将其返送到光栅化阶段。其中,对于完全位于规范立方体内部的图元,则直接进行下一阶段;完全处于规范立方外部的图元则完全被舍弃;部分处于规范立方体内部图元,则会根据摄像机视野进行对应的裁剪,在这一过程中可能会产生新的顶点。

通过裁剪Clipping可以将摄像机视野外的图元舍弃掉,减小光栅化阶段的消耗。

背面剔除
背面剔除即是将背向视点的图元剔除,因为它们对最终渲染的图像没有贡献。这是一种简单直观的操作,一次对一个多边形进行操作。剔除的基本原理是先判定多边形的朝向,并和当前的观察方向进行比较

更为详细的说明可以在《Real-Time Rendering》第14章加速算法找到,也可参照浅墨大大的总结文章 
https://blog.csdn.net/poem_qianmo/article/details/78884513

Unity中的背面剔除在光栅化阶段进行,执行在Vertex Shader 之后,在Fragment Shader片元着色器之前,通过Shader中的Cull指令来控制背面剔除的开启和关闭, 
Unity手册上的图示显示的比较清晰: 
 
https://docs.unity3d.com/Manual/SL-CullAndDepth.html

深度剔除
在Fragment Shader之后,光栅化阶段末期的融合阶段执行,又叫深度检测(或Z缓存检测)。每次将一个图元回执为相应的像素时,都会计算像素位置处图元的深度值,和深度缓存中对应像素的值进行比较,如果新计算出的深度小于缓存中的深度,则更新深度缓存中的值;如果深度值大于深度缓冲中的值,则计算结果被舍弃,深度缓冲的值也无需更新。

在执行深度剔除时,已经位于渲染管线末尾,所有的颜色计算都已经完成,因此意义只在处理图元的可见性问题,对于渲染的消耗基本没有影响,不是优化时需要重点考察的问题。

总结

  1. 在考虑渲染优化的问题上,应当优先考察”视椎体剔除”和”遮挡剔除”是否在项目中正常运作,这两项会极大的影响到实际渲染时的消耗。
  2. 其次需要考虑背面剔除的开启,在没有大量使用单面的模型情况下,背面剔除可以在不影响显示的前提下少处理一半的像素着色运算。
  3. 视口剔除和深度剔除是渲染管线的固有部分,不在优化的主要考察范围内。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Unity 添加渲染视口的方法如下: 1. 创建一个新的 Unity 项目。 2. 在资源管理器创建一个新的 C# 脚本,命名为 RenderView。 3. 在脚本添加以下代码: ``` using UnityEngine; using UnityEngine.UI; public class RenderView : MonoBehaviour { public RenderTexture renderTexture; public RawImage rawImage; private void Start() { rawImage.texture = renderTexture; } } ``` 4. 将新创建的脚本挂载到一个空的游戏对象上。 5. 在场景创建一个 RawImage 组件,并将其作为游戏对象的子对象。 6. 在游戏对象上创建一个 RenderTexture,并将其作为 RenderView 脚本的 renderTexture 字段。 7. 在 RawImage 组件上,将其作为 RenderView 脚本的 rawImage 字段。 8. 运行场景,您将在 GUI 看到渲染视口。 这是一种添加渲染视口到 Unity GUI 的基本方法,您可以根据需要进行修改。 ### 回答2: 在Unity,可以通过以下步骤在GUI添加渲染视口: 1. 创建一个空的游戏对象,并将其作为渲染视口的父级对象。 2. 在该游戏对象上添加一个Camera组件,用于渲染场景。 3. 在场景选择一个适当的位置和角度,调整该Camera的Transform属性,以确保它拍摄到想要呈现的内容。 4. 在GUI创建一个RawImage对象,用于显示渲染视口。 5. 将该RawImage的纹理(Texture)属性设置为之前所创建的Camera的渲染纹理(RenderTexture)。 可以使用RenderTexture.Create()方法创建渲染纹理,并将其设置为Camera的targetTexture属性。 6. 将渲染视口的父级对象的位置、尺寸和锚点根据GUI界面的要求进行调整。 7. 在每一帧更新时,通过调用Camera的Render()方法来进行场景的渲染。 8. 渲染完成后,通过将Camera的渲染纹理赋值给RawImage的纹理属性来显示渲染视口。 需要注意的是,渲染视口是通过在GUI模拟相机视角来实现的,因此在渲染视口的游戏对象并不会响应物理交互。如果需要实现交互功能,可以在GUI添加相应的按钮或其他控件,并通过代码控制游戏对象的行为。 此外,为了提高性能,可以选择将渲染视口的相机设置为只渲染特定的图层(Layer),并在GUI摄像机的Culling Mask属性排除这些图层,以避免不必要的渲染。 以上是在Unity的GUI添加渲染视口的基本步骤,通过合理的调整相机和GUI的参数,可以实现各种不同的效果和交互体验。 ### 回答3: 在Unity的GUI添加渲染视口,需要按照以下步骤进行操作: 1. 创建一个空的GameObject,用于容纳渲染视口。将其命名为"RenderViewport"。 2. 在"RenderViewport"对象上添加一个Camera组件。这将成为渲染视口的相机。 3. 配置相机的参数,例如设置宽高比、视野、背景色等。 4. 在"RenderViewport"对象上添加一个RawImage组件。这将用于显示渲染视口。 5. 创建一个RenderTexture对象用于渲染视口的输出。可以使用RenderTexture.Create函数创建一个指定分辨率的RenderTexture。 6. 将RenderTexture赋值给相机的targetTexture属性,以便将相机的输出渲染到RenderTexture上。 7. 将RenderTexture赋值给RawImage的texture属性,以便将RenderTexture显示在RawImage上。 8. 在GUI界面,将"RenderViewport"对象放置在期望显示渲染视口的位置上。可以使用GUILayout组件或自定义脚本来控制其位置和大小。 使用这些步骤,可以在Unity的GUI界面成功添加一个渲染视口。这样,通过控制相机的参数和渲染纹理,可以实现在GUI界面显示任何所需的渲染内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值