【DXR/UE4】DXR教程/UE4RTAO

2023-11-23 06:40
文章标签 ue4 教程 dxr ue4rtao

本文主要是介绍【DXR/UE4】DXR教程/UE4RTAO,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

DXR教程一

这个是Nvidia做的DXR的教程之一,总共14篇,主要是介绍DXR Api的使用,这套API还是非常繁琐的,如果一直关注细节的话很容易理不清思路。
事实上只需要关注TraceRay这个函数就可以很好的了解DXR的整体。这个流程中新的两个部分:加速结构(BLAS和TLAS)和ShaderTable都可以说是为TraceRay服务的,它们用于说明当ray与AccelerationStructure中的物体相交后执行哪部分程序。

Template<payload_t>
void TraceRay(RaytracingAccelerationStructure AccelerationStructure,uint RayFlags,uint InstanceInclusionMask,uint RayContributionToHitGroupIndex,uint MultiplierForGeometryContributionToHitGroupIndex,uint MissShaderIndex,RayDesc Ray,inout payload_t Payload);

第一个参数是使用的Top-Level Acceleration Structure。
第二个参数是Ray Flags,用于定义透明、裁剪一些提前操作。
第三个参数则用于拒绝某些Instance,

if(!((InstanceInclusionMask & InstanceMask) & 0xff)) { ignore intersection }
pInstanceDescs[i].InstanceMask = 0xFF;

当Instance的Mask设为0时,该instance会被忽略。
第四个参数是Ray Index,它的主要作用是索引次级光线。
第五个参数是两个Geometry的hit shader的距离。

教程13中的样例场景有3个实例,其中第一个实例有两个Geometry,一个是三角形,另一个是Plane,另外两个实例为三角形。同时击中后会产生一个再次发射一条阴影光线。
在这里插入图片描述
当RayGen Shader发射一条光线击中物体后,要确定接下来执行那个Hit Shader ,计算公式:

entryIndex =  
InstanceContributionToHitGroupIndex + 
GeometryIndex * MultiplierForGeometryContributionToShaderIndex + 
RayContributionToHitGroupIndex

假定击中的是Plane,那么就要执行hitshader,我们要去找hitShaderGroup的位置,HitGroupTable如下,它的起始的Offset是3个ShaderTableEntry的大小,包含8个HitShader。

	size_t hitOffset = 3 * mShaderTableEntrySize;raytraceDesc.HitGroupTable.StartAddress = mpShaderTable->GetGPUVirtualAddress() + hitOffset;raytraceDesc.HitGroupTable.StrideInBytes = mShaderTableEntrySize;raytraceDesc.HitGroupTable.SizeInBytes = mShaderTableEntrySize * 8;    // 8 hit-entries

找到HitShaderGroup的位置后,我们查找HitShader的索引。在上面EntryIndex的计算公式中,有两个是Shader中的参数:MultiplierForGeometryContributionToShaderIndex,
RayContributionToHitGroupIndex这两个在shader中指定,对于前者,是Instance中Geometry的数量,对于后者是Ray的index,因为是第一条光线所以Index=0。

InstanceContributionToHitGroupIndex在Top-Level AC中指定,用于说明当前的Instance在HitGroup中的位置,

	pInstanceDescs[0].InstanceID = 0;pInstanceDescs[0].InstanceContributionToHitGroupIndex = 0;``````for (int i = 1; i < 3; i++){pInstanceDescs[i].InstanceID = i;pInstanceDescs[i].InstanceContributionToHitGroupIndex = (i * 2) + 2;``````}

3个Instace的位置分别为0,4,6.

GeometryIndex用于说明这个Geometry在Instace中的位置,这个在Bottom-Level AC中指定,对于Instace0,Plane在其中的位置为1。

经过计算得到HitShader的Index为0+1*2+0=2,即执行hitGroup中的第三个Shader。

它的代码如下:

