| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> UE5-lumen的光照计算RenderLumenSceneLighting -> 正文阅读 |
|
[游戏开发]UE5-lumen的光照计算RenderLumenSceneLighting |
RenderLumenSceneLighting主要是lumen计算直接光与间接光的地方,主要通过体素以及有号距离场来计算光照效果。 总体的步骤如下:1.初始化光照的uav,srv,buffer 2.meshcard层面的剔除 3.间接光照参数 4.合并lumen场景光照需要的 5.lumen直接光照计算 6.合入漫反射信息,为后续间接光使用 7.过滤颜色 8.计算体素和有号距离场的间接光照可见对象 9.计算lumen的半透明光照效果 LumenSceneLighting.cpp中。 RenderLumenSceneLighting 只有FDeferredShadingSceneRenderer::Render才有RenderLumenSceneLighting。 如果lumen可视化的对象有开启,以下开启间接参数写入card中来更新这一帧的直接照明 ?。 有下面几步, 1.DirectLightingCardScatterContext.Init初始化光照的uav,srv,bufferinit主要是初始化QuadAllocator,QuadDataBuffer,QuadAllocatorUAV,QuadDataUAV 这一步主要是创建uav,srv或buffer给到后面使用的。 2.DirectLightingCardScatterContext.CullCardsToShape,meshcard层面的剔除这里主要注册了三个buffer,分别是VisibleCardsIndexBuffer,CardsToRenderIndexBuffer,CardsToRenderHashMapBuffer。然后通过GraphBuilder.AddPass给到computeshader“/Engine/Private/Lumen/LumenSceneLighting.usf”的CullCardsToShapeCS. ? 里面把在视锥内的对象。 在CullCardsToShapeCS中主要是根据索引中的lumen的数据是否在范围内以及是否灯光刷新频率内。如果是则可以进行更新。执行InterlockedAdd并标记mesh的cardid到RWQuadData[QuadDataInsertIndex]。 3.DirectLightingCardScatterContext.BuildScatterIndirectArgs,间接光照参数这里是通过FComputeShaderUtils::AddPass给到computeshader“InitializeCardScatterIndirectArgsCS”主要是初始化lumen间接光照的一些参数。 这些参数有两种模式,一种是RECT_LIST_TOPOLOGY,他就会记录RWCardIndirectArgs里面的数据为VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation。如果另一种模式则RWCardIndirectArgs记录为IndexCount, NumInstances, StartIndex, BaseVertexIndex, FirstInstance。 4.CombineLumenSceneLighting,合并lumen场景光照需要的这一步是通过GraphBuilder.AddPass通过光栅化的方式DrawQuadsToAtlas。他会执行到FLumenCardLightingEmissive这里,他会有顶点和片元着色。顶点用FRasterizeToCardsVS实现,片元用LumenCardLightingInitializePS实现的。主要是合并场景光照作用。 RasterizeToCardsVS这里主要做的就是转坐标,从lumen的card的数据转到屏幕坐标,最终输出两个,一个是屏幕坐标OutPosition,一个是mesh的card的vs到ps的数据CardInterpolants ? LumenCardLightingInitializePS这里就是简单的根据顶点着色的AtlasCoord采样RadiosityAtlas。 5.RenderDirectLightingForLumenScene,lumen直接光照计算会执行到FDeferredShadingSceneRenderer::RenderDirectLightingForLumenScene,主要是计算直线光的颜色。 光线追踪或者有号距离场:他会分平行光和其他光源的区别。如果是平行光则执行RenderDirectLightIntoLumenCards。然后看是否支持光线追踪,如果支持他会用光追FLumenDirectLightingHardwareRayTracingData。然后拿所有的可见光判断如果是直线光则RenderDirectLightIntoLumenCards,如果不是则先加入到GatheredLocalLights。 在RenderDirectLightIntoLumenCards中,会拿到虚拟纹理id(VirtualShadowMapId), 然后判断是否支持光追阴影bLumenUseHardwareRayTracedShadow,支持则执行RenderHardwareRayTracedShadowIntoLumenCards,具体到LumenSceneDirectShadowingHardwareRaytracing.cpp这里执行光追。 如果不支持光追则用网格的距离场来获取光照效果CullMeshSDFsForLightCards。 阴影及光照剔除如果不是平行光则所有光源及id先执行CardScatterContext.CullCardsToShape,也就最终执行到FCullCardsToShapeCS这里来剔除不可渲染的对象。然后执行RenderDirectLightIntoLumenCards,也就是执行到类似平行光的光照里面去做光照和阴影然后渲染直接光照。 在CullDistanceFieldObjectsForLight里面,实际上这里面只对有号距离场的阴影处理。首先通过FCullObjectsForShadowCS,也就是执行CullObjectsForShadowCS,对阴影剔除。 然后是ScatterObjectsToShadowTiles执行FShadowMeshSDFObjectCull,通过tile来把对应的shadow不可达的对象剔除。 然后执行FLumenCardDirectLighting来计算card的直接光照结果。执行LumenCardDirectLightingPS这个shader来执行片元着色,在里面计算光照衰减,以及其他各种光源,比如面光,虚拟纹理阴影,体积阴影,最终以辐照度的形式返回颜色。 ? 6.ApplyLumenCardAlbedo,合入漫反射信息为后续间接光使用这里会执行FLumenCardBlendAlbedoPS通过computeshader“LumenSceneLighting.usf”中的LumenCardBlendAlbedoPS合入漫反射效果。为后续间接光使用。 7.PrefilterLumenSceneLighting,过滤颜色这个执行到FDeferredShadingSceneRenderer::PrefilterLumenSceneLighting中。 通过computeshader执行到"/Engine/Private/Lumen/LumenSceneLighting.usf"的LumenCardPrefilterLightingPS,通过mrt执行三个颜色的赋值,OutLighting,OutColor1,OutColor2。分别是父级光照信息,直接辐照度颜色,间接辐照度颜色。 8.ComputeLumenSceneVoxelLighting,计算体素和有号距离场的间接光照可见对象这里是关于体素光照的计算,执行到FDeferredShadingSceneRenderer::ComputeLumenSceneVoxelLighting。他创建两个texture,一个是体素的光照颜色,一个是体素的可见性图。 8.1.更新区域然后执行UpdateVoxelVisBuffer,他有个ClipmapsToUpdate,也就是标记了要更新的体素区域,然后先执行FUploadVoxelLightingUpdateBoundsParameters更新区域 距离场步进获取可见对象然后是FClearIndirectAgrBuffersCS清理间接光的参数,FBuildUpdateGridTilesCS获取需要更新的当前clipmap中的块,这里在BuildUpdateGridTilesCS中通过UpdateBoundsIndex的几个索引然后在距离场中找是否距离小于等于0,如果是则说明在地下,记录该点。 ? FClearVisBuffer清理块中的可见对象,FCullToVoxelClipmapCS对clipmap区域内的对象剔除,在CullToVoxelClipmapCS也是通过距离场来查看对象边缘是否距离场可达 ? FSetupVoxelTracesCS用距离判断体素步进的对象,这里通过SetupVoxelTracesCS来通过ObjectIndex来看整个检查框DFObjectBounds是否在距离场内 ? FVoxelTraceCS开始步进,会利用距离场来步进,执行到LumenVoxelLighting.usf的VoxelTraceCS,其中会执行到RayTraceSingleMeshSDF对网格执行距离场步进,保存到RWVoxelVisBuffer里面是可见对象列表。这里就是关键的体素光照的步进。这里的VisBufferTextureCoord就是可见的。 ? 8.2.可见对象着色执行完UpdateVoxelVisBuffer后就是VoxelizeVisBuffer,然后用FClearVoxelLightingClipmapCS来清理原本的体素光照的clipmap,然后执行FCompactVisBufferCS获取可见性对象,然后执行FSetupVisBufferShadingCS设置可见对象的参数设置,FVisBufferShadingCS最终执行可见对象的着色。 ? 8.2.1.着色方式这里的颜色计算SampleLumenMeshCardsWithWeight中会拿到xyz三个轴的权重并且对三个轴进行进行采样SampleLumenCard。另外如果有距离场光照还会执行一次距离场的SampleLumenCard,最终整合颜色到Lighting中 ? 8.2.2.采样meshcard的颜色SampleLumenCard中对颜色采样会通过三张贴图之一确定,一个是FinalLightingAtlas,一个是IrradianceAtlas,一个是IndirectIrradianceAtlas,最终跟不透明贴图OpacityAtlas根据权重混合。 9.ComputeLumenTranslucencyGIVolume,计算lumen的半透明光照效果这里计算半透明渲染的全局光照,要有透明度还会用前一帧和当前帧做混合来减少锯齿。 9.1圆锥步进执行FTranslucencyLightingCS来计算半透明光照,他是用圆锥个数的步进来进行光照的,执行ConeTraceVoxels来步进,这里得出的结果是透明度和步进次数以及历史距离,如果有开启ENABLE_DYNAMIC_SKY_LIGHT也就是动态天光还会加上动态天光到颜色中。并且会加上球谐光照AddSH(Lighting, MulSH(SHBasisFunction(WorldConeDirection), TraceResult.Lighting * SampleWeight)); 9.2历史颜色混合然后用历史光照和当前光照混合到结果RWTranslucencyGI1中,并且保存颜色到RWTranslucencyGINewHistory1方便下次历史颜色混合。 ? 完成lumen着色最终把lumen计算出来的所有光照信息加入到view中。 ? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 16:27:33- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |