```c++ // Manually clamp scene texture UV as if using a clamp sampler. MaterialFloat2 ClampSceneTextureUV(MaterialFloat2 BufferUV, const uint SceneTextureId) { float4 MinMax = GetSceneTextureUVMinMax(SceneTextureId); return clamp(BufferUV, MinMax.xy, MinMax.zw); } ``` ## 相关函数的HLSL代码 ```c++ float GetPixelDepth(FMaterialVertexParameters Parameters) { FLATTEN if (View.ViewToClip[3][3] < 1.0f) { // Perspective return GetScreenPosition(Parameters).w; } else { // Ortho return ConvertFromDeviceZ(GetScreenPosition(Parameters).z); } } float GetPixelDepth(FMaterialPixelParameters Parameters) { FLATTEN if (View.ViewToClip[3][3] < 1.0f) { // Perspective return GetScreenPosition(Parameters).w; } else { // Ortho return ConvertFromDeviceZ(GetScreenPosition(Parameters).z); } } float2 GetSceneTextureUV(FMaterialVertexParameters Parameters) { return ScreenAlignedPosition(GetScreenPosition(Parameters)); } float2 GetSceneTextureUV(FMaterialPixelParameters Parameters) { return SvPositionToBufferUV(Parameters.SvPosition); } float2 GetViewportUV(FMaterialVertexParameters Parameters) { #if POST_PROCESS_MATERIAL return Parameters.WorldPosition.xy; #else return BufferUVToViewportUV(GetSceneTextureUV(Parameters)); #endif } float2 GetPixelPosition(FMaterialVertexParameters Parameters) { return GetViewportUV(Parameters) * View.ViewSizeAndInvSize.xy; } #if POST_PROCESS_MATERIAL float2 GetPixelPosition(FMaterialPixelParameters Parameters) { return Parameters.SvPosition.xy - float2(PostProcessOutput_ViewportMin); } float2 GetViewportUV(FMaterialPixelParameters Parameters) { return GetPixelPosition(Parameters) * PostProcessOutput_ViewportSizeInverse; } #else float2 GetPixelPosition(FMaterialPixelParameters Parameters) { return Parameters.SvPosition.xy - float2(View.ViewRectMin.xy); } float2 GetViewportUV(FMaterialPixelParameters Parameters) { return SvPositionToViewportUV(Parameters.SvPosition); } ``` ## 本质上是调用了SceneTextureLookup float4 SceneTextureLookup(float2 UV, int SceneTextureIndex, bool bFiltered) { FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV, false); switch(SceneTextureIndex) { // order needs to match to ESceneTextureId case PPI_SceneColor: return float4(CalcSceneColor(UV), 0); case PPI_SceneDepth: return ScreenSpaceData.GBuffer.Depth; case PPI_DiffuseColor: return float4(ScreenSpaceData.GBuffer.DiffuseColor, 0); case PPI_SpecularColor: return float4(ScreenSpaceData.GBuffer.SpecularColor, 0); case PPI_SubsurfaceColor: return IsSubsurfaceModel(ScreenSpaceData.GBuffer.ShadingModelID) ? float4( ExtractSubsurfaceColor(ScreenSpaceData.GBuffer), ScreenSpaceData.GBuffer.CustomData.a ) : ScreenSpaceData.GBuffer.CustomData; case PPI_BaseColor: return float4(ScreenSpaceData.GBuffer.BaseColor, 0); case PPI_Specular: return ScreenSpaceData.GBuffer.Specular; case PPI_Metallic: return ScreenSpaceData.GBuffer.Metallic; case PPI_WorldNormal: return float4(ScreenSpaceData.GBuffer.WorldNormal, 0); case PPI_SeparateTranslucency: return float4(1, 1, 1, 1); // todo case PPI_Opacity: return ScreenSpaceData.GBuffer.CustomData.a; case PPI_Roughness: return ScreenSpaceData.GBuffer.Roughness; case PPI_MaterialAO: return ScreenSpaceData.GBuffer.GBufferAO; case PPI_CustomDepth: return ScreenSpaceData.GBuffer.CustomDepth; case PPI_PostProcessInput0: return Texture2DSample(PostProcessInput_0_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_0_SharedSampler, UV); case PPI_PostProcessInput1: return Texture2DSample(PostProcessInput_1_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_1_SharedSampler, UV); case PPI_PostProcessInput2: return Texture2DSample(PostProcessInput_2_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_2_SharedSampler, UV); case PPI_PostProcessInput3: return Texture2DSample(PostProcessInput_3_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_3_SharedSampler, UV); case PPI_PostProcessInput4: return Texture2DSample(PostProcessInput_4_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_4_SharedSampler, UV); case PPI_DecalMask: return 0; // material compiler will return an error case PPI_ShadingModelColor: return float4(GetShadingModelColor(ScreenSpaceData.GBuffer.ShadingModelID), 1); case PPI_ShadingModelID: return float4(ScreenSpaceData.GBuffer.ShadingModelID, 0, 0, 0); case PPI_AmbientOcclusion: return ScreenSpaceData.AmbientOcclusion; case PPI_CustomStencil: return ScreenSpaceData.GBuffer.CustomStencil; case PPI_StoredBaseColor: return float4(ScreenSpaceData.GBuffer.StoredBaseColor, 0); case PPI_StoredSpecular: return float4(ScreenSpaceData.GBuffer.StoredSpecular.rrr, 0); case PPI_WorldTangent: return float4(ScreenSpaceData.GBuffer.WorldTangent, 0); case PPI_Anisotropy: return ScreenSpaceData.GBuffer.Anisotropy; default: return float4(0, 0, 0, 0); } } ## FScreenSpaceData GetScreenSpaceData(float2 UV, bool bGetNormalizedNormal = true) { FScreenSpaceData Out; Out.GBuffer = GetGBufferData(UV, bGetNormalizedNormal); float4 ScreenSpaceAO = Texture2DSampleLevel(SceneTexturesStruct.ScreenSpaceAOTexture, SceneTexturesStruct_ScreenSpaceAOTextureSampler, UV, 0); Out.AmbientOcclusion = ScreenSpaceAO.r; return Out; } ## GetGBufferData使用的GBufferXTexture的传入位置 比如AOUpsamplePS(c++中为FDistanceFieldAOUpsamplePS)就带有FSceneTextureUniformParameters, SceneTextures。都是由对应的渲染函数的TRDGUniformBufferRef SceneTexturesUniformBuffer形参传入。 ```c# FGBufferData GetGBufferData(float2 UV, bool bGetNormalizedNormal = true) { float4 GBufferA = Texture2DSampleLevel(SceneTexturesStruct.GBufferATexture, SceneTexturesStruct_GBufferATextureSampler, UV, 0); float4 GBufferB = Texture2DSampleLevel(SceneTexturesStruct.GBufferBTexture, SceneTexturesStruct_GBufferBTextureSampler, UV, 0); float4 GBufferC = Texture2DSampleLevel(SceneTexturesStruct.GBufferCTexture, SceneTexturesStruct_GBufferCTextureSampler, UV, 0); float4 GBufferD = Texture2DSampleLevel(SceneTexturesStruct.GBufferDTexture, SceneTexturesStruct_GBufferDTextureSampler, UV, 0); float CustomNativeDepth = Texture2DSampleLevel(SceneTexturesStruct.CustomDepthTexture, SceneTexturesStruct_CustomDepthTextureSampler, UV, 0).r; int2 IntUV = (int2)trunc(UV * View.BufferSizeAndInvSize.xy); uint CustomStencil = SceneTexturesStruct.CustomStencilTexture.Load(int3(IntUV, 0)) STENCIL_COMPONENT_SWIZZLE; #if ALLOW_STATIC_LIGHTING float4 GBufferE = Texture2DSampleLevel(SceneTexturesStruct.GBufferETexture, SceneTexturesStruct_GBufferETextureSampler, UV, 0); #else float4 GBufferE = 1; #endif float4 GBufferF = Texture2DSampleLevel(SceneTexturesStruct.GBufferFTexture, SceneTexturesStruct_GBufferFTextureSampler, UV, 0); #if WRITES_VELOCITY_TO_GBUFFER float4 GBufferVelocity = Texture2DSampleLevel(SceneTexturesStruct.GBufferVelocityTexture, SceneTexturesStruct_GBufferVelocityTextureSampler, UV, 0); #else float4 GBufferVelocity = 0; #endif float SceneDepth = CalcSceneDepth(UV); //FGBufferData DecodeGBufferData()通过解码GBuffer之后返回FGBufferData 结构体 return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); } ``` ## GetGBufferDataFromSceneTextures中使用的GBufferXTexture的传入位置 SingleLayerWaterCompositePS中使用了GetGBufferDataFromSceneTextures()来获取GBuffer,这个数据是在SingleLayerWaterRendering.cpp中传入的。传入的变量FSingleLayerWaterCommonShaderParameters->FSceneTextureParameters SceneTextures中带有GBufferABCEDF与Depth、Stencil、Velocity贴图。 ```c++ Texture2D SceneDepthTexture; Texture2D SceneStencilTexture; Texture2D GBufferATexture; Texture2D GBufferBTexture; Texture2D GBufferCTexture; Texture2D GBufferDTexture; Texture2D GBufferETexture; Texture2D GBufferVelocityTexture; Texture2D GBufferFTexture; Texture2D SceneLightingChannels; FGBufferData GetGBufferDataFromSceneTextures(float2 UV, bool bGetNormalizedNormal = true) { float4 GBufferA = GBufferATexture.SampleLevel(GBufferATextureSampler, UV, 0); float4 GBufferB = GBufferBTexture.SampleLevel(GBufferBTextureSampler, UV, 0); float4 GBufferC = GBufferCTexture.SampleLevel(GBufferCTextureSampler, UV, 0); float4 GBufferD = GBufferDTexture.SampleLevel(GBufferDTextureSampler, UV, 0); float4 GBufferE = GBufferETexture.SampleLevel(GBufferETextureSampler, UV, 0); float4 GBufferF = GBufferFTexture.SampleLevel(GBufferFTextureSampler, UV, 0); float4 GBufferVelocity = GBufferVelocityTexture.SampleLevel(GBufferVelocityTextureSampler, UV, 0); uint CustomStencil = 0; float CustomNativeDepth = 0; float DeviceZ = SampleDeviceZFromSceneTextures(UV); float SceneDepth = ConvertFromDeviceZ(DeviceZ); //FGBufferData DecodeGBufferData()通过解码GBuffer之后返回FGBufferData 结构体 return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); } ```