[shader("closesthit")]
void planeChs(inout RayPayload payload, in BuiltInTriangleIntersectionAttributes attribs)
{   ``````ShadowPayload Shadowpayload;TraceRay(gRtScene, 0 /*rayFlags*/, 0xFF, 1 /* ray index*/, 0, 1, ray, Shadowpayload);float factor = Shadowpayload.hit ? 0.1 : 1.0;payload.color = float4(0.9f, 0.9f, 0.9f, 1.0f) * factor;
}

也就是再发射次级光线进行阴影判断,所以Ray Index从0变成1,RayContributionToHitGroupIndex的值为1。
倒数第三个参数说明,如果未击中执行则执行MissGroup中的第2个Shader,index=1。

假设击中了Instance3,那么结果为:
entryIndex =
InstanceContributionToHitGroupIndex(6) +
GeometryIndex(0) * MultiplierForGeometryContributionToShaderIndex(0) +
RayContributionToHitGroupIndex(1)

即执行第8个shader,Index=7。

DXR剩下的部分(PipelineState,Resources等)类比光栅流程就可以了。

DXR教程二

第二份教程是在Falcor框架的基础上写的,同样是14节,与第一份教程相比,Falcor框架简化了DXR的操作,第一份教程的上千行代码在Falor框架下十几行就可以实现。

	pipeline->setPass(0, LightProbeGBufferPass::create());pipeline->setPass(1, GGXGlobalIlluminationPass::create("HDRColorOutput"));  pipeline->setPass(2, SimpleAccumulationPass::create("HDRColorOutput"));     pipeline->setPass(3, SimpleToneMappingPass::create("HDRColorOutput", ResourceManager::kOutputChannel)); 

总共四个Pass,第一个Pass是光栅化流程,输出一个GBuffer,包阔PosWorl,Normal,diffuse等信息。第2个Pass是RayTracing的核心,第三个Pass进行temporal accumulation,第四个Pass将结果输出。

第三个Pass的思路比较朴素,即如果前一帧和当前帧场景未发生改变,可以将前一帧(prevColor)的结果累加到当前帧(curColor),静止的帧数越多(gAccumCount),场景的噪点就会越小。

(gAccumCount * prevColor + curColor) / (gAccumCount + 1);

这个方法结合上相机位置的Jitter,不就在降噪的同时顺便进行了类似TAA的操作,Jitter是在第一个Pass中进行的。

第二个Pass的核心代码如下

	if (isGeometryValid){// Add any emissive color from primary raysshadeColor = gEmitMult * pixelEmissive.rgb;// (Optionally) do explicit direct lighting to a random light in the sceneif (gDoDirectGI)shadeColor += ggxDirect(randSeed, worldPos.xyz, worldNorm.xyz, V,difMatlColor.rgb, specMatlColor.rgb, roughness);// (Optionally) do indirect lighting for global illuminationif (gDoIndirectGI && (gMaxDepth > 0))shadeColor += ggxIndirect(randSeed, worldPos.xyz, worldNorm.xyz, noMapN,V, difMatlColor.rgb, specMatlColor.rgb, roughness, 0);}

如果当前击中点有效的话,进行直接光和间接光的计算。

在计算直接光的时候,为了减小计算量,教程在多个光源中随机选择一个光源计算,

	int lightToSample = min(int(nextRand(rndSeed) * gLightsCount), gLightsCount - 1);``````// Shoot our shadow ray to our randomly selected lightfloat shadowMult = float(gLightsCount) * shadowRayVisibility(hit, toLight, gMinT, distToLight);// Return the Lambertian shading color using the physically based Lambertian term (albedo / pi)return shadowMult * LdotN * lightIntensity * difColor / M_PI;

在计算间接光时,根据概率选择采样Diffuse还是Spec。

UE4 RTAO

选择了各种RT效果中最简单的RTAO来实现,主要是为了熟悉下UE Ray Tracing的流程,之前在DXR的API文档上已经浪费了够多时间了。

SSAO的问题就是只有屏幕信息,无法判断柱子后有没有物体。
在这里插入图片描述

RTAO就没有这个问题

在这里插入图片描述

#include "../Common.ush"
#include "../DeferredShadingCommon.ush"
#include "../Montecarlo.ush"
#include "../PathTracing/Utilities/PathTracingRandomSequence.ush"
#include "../SceneTextureParameters.ush"
#include"RayTracingCommon.ush"
#include "RayTracingDeferredShadingCommon.ush"
RaytracingAccelerationStructure TLAS;
RWTexture2D<float> RWAmbientOcclusionMaskUAV;
RWTexture2D<float> RWAmbientOcclusionHitDistanceUAV;RAY_TRACING_ENTRY_RAYGEN(MyRTAORGS)
{//recompileShaders changedconst uint gNumRays = 2;float IntensityLocal = 0.2;float Visibility = 0.0;uint2 PixelCoord = DispatchRaysIndex().xy + View.ViewRectMin;RandomSequence RandSequence;uint LinearIndex = CalcLinearIndex(PixelCoord);RandomSequence_Initialize(RandSequence, LinearIndex, View.StateFrameIndex);FGBufferData GBufferData = GetGBufferDataFromSceneTexturesLoad(PixelCoord);float DeviceZ = SceneDepthTexture.Load(int3(PixelCoord, 0)).r;float3 WorldPosition;float3 CameraDirection;ReconstructWorldPositionAndCameraDirectionFromDeviceZ(PixelCoord, DeviceZ, WorldPosition, CameraDirection);float3 WorldNormal = GBufferData.WorldNormal;float ClosestRayHitDistance = 10000.0;for (uint index = 0; index < gNumRays;index++){uint DummyVariable;float2 RandSample = RandomSequence_GenerateSample2D(RandSequence, DummyVariable);float3 Direction_Tangent;Direction_Tangent.xy = UniformSampleDiskConcentric(RandSample);Direction_Tangent.z = sqrt(1.0 - dot(Direction_Tangent.xy, Direction_Tangent.xy));float3 Direction_World = TangentToWorld(Direction_Tangent.xyz, WorldNormal);RayDesc Ray;Ray.Origin = WorldPosition;Ray.Direction = Direction_World;Ray.TMin = 0.01;Ray.TMax = 196.0;uint RayFlags = 0;const uint InstanceInclusionMask = RAY_TRACING_MASK_SHADOW | RAY_TRACING_MASK_THIN_SHADOW;float RayWeight = 1.0;FMinimalPayload MinimalPayload = TraceVisibilityRay(TLAS,RayFlags,InstanceInclusionMask,PixelCoord,Ray);Visibility += RayWeight * (MinimalPayload.IsMiss() ? 1.0 : (1.0 - IntensityLocal) * (MinimalPayload.HitT / Ray.TMax));if (MinimalPayload.IsHit()){ClosestRayHitDistance = min(ClosestRayHitDistance, MinimalPayload.HitT);}}RWAmbientOcclusionMaskUAV[PixelCoord] = Visibility / float(gNumRays);RWAmbientOcclusionHitDistanceUAV[PixelCoord] = ClosestRayHitDistance;}
#include"MyRTAO.h"
#include "DeferredShadingRenderer.h"#if RHI_RAYTRACING#include "ClearQuad.h"
#include "SceneRendering.h"
#include "SceneRenderTargets.h"
#include "SceneUtils.h"
#include "RenderTargetPool.h"
#include "RHIResources.h"
#include "UniformBuffer.h"
#include "RHI/Public/PipelineStateCache.h"
#include "Raytracing/RaytracingOptions.h"
#include "Raytracing/RayTracingMaterialHitShaders.h"//Note
#include "SceneTextureParameters.h"#include "PostProcess/PostProcessing.h"
#include "PostProcess/SceneFilterRendering.h"class FMyRTAORGS : public FGlobalShader
{DECLARE_GLOBAL_SHADER(FMyRTAORGS)SHADER_USE_ROOT_PARAMETER_STRUCT(FMyRTAORGS, FGlobalShader)static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters){return ShouldCompileRayTracingShadersForProject(Parameters.Platform);}BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )SHADER_PARAMETER_SRV(RaytracingAccelerationStructure, TLAS)SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWAmbientOcclusionMaskUAV)SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWAmbientOcclusionHitDistanceUAV)SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)END_SHADER_PARAMETER_STRUCT()
};
IMPLEMENT_GLOBAL_SHADER(FMyRTAORGS, "/Engine/Private/RayTracing/MyRTAORGS.usf", "MyRTAORGS", SF_RayGen);
void FDeferredShadingSceneRenderer::MyRenderRTAO(FRDGBuilder& GraphBuilder,FViewInfo& View,const FSceneTextureParameters& SceneTextures,FRDGTextureRef* OutAmbientOcclusionTexture)
#if RHI_RAYTRACING
{RDG_EVENT_SCOPE(GraphBuilder, "My_RTAO");IScreenSpaceDenoiser::FAmbientOcclusionInputs DenoiserInputs;{FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(SceneTextures.SceneDepthTexture->Desc.Extent,PF_R16F,FClearValueBinding::None,TexCreate_ShaderResource | TexCreate_RenderTargetable | TexCreate_UAV);DenoiserInputs.Mask = GraphBuilder.CreateTexture(Desc, TEXT("M_RTAO_TEX"));DenoiserInputs.RayHitDistance = GraphBuilder.CreateTexture(Desc, TEXT("M_RTAO_Hit_TEX"));}FMyRTAORGS::FParameters *PassParameters = GraphBuilder.AllocParameters<FMyRTAORGS::FParameters>();PassParameters->TLAS = View.RayTracingScene.RayTracingSceneRHI->GetShaderResourceView();PassParameters->RWAmbientOcclusionMaskUAV = GraphBuilder.CreateUAV(DenoiserInputs.Mask);PassParameters->RWAmbientOcclusionHitDistanceUAV = GraphBuilder.CreateUAV(DenoiserInputs.RayHitDistance);PassParameters->ViewUniformBuffer = View.ViewUniformBuffer;PassParameters->SceneTextures = SceneTextures;TShaderMapRef<FMyRTAORGS> RayGenerationShader(GetGlobalShaderMap(FeatureLevel));FIntPoint RayTracingResolution = View.ViewRect.Size();ClearUnusedGraphResources(RayGenerationShader, PassParameters);GraphBuilder.AddPass(RDG_EVENT_NAME("M_RTAO"),PassParameters,ERDGPassFlags::Compute,[PassParameters, this, &View, RayGenerationShader, RayTracingResolution](FRHICommandList& RHICmdList){FRayTracingShaderBindingsWriter GlobalResources;SetShaderParameters(GlobalResources, RayGenerationShader, *PassParameters);// TODO: Provide material support for opacity maskFRayTracingPipelineState* Pipeline = View.RayTracingMaterialPipeline;//------------------------------------------------------// Declare default pipelineFRayTracingPipelineStateInitializer Initializer;Initializer.MaxPayloadSizeInBytes = 64; // sizeof(FPackedMaterialClosestHitPayload)FRHIRayTracingShader* RayGenShaderTable[] = { RayGenerationShader.GetRayTracingShader() };Initializer.SetRayGenShaderTable(RayGenShaderTable);FRHIRayTracingShader* HitGroupTable[] = { View.ShaderMap->GetShader<FOpaqueShadowHitGroup>().GetRayTracingShader() };Initializer.SetHitGroupTable(HitGroupTable);Initializer.bAllowHitGroupIndexing = false; // Use the same hit shader for all geometry in the scene by disabling SBT indexing.Pipeline = PipelineStateCache::GetAndOrCreateRayTracingPipelineState(RHICmdList, Initializer);//---------------------------------------------------------FRHIRayTracingScene* RayTracingSceneRHI = View.RayTracingScene.RayTracingSceneRHI;RHICmdList.RayTraceDispatch(Pipeline, RayGenerationShader.GetRayTracingShader(), RayTracingSceneRHI, GlobalResources, RayTracingResolution.X, RayTracingResolution.Y);});int32 DenoiserMode = 1;if (DenoiserMode != 0){IScreenSpaceDenoiser::FAmbientOcclusionRayTracingConfig RayTracingConfig;RayTracingConfig.RayCountPerPixel = 2;const IScreenSpaceDenoiser* DefaultDenoiser = IScreenSpaceDenoiser::GetDefaultDenoiser();const IScreenSpaceDenoiser* DenoiserToUse = DenoiserMode == 1 ? DefaultDenoiser : GScreenSpaceDenoiser;RDG_EVENT_SCOPE(GraphBuilder, "%s%s(AmbientOcclusion) %dx%d",DenoiserToUse != DefaultDenoiser ? TEXT("ThirdParty ") : TEXT(""),DenoiserToUse->GetDebugName(),View.ViewRect.Width(), View.ViewRect.Height());IScreenSpaceDenoiser::FAmbientOcclusionOutputs DenoiserOutputs = DenoiserToUse->DenoiseAmbientOcclusion(GraphBuilder,View,&View.PrevViewInfo,SceneTextures,DenoiserInputs,RayTracingConfig);*OutAmbientOcclusionTexture = DenoiserOutputs.AmbientOcclusionMask;
}else{*OutAmbientOcclusionTexture = DenoiserInputs.Mask;}
}
#else
{unimplemented();
}
#endif
#endif

这篇关于【DXR/UE4】DXR教程/UE4RTAO的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/416090

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

沁恒CH32在MounRiver Studio上环境配置以及使用详细教程

目录 1.  RISC-V简介 2.  CPU架构现状 3.  MounRiver Studio软件下载 4.  MounRiver Studio软件安装 5.  MounRiver Studio软件介绍 6.  创建工程 7.  编译代码 1.  RISC-V简介         RISC就是精简指令集计算机(Reduced Instruction SetCom

前端技术(七)——less 教程

一、less简介 1. less是什么? less是一种动态样式语言,属于css预处理器的范畴,它扩展了CSS语言,增加了变量、Mixin、函数等特性,使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 ,也可以借助Node.js在服务端运行。 less的中文官网:https://lesscss.cn/ 2. less编译工具 koala 官网 http://koala-app.

【Shiro】Shiro 的学习教程(三)之 SpringBoot 集成 Shiro

目录 1、环境准备2、引入 Shiro3、实现认证、退出3.1、使用死数据实现3.2、引入数据库,添加注册功能后端代码前端代码 3.3、MD5、Salt 的认证流程 4.、实现授权4.1、基于角色授权4.2、基于资源授权 5、引入缓存5.1、EhCache 实现缓存5.2、集成 Redis 实现 Shiro 缓存 1、环境准备 新建一个 SpringBoot 工程,引入依赖:

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

PHP APC缓存函数使用教程

APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。(Linux APC扩展安装) 系统缓存 它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存 3600s(一小时)。但是这样仍会浪费大量C

Qt多语种开发教程

Qt作为跨平台的开发工具,早已应用到各行各业的软件开发中。 今天讲讲,Qt开发的正序怎么做多语言开发。就是说,你设置中文,就中文显示;设置英语就英文显示,设置繁体就繁体显示,设置发育就显示法语等。 开发环境(其实多语种这块根环境没太大关系):win10,Qt.5.12.10 一.先用QtCreator创建一个简单的桌面程序 1.工程就随便命名“LanguageTest”,其他默认。 2.在设计师

如何打造个性化大学生线上聊天交友系统?Java SpringBoot Vue教程,2025最新设计思路

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 | SpringBoot/SSM Python实战项目 | Django 微信小程序/安卓实战项目 大数据实战项目 ⚡⚡文末获取源码 文章目录