UE5.1移动端PreintegratedSkinBxDF解析
Part 1
头文件 MobileBasePassPixelShader.usf
主要看Main函数:
#if MOBILE_MULTI_VIEWResolvedView = ResolveView(BasePassInterpolants.MultiViewId);
#elseResolvedView = ResolveView();
#endif
这玩意Shader文件找不到,感觉是个全局变量的东西。万幸有大佬搞出来了,具体怎么弄我也不懂==》UE4-Render-RenderPrePass-HLSL
头文件 InstancedStereo.ush#define PrimaryView GetPrimaryView()static ViewState ResolvedView = (ViewState)0.0f;ViewState ResolveView()
{return GetPrimaryView();
}...#if !(COMPILER_METAL && (COMPILER_HLSLCC == 1)) && (INSTANCED_STEREO || MOBILE_MULTI_VIEW)
ViewState ResolveView(uint ViewIndex)
{if (ViewIndex == 0){return GetPrimaryView();}else{return GetInstancedView();}
}
#endif
Part 2 ViewState
struct ViewState
{float4x4 TranslatedWorldToClip;float4x4 WorldToClip;float4x4 TranslatedWorldToView;float4x4 ViewToTranslatedWorld;float4x4 TranslatedWorldToCameraView;float4x4 CameraViewToTranslatedWorld;float4x4 ViewToClip;float4x4 ViewToClipNoAA;float4x4 ClipToView;float4x4 ClipToTranslatedWorld;float4x4 SVPositionToTranslatedWorld;float4x4 ScreenToWorld;float4x4 ScreenToTranslatedWorld;float3 ViewForward;float3 ViewUp;float3 ViewRight;float3 HMDViewNoRollUp;float3 HMDViewNoRollRight;float4 InvDeviceZToWorldZTransform;float4 ScreenPositionScaleBias;float3 WorldCameraOrigin;float3 TranslatedWorldCameraOrigin;float3 WorldViewOrigin;float3 PreViewTranslation;float4x4 PrevProjection;float4x4 PrevViewProj;float4x4 PrevViewRotationProj;float4x4 PrevViewToClip;float4x4 PrevClipToView;float4x4 PrevTranslatedWorldToClip;float4x4 PrevTranslatedWorldToView;float4x4 PrevViewToTranslatedWorld;float4x4 PrevTranslatedWorldToCameraView;float4x4 PrevCameraViewToTranslatedWorld;float3 PrevWorldCameraOrigin;float3 PrevWorldViewOrigin;float3 PrevPreViewTranslation;float4x4 PrevInvViewProj;float4x4 PrevScreenToTranslatedWorld;float4x4 ClipToPrevClip;float4 TemporalAAJitter;float4 GlobalClippingPlane;float2 FieldOfViewWideAngles;float2 PrevFieldOfViewWideAngles;float4 ViewRectMin;float4 ViewSizeAndInvSize;float4 BufferSizeAndInvSize;float4 BufferBilinearUVMinMax;int NumSceneColorMSAASamples;float PreExposure;float OneOverPreExposure;float4 DiffuseOverrideParameter;float4 SpecularOverrideParameter;float4 NormalOverrideParameter;float2 RoughnessOverrideParameter;float PrevFrameGameTime;float PrevFrameRealTime;float OutOfBoundsMask;float3 WorldCameraMovementSinceLastFrame;float CullingSign;float NearPlane;float AdaptiveTessellationFactor;float GameTime;float RealTime;float MaterialTextureMipBias;float MaterialTextureDerivativeMultiply;uint Random;uint FrameNumber;uint StateFrameIndexMod8;float CameraCut;float UnlitViewmodeMask;float4 DirectionalLightColor;float3 DirectionalLightDirection;float4 TranslucencyLightingVolumeMin[2];float4 TranslucencyLightingVolumeInvSize[2];float4 TemporalAAParams;float4 CircleDOFParams;float DepthOfFieldSensorWidth;float DepthOfFieldFocalDistance;float DepthOfFieldScale;float DepthOfFieldFocalLength;float DepthOfFieldFocalRegion;float DepthOfFieldNearTransitionRegion;float DepthOfFieldFarTransitionRegion;float MotionBlurNormalizedToPixel;float bSubsurfacePostprocessEnabled;float GeneralPurposeTweak;float DemosaicVposOffset;float3 IndirectLightingColorScale;float HDR32bppEncodingMode;float3 AtmosphericFogSunDirection;float AtmosphericFogSunPower;float AtmosphericFogPower;float AtmosphericFogDensityScale;float AtmosphericFogDensityOffset;float AtmosphericFogGroundOffset;float AtmosphericFogDistanceScale;float AtmosphericFogAltitudeScale;float AtmosphericFogHeightScaleRayleigh;float AtmosphericFogStartDistance;float AtmosphericFogDistanceOffset;float AtmosphericFogSunDiscScale;uint AtmosphericFogRenderMask;uint AtmosphericFogInscatterAltitudeSampleNum;float4 AtmosphericFogSunColor;float3 NormalCurvatureToRoughnessScaleBias;float RenderingReflectionCaptureMask;float4 AmbientCubemapTint;float AmbientCubemapIntensity;float SkyLightParameters;float4 SkyLightColor;float4 SkyIrradianceEnvironmentMap[7];float MobilePreviewMode;float HMDEyePaddingOffset;float ReflectionCubemapMaxMip;float ShowDecalsMask;uint DistanceFieldAOSpecularOcclusionMode;float IndirectCapsuleSelfShadowingIntensity;float3 ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight;int StereoPassIndex;float4 GlobalVolumeCenterAndExtent[4];float4 GlobalVolumeWorldToUVAddAndMul[4];float GlobalVolumeDimension;float GlobalVolumeTexelSize;float MaxGlobalDistance;float bCheckerboardSubsurfaceProfileRendering;float3 VolumetricFogInvGridSize;float3 VolumetricFogGridZParams;float2 VolumetricFogSVPosToVolumeUV;float VolumetricFogMaxDistance;float3 VolumetricLightmapWorldToUVScale;float3 VolumetricLightmapWorldToUVAdd;float3 VolumetricLightmapIndirectionTextureSize;float VolumetricLightmapBrickSize;float3 VolumetricLightmapBrickTexelSize;float StereoIPD;
};
Part 3 GetPrimaryView()
ViewState GetPrimaryView()
{ViewState Result;Result.TranslatedWorldToClip = View_TranslatedWorldToClip;Result.WorldToClip = View_WorldToClip;Result.TranslatedWorldToView = View_TranslatedWorldToView;Result.ViewToTranslatedWorld = View_ViewToTranslatedWorld;Result.TranslatedWorldToCameraView = View_TranslatedWorldToCameraView;Result.CameraViewToTranslatedWorld = View_CameraViewToTranslatedWorld;Result.ViewToClip = View_ViewToClip;Result.ViewToClipNoAA = View_ViewToClipNoAA;Result.ClipToView = View_ClipToView;Result.ClipToTranslatedWorld = View_ClipToTranslatedWorld;Result.SVPositionToTranslatedWorld = View_SVPositionToTranslatedWorld;Result.ScreenToWorld = View_ScreenToWorld;Result.ScreenToTranslatedWorld = View_ScreenToTranslatedWorld;Result.ViewForward = View_ViewForward;Result.ViewUp = View_ViewUp;Result.ViewRight = View_ViewRight;Result.HMDViewNoRollUp = View_HMDViewNoRollUp;Result.HMDViewNoRollRight = View_HMDViewNoRollRight;Result.InvDeviceZToWorldZTransform = View_InvDeviceZToWorldZTransform;Result.ScreenPositionScaleBias = View_ScreenPositionScaleBias;Result.WorldCameraOrigin = View_WorldCameraOrigin;Result.TranslatedWorldCameraOrigin = View_TranslatedWorldCameraOrigin;Result.WorldViewOrigin = View_WorldViewOrigin;Result.PreViewTranslation = View_PreViewTranslation;Result.PrevProjection = View_PrevProjection;Result.PrevViewProj = View_PrevViewProj;Result.PrevViewRotationProj = View_PrevViewRotationProj;Result.PrevViewToClip = View_PrevViewToClip;Result.PrevClipToView = View_PrevClipToView;Result.PrevTranslatedWorldToClip = View_PrevTranslatedWorldToClip;Result.PrevTranslatedWorldToView = View_PrevTranslatedWorldToView;Result.PrevViewToTranslatedWorld = View_PrevViewToTranslatedWorld;Result.PrevTranslatedWorldToCameraView = View_PrevTranslatedWorldToCameraView;Result.PrevCameraViewToTranslatedWorld = View_PrevCameraViewToTranslatedWorld;Result.PrevWorldCameraOrigin = View_PrevWorldCameraOrigin;Result.PrevWorldViewOrigin = View_PrevWorldViewOrigin;Result.PrevPreViewTranslation = View_PrevPreViewTranslation;Result.PrevInvViewProj = View_PrevInvViewProj;Result.PrevScreenToTranslatedWorld = View_PrevScreenToTranslatedWorld;Result.ClipToPrevClip = View_ClipToPrevClip;Result.TemporalAAJitter = View_TemporalAAJitter;Result.GlobalClippingPlane = View_GlobalClippingPlane;Result.FieldOfViewWideAngles = View_FieldOfViewWideAngles;Result.PrevFieldOfViewWideAngles = View_PrevFieldOfViewWideAngles;Result.ViewRectMin = View_ViewRectMin;Result.ViewSizeAndInvSize = View_ViewSizeAndInvSize;Result.BufferSizeAndInvSize = View_BufferSizeAndInvSize;Result.BufferBilinearUVMinMax = View_BufferBilinearUVMinMax;Result.NumSceneColorMSAASamples = View_NumSceneColorMSAASamples;Result.PreExposure = View_PreExposure;Result.OneOverPreExposure = View_OneOverPreExposure;Result.DiffuseOverrideParameter = View_DiffuseOverrideParameter;Result.SpecularOverrideParameter = View_SpecularOverrideParameter;Result.NormalOverrideParameter = View_NormalOverrideParameter;Result.RoughnessOverrideParameter = View_RoughnessOverrideParameter;Result.PrevFrameGameTime = View_PrevFrameGameTime;Result.PrevFrameRealTime = View_PrevFrameRealTime;Result.OutOfBoundsMask = View_OutOfBoundsMask;Result.WorldCameraMovementSinceLastFrame = View_WorldCameraMovementSinceLastFrame;Result.CullingSign = View_CullingSign;Result.NearPlane = View_NearPlane;Result.AdaptiveTessellationFactor = View_AdaptiveTessellationFactor;Result.GameTime = View_GameTime;Result.RealTime = View_RealTime;Result.MaterialTextureMipBias = View_MaterialTextureMipBias;Result.MaterialTextureDerivativeMultiply = View_MaterialTextureDerivativeMultiply;Result.Random = View_Random;Result.FrameNumber = View_FrameNumber;Result.StateFrameIndexMod8 = View_StateFrameIndexMod8;Result.CameraCut = View_CameraCut;Result.UnlitViewmodeMask = View_UnlitViewmodeMask;Result.DirectionalLightColor = View_DirectionalLightColor;Result.DirectionalLightDirection = View_DirectionalLightDirection;Result.TranslucencyLightingVolumeMin = View_TranslucencyLightingVolumeMin;Result.TranslucencyLightingVolumeInvSize = View_TranslucencyLightingVolumeInvSize;Result.TemporalAAParams = View_TemporalAAParams;Result.CircleDOFParams = View_CircleDOFParams;Result.DepthOfFieldSensorWidth = View_DepthOfFieldSensorWidth;Result.DepthOfFieldFocalDistance = View_DepthOfFieldFocalDistance;Result.DepthOfFieldScale = View_DepthOfFieldScale;Result.DepthOfFieldFocalLength = View_DepthOfFieldFocalLength;Result.DepthOfFieldFocalRegion = View_DepthOfFieldFocalRegion;Result.DepthOfFieldNearTransitionRegion = View_DepthOfFieldNearTransitionRegion;Result.DepthOfFieldFarTransitionRegion = View_DepthOfFieldFarTransitionRegion;Result.MotionBlurNormalizedToPixel = View_MotionBlurNormalizedToPixel;Result.bSubsurfacePostprocessEnabled = View_bSubsurfacePostprocessEnabled;Result.GeneralPurposeTweak = View_GeneralPurposeTweak;Result.DemosaicVposOffset = View_DemosaicVposOffset;Result.IndirectLightingColorScale = View_IndirectLightingColorScale;Result.HDR32bppEncodingMode = View_HDR32bppEncodingMode;Result.AtmosphericFogSunDirection = View_AtmosphericFogSunDirection;Result.AtmosphericFogSunPower = View_AtmosphericFogSunPower;Result.AtmosphericFogPower = View_AtmosphericFogPower;Result.AtmosphericFogDensityScale = View_AtmosphericFogDensityScale;Result.AtmosphericFogDensityOffset = View_AtmosphericFogDensityOffset;Result.AtmosphericFogGroundOffset = View_AtmosphericFogGroundOffset;Result.AtmosphericFogDistanceScale = View_AtmosphericFogDistanceScale;Result.AtmosphericFogAltitudeScale = View_AtmosphericFogAltitudeScale;Result.AtmosphericFogHeightScaleRayleigh = View_AtmosphericFogHeightScaleRayleigh;Result.AtmosphericFogStartDistance = View_AtmosphericFogStartDistance;Result.AtmosphericFogDistanceOffset = View_AtmosphericFogDistanceOffset;Result.AtmosphericFogSunDiscScale = View_AtmosphericFogSunDiscScale;Result.AtmosphericFogRenderMask = View_AtmosphericFogRenderMask;Result.AtmosphericFogInscatterAltitudeSampleNum = View_AtmosphericFogInscatterAltitudeSampleNum;Result.AtmosphericFogSunColor = View_AtmosphericFogSunColor;Result.NormalCurvatureToRoughnessScaleBias = View_NormalCurvatureToRoughnessScaleBias;Result.RenderingReflectionCaptureMask = View_RenderingReflectionCaptureMask;Result.AmbientCubemapTint = View_AmbientCubemapTint;Result.AmbientCubemapIntensity = View_AmbientCubemapIntensity;Result.SkyLightParameters = View_SkyLightParameters;Result.SkyLightColor = View_SkyLightColor;Result.SkyIrradianceEnvironmentMap = View_SkyIrradianceEnvironmentMap;Result.MobilePreviewMode = View_MobilePreviewMode;Result.HMDEyePaddingOffset = View_HMDEyePaddingOffset;Result.ReflectionCubemapMaxMip = View_ReflectionCubemapMaxMip;Result.ShowDecalsMask = View_ShowDecalsMask;Result.DistanceFieldAOSpecularOcclusionMode = View_DistanceFieldAOSpecularOcclusionMode;Result.IndirectCapsuleSelfShadowingIntensity = View_IndirectCapsuleSelfShadowingIntensity;Result.ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight = View_ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight;Result.StereoPassIndex = View_StereoPassIndex;Result.GlobalVolumeCenterAndExtent = View_GlobalVolumeCenterAndExtent;Result.GlobalVolumeWorldToUVAddAndMul = View_GlobalVolumeWorldToUVAddAndMul;Result.GlobalVolumeDimension = View_GlobalVolumeDimension;Result.GlobalVolumeTexelSize = View_GlobalVolumeTexelSize;Result.MaxGlobalDistance = View_MaxGlobalDistance;Result.bCheckerboardSubsurfaceProfileRendering = View_bCheckerboardSubsurfaceProfileRendering;Result.VolumetricFogInvGridSize = View_VolumetricFogInvGridSize;Result.VolumetricFogGridZParams = View_VolumetricFogGridZParams;Result.VolumetricFogSVPosToVolumeUV = View_VolumetricFogSVPosToVolumeUV;Result.VolumetricFogMaxDistance = View_VolumetricFogMaxDistance;Result.VolumetricLightmapWorldToUVScale = View_VolumetricLightmapWorldToUVScale;Result.VolumetricLightmapWorldToUVAdd = View_VolumetricLightmapWorldToUVAdd;Result.VolumetricLightmapIndirectionTextureSize = View_VolumetricLightmapIndirectionTextureSize;Result.VolumetricLightmapBrickSize = View_VolumetricLightmapBrickSize;Result.VolumetricLightmapBrickTexelSize = View_VolumetricLightmapBrickTexelSize;Result.StereoIPD = View_StereoIPD;return Result;
}
Part 4
没明白这个DiffuseOverrideParameter是干嘛的
#if (MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE || MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE || MATERIAL_SHADINGMODEL_CLOTH || MATERIAL_SHADINGMODEL_EYE) if (ShadingModelID == SHADINGMODELID_SUBSURFACE || ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN || ShadingModelID == SHADINGMODELID_SUBSURFACE_PROFILE || ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE || ShadingModelID == SHADINGMODELID_CLOTH || ShadingModelID == SHADINGMODELID_EYE){half4 SubsurfaceData = GetMaterialSubsurfaceData(PixelMaterialInputs);// If the subsurface feature is disabled, the subsurface color should be black// This will also ensure that the subsurface profile does not contribute when subsurface scattering is disabledSubsurfaceData *= View.bSubsurfacePostprocessEnabled;if (ShadingModelID == SHADINGMODELID_SUBSURFACE || ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN || ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE){SubsurfaceColor = SubsurfaceData.rgb * ResolvedView.DiffuseOverrideParameter.w + ResolvedView.DiffuseOverrideParameter.xyz;}else if (ShadingModelID == SHADINGMODELID_CLOTH){SubsurfaceColor = SubsurfaceData.rgb;}SubsurfaceProfile = SubsurfaceData.a;}
#endif
获取材质上的SubsurfaceColor
// .rgb:SubsurfaceColor, .a:SSProfileId in 0..1 range
half4 GetMaterialSubsurfaceDataRaw(FPixelMaterialInputs PixelMaterialInputs)
{return PixelMaterialInputs.Subsurface;
}half4 GetMaterialSubsurfaceData(FPixelMaterialInputs PixelMaterialInputs)
{half4 OutSubsurface = GetMaterialSubsurfaceDataRaw(PixelMaterialInputs);OutSubsurface.rgb = saturate(OutSubsurface.rgb);return OutSubsurface;
}
SetGBufferForShadingModel函数:把SubsurfaceColor和Opacity放进GBuffer.CustomData
SetGBufferForShadingModel(GBuffer,MaterialParameters,Opacity,BaseColor,Metallic,Specular,Roughness,Anisotropy,SubsurfaceColor,SubsurfaceProfile,0.0f,ShadingModelID);···#if MATERIAL_SHADINGMODEL_PREINTEGRATED_SKINelse if (ShadingModel == SHADINGMODELID_PREINTEGRATED_SKIN){GBuffer.CustomData.rgb = EncodeSubsurfaceColor(SubsurfaceColor);GBuffer.CustomData.a = Opacity;}
#endif···float3 EncodeSubsurfaceColor(float3 SubsurfaceColor)
{return sqrt(saturate(SubsurfaceColor));
}
计算GBuffer.SpecularColor和GBuffer.DiffuseColor
#if NONMETALGBuffer.DiffuseColor = GBuffer.BaseColor;GBuffer.SpecularColor = 0.04;
#elseGBuffer.SpecularColor = ComputeF0(GBuffer.Specular, GBuffer.BaseColor, GBuffer.Metallic);GBuffer.DiffuseColor = GBuffer.BaseColor - GBuffer.BaseColor * GBuffer.Metallic;
#endif
这个MOBILE_EMULATION宏的意思是移动模拟?只在开发中用到?
#if MOBILE_EMULATION && !MOBILE_DEFERRED_LIGHTING{// this feature is only needed for development/editor - we can compile it out for a shipping build (see r.CompileShadersForDevelopment cvar help)GBuffer.DiffuseColor = GBuffer.DiffuseColor * ResolvedView.DiffuseOverrideParameter.w + ResolvedView.DiffuseOverrideParameter.xyz;GBuffer.SpecularColor = GBuffer.SpecularColor * ResolvedView.SpecularOverrideParameter.w + ResolvedView.SpecularOverrideParameter.xyz;}
#endif
把SubsurfaceColor加到间接漫反射上
half IndirectIrradiance = 0;half3 DiffuseIndirectLighting = 0;half3 SubsurfaceIndirectLighting = 0;half3 DiffuseColorForIndirect = GBuffer.DiffuseColor;half3 DiffuseDir = ShadingOcclusion.BentNormal;#if MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKINif (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN){// Add subsurface energy to diffuse//@todo - better subsurface handling for these shading models with skylight and precomputed GIDiffuseColorForIndirect += SubsurfaceColor;}
#endif
获取预计算间接光照和天光
GetPrecomputedIndirectLightingAndSkyLight(LightmapVTPageTableResult, Interpolants, bEvaluateBackface, DiffuseDir, bApplySkyLighting, ResolvedView.SkyLightColor.rgb, DiffuseIndirectLighting, SubsurfaceIndirectLighting, IndirectIrradiance, WaterDiffuseIndirectLuminance);
Part 5
DiffuseColor
// Apply MaterialAO since we don't have the DiffuseIndirectComposite pass on mobile deferred.IndirectIrradiance *= GBuffer.GBufferAO;half3 DiffuseColor = (DiffuseIndirectLighting * DiffuseColorForIndirect + SubsurfaceIndirectLighting * SubsurfaceColor) * AOMultiBounce(GBuffer.BaseColor, ShadingOcclusion.DiffOcclusion);····// [ Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion" ]
half3 AOMultiBounce(half3 BaseColor, half AO)
{if (SHADING_PATH_MOBILE && !MOBILE_HIGH_QUALITY_BRDF){return AO;}else{half3 a = 2.0404 * BaseColor - 0.3324;half3 b = -4.7951 * BaseColor + 0.6417;half3 c = 2.7552 * BaseColor + 0.6903;return max(AO, ((AO * a + b) * AO + c) * AO);}
}
计算总光照和烘焙阴影
FLightAccumulator DirectLighting = (FLightAccumulator)0;
LightAccumulator_AddSplit(DirectLighting, DiffuseColor, 0.0f, DiffuseColor, 1.0f, false);GBuffer.PrecomputedShadowFactors = GetPrimaryPrecomputedShadowMask(LightmapVTPageTableResult, Interpolants,MaterialParameters);···void LightAccumulator_AddSplit(inout FLightAccumulator In, float3 DiffuseTotalLight, float3 SpecularTotalLight, float3 ScatterableLight, float3 CommonMultiplier, const bool bNeedsSeparateSubsurfaceLightAccumulation)
{// 3 madIn.TotalLight += (DiffuseTotalLight + SpecularTotalLight) * CommonMultiplier;// This should ideally be evaluated statically outside of this function to avoid the branchif (bNeedsSeparateSubsurfaceLightAccumulation){if (SUBSURFACE_CHANNEL_MODE == 1){if (View.bCheckerboardSubsurfaceProfileRendering == 0){In.ScatterableLightLuma += Luminance(ScatterableLight * CommonMultiplier);}}else if (SUBSURFACE_CHANNEL_MODE == 2){// 3 madIn.ScatterableLight += ScatterableLight * CommonMultiplier;}}In.TotalLightDiffuse += DiffuseTotalLight * CommonMultiplier;In.TotalLightSpecular += SpecularTotalLight * CommonMultiplier;
}···// Used by mobile renderer only
half4 GetPrimaryPrecomputedShadowMask(VTPageTableResult LightmapVTPageTableResult, FVertexFactoryInterpolantsVSToPS Interpolants, FMaterialPixelParameters MaterialParameters)
{#if STATICLIGHTING_TEXTUREMASK && STATICLIGHTING_SIGNEDDISTANCEFIELDLightmapUVType ShadowMapCoordinate;uint LightmapDataIndex;GetShadowMapCoordinate(Interpolants, ShadowMapCoordinate, LightmapDataIndex);// Fetch the distance field data#if LIGHTMAP_VT_ENABLEDhalf4 DistanceField = SampleLightmapVT(LightmapVTPageTableResult, 2u, LightmapDataIndex, LightmapResourceCluster.VTStaticShadowTexture, LightmapResourceCluster.StaticShadowTextureSampler);#elsehalf4 DistanceField = Texture2DSample(LightmapResourceCluster.StaticShadowTexture, LightmapResourceCluster.StaticShadowTextureSampler, ShadowMapCoordinate);#endiffloat4 InvUniformPenumbraSizes = GetLightmapData(LightmapDataIndex).InvUniformPenumbraSizes;float4 DistanceFieldBias = -.5f * InvUniformPenumbraSizes + .5f;// Compute shadow factors by scaling and biasing the distancehalf4 ShadowFactor = saturate( DistanceField * InvUniformPenumbraSizes + DistanceFieldBias );return GetLightmapData(LightmapDataIndex).StaticShadowMapMasks * ShadowFactor * ShadowFactor;#elif MOVABLE_DIRECTIONAL_LIGHT// Do this before checking for lightmaps as we might have a lightmap + movable directional lightreturn 1.0f;#elif HQ_TEXTURE_LIGHTMAP || LQ_TEXTURE_LIGHTMAP// Mark as shadowed for lightmapped objects with no shadowmap// This is necessary because objects inside a light's influence that were determined to be completely shadowed won't be rendered with STATICLIGHTING_TEXTUREMASK==1return 0.0f;#else#if CACHED_POINT_INDIRECT_LIGHTING || CACHED_VOLUME_INDIRECT_LIGHTING// output per-primitive directional light shadowing if requestedif ((GetPrimitiveData(MaterialParameters).Flags & PRIMITIVE_SCENE_DATA_FLAG_USE_SINGLE_SAMPLE_SHADOW_SL) != 0 && ResolvedView.IndirectLightingCacheShowFlag > 0.0f){return half4(IndirectLightingCache.DirectionalLightShadowing, 1, 1, 1);}#endif#endifreturn 1.0f;
}···void GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 ShadowMapCoordinate, out uint LightmapDataIndex)
{ShadowMapCoordinate = Interpolants.ShadowMapCoordinate;#if VF_USE_PRIMITIVE_SCENE_DATALightmapDataIndex = GetPrimitiveData(Interpolants.PrimitiveId).LightmapDataIndex;
#elseLightmapDataIndex = 0;
#endif}
#endif
Lightmap相关==>LightmapData.ush
// Must match FPrecomputedLightingUniformParameters in C++
struct FLightmapSceneData
{float4 StaticShadowMapMasks;float4 InvUniformPenumbraSizes;float4 LightMapCoordinateScaleBias;float4 ShadowMapCoordinateScaleBias;float4 LightMapScale[2];float4 LightMapAdd[2];uint4 LightmapVTPackedPageTableUniform[2];uint4 LightmapVTPackedUniform[5];
};// Stride of a single lightmap data entry in float4's, must match C++
#define LIGHTMAP_SCENE_DATA_STRIDE 15#if USE_GLOBAL_GPU_LIGHTMAP_DATA
StructuredBuffer<float4> GPUSceneLightmapData;
#endiffloat4 LoadLightmapDataElement(uint Index)
{
#if USE_GLOBAL_GPU_LIGHTMAP_DATAcheckStructuredBufferAccessSlow(GPUSceneLightmapData, Index);return GPUSceneLightmapData[Index];
#elsecheckStructuredBufferAccessSlow(View.LightmapSceneData, Index);return View.LightmapSceneData[Index];
#endif
}// Fetch from scene lightmap data buffer
FLightmapSceneData GetLightmapData(uint LightmapDataIndex)
{// Note: layout must match FLightmapSceneShaderData in C++// Relying on optimizer to remove unused loadsFLightmapSceneData LightmapData;uint LightmapDataBaseOffset = LightmapDataIndex * LIGHTMAP_SCENE_DATA_STRIDE;LightmapData.StaticShadowMapMasks = LoadLightmapDataElement(LightmapDataBaseOffset + 0);LightmapData.InvUniformPenumbraSizes = LoadLightmapDataElement(LightmapDataBaseOffset + 1);LightmapData.LightMapCoordinateScaleBias = LoadLightmapDataElement(LightmapDataBaseOffset + 2);LightmapData.ShadowMapCoordinateScaleBias = LoadLightmapDataElement(LightmapDataBaseOffset + 3);LightmapData.LightMapScale[0] = LoadLightmapDataElement(LightmapDataBaseOffset + 4);LightmapData.LightMapScale[1] = LoadLightmapDataElement(LightmapDataBaseOffset + 5);LightmapData.LightMapAdd[0] = LoadLightmapDataElement(LightmapDataBaseOffset + 6);LightmapData.LightMapAdd[1] = LoadLightmapDataElement(LightmapDataBaseOffset + 7);LightmapData.LightmapVTPackedPageTableUniform[0] = asuint(LoadLightmapDataElement(LightmapDataBaseOffset + 8));LightmapData.LightmapVTPackedPageTableUniform[1] = asuint(LoadLightmapDataElement(LightmapDataBaseOffset + 9));UNROLLfor (uint i = 0u; i < 5u; ++i){LightmapData.LightmapVTPackedUniform[i] = asuint(LoadLightmapDataElement(LightmapDataBaseOffset + 10 + i));}return LightmapData;
}
Part 6
动态光照
half4 DynamicShadowFactors = 1.0f;
float DirectionalLightShadow = 1.0f;// Directional light
AccumulateDirectionalLighting(GBuffer, MaterialParameters.WorldPosition_CamRelative, CameraVector, MaterialParameters.ScreenPosition, SvPosition, DynamicShadowFactors, DirectionalLightShadow, DirectLighting);
MobileLightingCommon.ush
void AccumulateDirectionalLighting(FGBufferData GBuffer, float3 TranslatedWorldPosition, half3 CameraVector, float4 ScreenPosition, float4 SvPosition, inout half4 DynamicShadowFactors, inout float OutDirectionalLightShadow, inout FLightAccumulator DirectLighting)
{
#if USE_SHADOWMASKTEXTUREhalf4 PreviewShadowMapChannelMask = half4(1.0f, 0.0f, 0.0f, 0.0f);DynamicShadowFactors = Texture2DSample(MobileBasePass.ScreenSpaceShadowMaskTexture, MobileBasePass.ScreenSpaceShadowMaskSampler, SvPositionToBufferUV(SvPosition));DynamicShadowFactors = DecodeLightAttenuation(DynamicShadowFactors);PreviewShadowMapChannelMask = UnpackShadowMapChannelMask(MobileDirectionalLight.DirectionalLightShadowMapChannelMask >> 4);half DynamicShadowing = dot(PreviewShadowMapChannelMask, DynamicShadowFactors);
#elsefloat ShadowPositionZ = 0;half ShadowMap = MobileDirectionalLightCSM(ScreenPosition.xy, ScreenPosition.w, ShadowPositionZ);half DynamicShadowing = 1.0f;#if !MOBILE_DEFERRED_SHADING && DIRECTIONAL_LIGHT_CSM && !MATERIAL_SHADINGMODEL_SINGLELAYERWATER// Cascaded Shadow Mapif (IsCSMEnabled()){ DynamicShadowing = ShadowMap;}#elif MOBILE_DEFERRED_SHADINGDynamicShadowing = ShadowMap;#endif
#endifFDeferredLightData LightData = (FDeferredLightData)0;LightData.Color = MobileDirectionalLight.DirectionalLightColor.rgb;LightData.FalloffExponent = 0;LightData.Direction = MobileDirectionalLight.DirectionalLightDirectionAndShadowTransition.xyz;LightData.bRadialLight = false;LightData.SpecularScale = MobileDirectionalLight.DirectionalLightDistanceFadeMADAndSpecularScale.z;LightData.ShadowedBits = 1;LightData.HairTransmittance = InitHairTransmittanceData();LightData.ShadowMapChannelMask = UnpackShadowMapChannelMask(MobileDirectionalLight.DirectionalLightShadowMapChannelMask);half4 LightAttenuation = half4(1, 1, DynamicShadowing, DynamicShadowing);FLightAccumulator NewLighting = AccumulateDynamicLighting(TranslatedWorldPosition, CameraVector, GBuffer, 1, GBuffer.ShadingModelID, LightData, LightAttenuation, 0, uint2(0, 0), OutDirectionalLightShadow);DirectLighting = LightAccumulator_Add(DirectLighting, NewLighting);
}···
FLightAccumulator LightAccumulator_Add(FLightAccumulator A, FLightAccumulator B)
{FLightAccumulator Sum = (FLightAccumulator)0;Sum.TotalLight = A.TotalLight + B.TotalLight;Sum.ScatterableLightLuma = A.ScatterableLightLuma + B.ScatterableLightLuma;Sum.ScatterableLight = A.ScatterableLight + B.ScatterableLight;Sum.EstimatedCost = A.EstimatedCost + B.EstimatedCost;Sum.TotalLightDiffuse = A.TotalLightDiffuse + B.TotalLightDiffuse;Sum.TotalLightSpecular = A.TotalLightSpecular + B.TotalLightSpecular;return Sum;
}
DeferredLightingCommon.ush
这里进入BXDF
FLightAccumulator AccumulateDynamicLighting(float3 TranslatedWorldPosition, half3 CameraVector, FGBufferData GBuffer, half AmbientOcclusion, uint ShadingModelID,FDeferredLightData LightData, half4 LightAttenuation, float Dither, uint2 SVPos, inout float SurfaceShadow)
{···#if SHADING_PATH_MOBILEconst bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID);FDirectLighting Lighting = (FDirectLighting)0;half NoL = max(0, dot(GBuffer.WorldNormal, L));#if TRANSLUCENCY_NON_DIRECTIONALNoL = 1.0f;#endifLighting = EvaluateBxDF(GBuffer, N, V, L, NoL, Shadow);Lighting.Specular *= LightData.SpecularScale;LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation );LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * Shadow.TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation );#else // SHADING_PATH_MOBILE···
}
ShadingModels.ush
FDirectLighting PreintegratedSkinBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
{FDirectLighting Lighting = DefaultLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );half3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);half Opacity = GBuffer.CustomData.a;half3 PreintegratedBRDF = Texture2DSampleLevel(View.PreIntegratedBRDF, View.PreIntegratedBRDFSampler, float2(saturate(dot(N, L) * .5 + .5), 1 - Opacity), 0).rgb;Lighting.Transmission = AreaLight.FalloffColor * Falloff * PreintegratedBRDF * SubsurfaceColor;return Lighting;
}FDirectLighting IntegrateBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
{switch( GBuffer.ShadingModelID ){case SHADINGMODELID_DEFAULT_LIT:case SHADINGMODELID_SINGLELAYERWATER:case SHADINGMODELID_THIN_TRANSLUCENT:return DefaultLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_SUBSURFACE:return SubsurfaceBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_PREINTEGRATED_SKIN:return PreintegratedSkinBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_CLEAR_COAT:return ClearCoatBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_SUBSURFACE_PROFILE:return SubsurfaceProfileBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_TWOSIDED_FOLIAGE:return TwoSidedBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_HAIR:return HairBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_CLOTH:return ClothBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );case SHADINGMODELID_EYE:return EyeBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );default:return (FDirectLighting)0;}
}FDirectLighting EvaluateBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float NoL, FShadowTerms Shadow )
{FAreaLight AreaLight;AreaLight.SphereSinAlpha = 0;AreaLight.SphereSinAlphaSoft = 0;AreaLight.LineCosSubtended = 1;AreaLight.FalloffColor = 1;AreaLight.Rect = (FRect)0;AreaLight.IsRectAndDiffuseMicroReflWeight = 0;AreaLight.Texture = InitRectTexture();return IntegrateBxDF( GBuffer, N, V, L, 1, NoL, AreaLight, Shadow );
}
最后走的还是 DefaultLitBxDF
FDirectLighting DefaultLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
{BxDFContext Context;FDirectLighting Lighting;#if SUPPORTS_ANISOTROPIC_MATERIALSbool bHasAnisotropy = HasAnisotropy(GBuffer.SelectiveOutputMask);
#elsebool bHasAnisotropy = false;
#endiffloat NoV, VoH, NoH;BRANCHif (bHasAnisotropy){half3 X = GBuffer.WorldTangent;half3 Y = normalize(cross(N, X));Init(Context, N, X, Y, V, L);NoV = Context.NoV;VoH = Context.VoH;NoH = Context.NoH;}else{
#if SHADING_PATH_MOBILEInitMobile(Context, N, V, L, NoL);
#elseInit(Context, N, V, L);
#endifNoV = Context.NoV;VoH = Context.VoH;NoH = Context.NoH;SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true);}Context.NoV = saturate(abs( Context.NoV ) + 1e-5);#if MATERIAL_ROUGHDIFFUSE// Chan diffuse model with roughness == specular roughness. This is not necessarily a good modelisation of reality because when the mean free path is super small, the diffuse can in fact looks rougher. But this is a start.// Also we cannot use the morphed context maximising NoH as this is causing visual artefact when interpolating rough/smooth diffuse response. Lighting.Diffuse = Diffuse_Chan(GBuffer.DiffuseColor, Pow4(GBuffer.Roughness), NoV, NoL, VoH, NoH, GetAreaLightDiffuseMicroReflWeight(AreaLight));
#elseLighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor);
#endifLighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);BRANCHif (bHasAnisotropy){//Lighting.Specular = GBuffer.WorldTangent * .5f + .5f;Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, Context, NoL, AreaLight);}else{if( IsRectLight(AreaLight) ){Lighting.Specular = RectGGXApproxLTC(GBuffer.Roughness, GBuffer.SpecularColor, N, V, AreaLight.Rect, AreaLight.Texture);}else{Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.SpecularColor, Context, NoL, AreaLight);}}FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, Context.NoV, GBuffer.SpecularColor);// Add energy presevation (i.e. attenuation of the specular layer onto the diffuse componentLighting.Diffuse *= ComputeEnergyPreservation(EnergyTerms);// Add specular microfacet multiple scattering term (energy-conservation)Lighting.Specular *= ComputeEnergyConservation(EnergyTerms);Lighting.Transmission = 0;return Lighting;
}
SpecularGGX
float3 SpecularGGX( float Roughness, float3 SpecularColor, BxDFContext Context, half NoL, FAreaLight AreaLight )
{float a2 = Pow4( Roughness );//EnergyNormalization感觉涉及到AreaLight暂时忽略float Energy = EnergyNormalization( a2, Context.VoH, AreaLight );#if SHADING_PATH_MOBILEhalf D = GGX_Mobile(Roughness, Context.NoH) * Energy;return MobileSpecularGGXInner(D, SpecularColor, Roughness, Context.NoV, NoL, Context.VoH, MOBILE_HIGH_QUALITY_BRDF);
#else// Generalized microfacet specularfloat D = D_GGX( a2, Context.NoH ) * Energy;float Vis = Vis_SmithJointApprox( a2, Context.NoV, NoL );float3 F = F_Schlick( SpecularColor, Context.VoH );return (D * Vis) * F;
#endif
}···half GGX_Mobile(half Roughness, float NoH)
{// Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"float OneMinusNoHSqr = 1.0 - NoH * NoH; half a = Roughness * Roughness;half n = NoH * a;half p = a / (OneMinusNoHSqr + n * n);half d = p * p;// clamp to avoid overlfow in a bright envreturn min(d, 2048.0);
}···half3 MobileSpecularGGXInner(half D, half3 SpecularColor, half Roughness, half NoV, half NoL, half VoH, bool bHighQualityBRDF)
{half Vis = (Roughness * 0.25 + 0.25);half3 F = GetEnvBRDF(SpecularColor, Roughness, NoV);//使用高质量计算完整的G(几何函数)项和F项if (bHighQualityBRDF){Vis = saturate(Vis_SmithJointApprox(Roughness * Roughness * Roughness * Roughness, NoV, NoL));F = F_Schlick(SpecularColor, VoH);}return (D * Vis) * F;
}
使用高质量计算完整的G(几何函数)项和F项
看看EnvBRDF
half3 GetEnvBRDF(half3 SpecularColor, half Roughness, half NoV)
{
#if FULLY_ROUGHreturn 0.0f;
#elif MOBILE_USE_PREINTEGRATED_GFreturn EnvBRDF(SpecularColor, Roughness, NoV);
#elif NONMETAL// If nothing is hooked up to Metalic and Specular,// then defaults are the same as a non-metal,// so this define is safe.return EnvBRDFApproxNonmetal(Roughness, NoV).xxx;
#elsereturn EnvBRDFApprox(SpecularColor, Roughness, NoV);
#endif
}···half2 EnvBRDFApproxLazarov(half Roughness, half NoV)
{// [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ]// Adaptation to fit our G term.const half4 c0 = { -1, -0.0275, -0.572, 0.022 };const half4 c1 = { 1, 0.0425, 1.04, -0.04 };half4 r = Roughness * c0 + c1;half a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;half2 AB = half2(-1.04, 1.04) * a004 + r.zw;return AB;
}half3 EnvBRDFApprox( half3 SpecularColor, half Roughness, half NoV )
{half2 AB = EnvBRDFApproxLazarov(Roughness, NoV);// Anything less than 2% is physically impossible and is instead considered to be shadowing// Note: this is needed for the 'specular' show flag to work, since it uses a SpecularColor of 0float F90 = saturate( 50.0 * SpecularColor.g );return SpecularColor * AB.x + F90 * AB.y;
}
前向渲染正常走的是EnvBRDFApprox除非勾了材质里的简单IBL的预整合GF。

Part 7
SpecularIBL
MATERIALBLENDING_SOLID对应的是Opaque Mode
#if MATERIALBLENDING_MASKED || MATERIALBLENDING_SOLID || TRANSLUCENCY_LIGHTING_SURFACE_FORWARDSHADING || MATERIAL_SHADINGMODEL_SINGLELAYERWATER// Reflection IBLAccumulateReflection(GBuffer, CameraVector, MaterialParameters.WorldPosition_CamRelative, MaterialParameters.ReflectionVector, IndirectIrradiance, GridIndex, DirectLighting);
#endif
AccumulateReflection
void AccumulateReflection(FGBufferData GBuffer, half3 CameraVector, float3 TranslatedWorldPosition, half3 ReflectionVector, half IndirectIrradiance, uint GridIndex, inout FLightAccumulator DirectLighting)
{half3 SpecularIBLLighting = (half3)0.0f;half3 N = GBuffer.WorldNormal;half3 V = -CameraVector;half NoV = saturate(abs(dot(N, V)) + 1e-5);half3 TopLayerR = ReflectionVector;half SpecularOcclusion = GBuffer.GBufferAO;if (MOBILE_HIGH_QUALITY_BRDF){// Point lobe in off-specular peak directionReflectionVector = GetOffSpecularPeakReflectionDir(N, ReflectionVector, GBuffer.Roughness);half RoughnessSq = GBuffer.Roughness * GBuffer.Roughness;SpecularOcclusion = GetSpecularOcclusion(NoV, RoughnessSq, SpecularOcclusion);}half3 SpecularIBL = GetImageBasedReflectionLighting(ReflectionVector, TranslatedWorldPosition, GBuffer.Roughness, IndirectIrradiance, SpecularOcclusion, GridIndex);#if ENABLE_PLANAR_REFLECTION || MATERIAL_PLANAR_FORWARD_REFLECTIONSBRANCHif (abs(dot(PlanarReflectionStruct.ReflectionPlane.xyz, 1)) > .0001f){half4 PlanarReflection = GetPlanarReflection(TranslatedWorldPosition, GBuffer.WorldNormal, GBuffer.Roughness);// Planar reflections win over reflection environmentSpecularIBL = lerp(SpecularIBL, PlanarReflection.rgb, PlanarReflection.a);}
#endifhalf3 DiffuseColor = GBuffer.DiffuseColor;half3 SpecularColor = GBuffer.SpecularColor;if (GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT){//省略部分代码···}else if (GBuffer.ShadingModelID == SHADINGMODELID_HAIR){//Skip IBL for Hair}else{SpecularIBLLighting += SpecularIBL * GetEnvBRDF(SpecularColor, GBuffer.Roughness, NoV);}LightAccumulator_AddSplit(DirectLighting, 0.0f, SpecularIBLLighting, 0.0f, 1.0f, false);
}
GetImageBasedReflectionLighting和GetMobileSkyLightReflection
#if IS_MOBILE_BASE_PASS
/** Prenormalized capture of the scene that's closest to the object being rendered. */
half3 GetMobileSkyLightReflection(half3 ReflectionVector, half Roughness, half CubemapMaxMip)
{half AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness, CubemapMaxMip);half4 Reflection = MobileReflectionCapture.Texture.SampleLevel(MobileReflectionCapture.TextureSampler, ReflectionVector, AbsoluteSpecularMip);return Reflection.rgb * ResolvedView.SkyLightColor.rgb;
}
#endifhalf3 GetImageBasedReflectionLighting(half3 ReflectionVector, float3 TranslatedWorldPosition, half Roughness, half IndirectIrradiance, half CompositeAlpha, uint GridIndex
)
{half3 SpecularIBL = (half3)0.0f;#if ENABLE_CLUSTERED_REFLECTION //混合多个Cubemap光照,好像移动端并没有这个功能uint NumCulledEntryIndex = (ForwardLightData.NumGridCells + GridIndex) * NUM_CULLED_LIGHTS_GRID_STRIDE;uint NumLocalReflectionCaptures = min(ForwardLightData.NumCulledLightsGrid[NumCulledEntryIndex + 0], ForwardLightData.NumReflectionCaptures);uint DataStartIndex = ForwardLightData.NumCulledLightsGrid[NumCulledEntryIndex + 1];SpecularIBL = CompositeReflectionCapturesAndSkylightTWS(CompositeAlpha,TranslatedWorldPosition,ReflectionVector,//RayDirection,Roughness,IndirectIrradiance,1.0f,0.0f,NumLocalReflectionCaptures,DataStartIndex,0,true);
#elif MOBILE_DEFERRED_LIGHTINGfloat SkyAverageBrightness = 1.0f;SpecularIBL = GetSkyLightReflection(ReflectionVector, Roughness, SkyAverageBrightness);#if ALLOW_STATIC_LIGHTINGSpecularIBL *= ComputeMixingWeight(IndirectIrradiance, SkyAverageBrightness, Roughness);#endifSpecularIBL *= CompositeAlpha;
#else // !(ENABLE_CLUSTERED_REFLECTION || MOBILE_DEFERRED_LIGHTING)half UsingSkyReflection = MobileReflectionCapture.Params.y > 0.0f;if (UsingSkyReflection){// Apply sky colour if the reflection map is the sky.SpecularIBL = GetMobileSkyLightReflection(ReflectionVector, Roughness, MobileReflectionCapture.Params.y);}else{half AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness, ResolvedView.ReflectionCubemapMaxMip);SpecularIBL = MobileReflectionCapture.Texture.SampleLevel(MobileReflectionCapture.TextureSampler, ReflectionVector, AbsoluteSpecularMip).rgb;half ReflectionCaptureBrightness = MobileReflectionCapture.Params.w;SpecularIBL = SpecularIBL * ReflectionCaptureBrightness;}#if ALLOW_STATIC_LIGHTINGSpecularIBL *= ComputeMixingWeight(IndirectIrradiance, MobileReflectionCapture.Params.x, Roughness);#endifSpecularIBL *= CompositeAlpha;
#endifreturn SpecularIBL;
}
AccumulateReflection函数之后MobileBasePassPixelShader.usf就没有光照计算的的代码了
#if !MATERIAL_SHADINGMODEL_UNLIThalf3 Color = DirectLighting.TotalLight;
#elsehalf3 Color = 0.0f;
#endif
其实只看LightAccumulator_AddSplit和LightAccumulator_Add就可大概了解光照的流程了。
第一次是DiffuseColor:
LightAccumulator_AddSplit(DirectLighting, DiffuseColor, 0.0f, DiffuseColor, 1.0f, false);
第二和第三次是BXDF之后:
LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation );
LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * Shadow.TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation );
//PreintegratedSkinBxDF
//Lighting.Transmission = AreaLight.FalloffColor * Falloff * PreintegratedBRDF * SubsurfaceColor;
LightAccumulator_Add把DiffuseColor和BXDF相加:
DirectLighting = LightAccumulator_Add(DirectLighting, NewLighting);
第四次是把SpecularIBLLighting加上:
LightAccumulator_AddSplit(DirectLighting, 0.0f, SpecularIBLLighting, 0.0f, 1.0f, false);
以上,完。
相关文章:
UE5.1移动端PreintegratedSkinBxDF解析
Part 1 头文件 MobileBasePassPixelShader.usf 主要看Main函数: #if MOBILE_MULTI_VIEWResolvedView ResolveView(BasePassInterpolants.MultiViewId); #elseResolvedView ResolveView(); #endif这玩意Shader文件找不到,感觉是个全局变量的东西。万幸…...
WebSocket心跳机制(笔记大全)
一、WebSocket心跳机制前端 前端实现WebSocket心跳机制的方式主要有两种: 使用setInterval定时发送心跳包。在前端监听到WebSocket的onclose()事件时,重新创建WebSocket连接。 第一种方式会对服务器造成很大的压力,因为即使WebSocket连接正…...
Spring Boot日志:SLF4J和Logback
日志的分类 SpringBoot中的日志库分为两种: 实现库:提供具体的日志实现,例如日志级别的控制、打印格式、输出目标等。外观库:自身不提供日志实现,而是对其他日志库进行封装,从而方便使用。基于外观模式实…...
[C++] C++入门第二篇 -- 引用 -- 内联函数inline -- auto+for
目录 1、引用 -- & 1.1 引用的概念 1.2 引用特性 1.3 常引用 -- 权限问题 1.4 引用的使用场景 1.4.1 做参数 1.4.2 做返回值 注意 1.5 传值、传引用的效率比较 1.6 引用和指针的区别 2、内联函数 2.1 概念 转存失败重新上传取消编辑转存失败重新上传取消编…...
Latex | 将MATLAB图并导入Latex中的方法
一、问题描述 用Latex时写paper时,要导入MATLAB生成的图进去 二、解决思路 (1)在MATLAB生成图片的窗口中,导出.eps矢量图 (2)把图上传到overleaf的目录 (3)在文中添加相应代码 三…...
JSON格式Python,Java,PHP等封装根据关键词搜索获取淘宝商品列表数据API
淘宝是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要用关键词搜索获取淘宝天猫商品列表,您可以通过开放平台的接口或者直接访问淘宝天猫商城的网页来获取商品列表详细信息。以下是两种常用方法的介绍&a…...
MySQL MHA高可用配置及故障切换
文章目录 一.MySQL MHA1.什么是MHA2.MHA的组成2.1MHA Node (数据节点)2.2MHA Manager (管理节点) 3.MHA的特点4.…...
PHP8知识详解:PHP8开发工具VS Code的安装
作为PHP8的开发工具有很多,具有IDE功能的有phpstorm、Visual Studio Code、Sublime Text、NetBeans、Eclipse、Codelobster、PHP Designer等,当然还有很多轻量的工具,比如Notepad、Editplus等。本文给你介绍的是万能编辑器Visual Studio Code…...
Sui Move与标准Move的有哪些区别和根本性创新
Sui网络将Sui Move作为其本地编程语言,使用Sui Move编写的apps利用Sui的共识机制,实现了令人印象深刻的交易性能。 然而,熟悉Move编程语言的开发者在探索Sui文档时可能会感到困惑,因为该文档着重介绍了对象和一些指令,…...
构建自己的ChatGPT:从零开始构建个性化语言模型
🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~ἳ…...
【react】react18的学习(十二)– 底层原理(二)之 迭代器 iterator
迭代器iterator 是一种 ES6 规范,具有这种机制的数据结构才可以使用for of循环:返回每一项的值; 原型链具有Symbol.iterator属性的数据结构都具备;如数组、部分类数组、字符串等; 普通对象就不能用; for-…...
一遍过JavaSE基础知识
文章目录 前言安装Java Development Kit (JDK)安装jdk配置开发环境验证是否安装配置成功 编写第一个Java程序hello world运行Java程序的流程 数据类型和变量数据类型变量 程序逻辑控制条件语句循环语句跳转语句 数组声明和创建数组访问数组元素数组长度遍历数组多维数组 面向对…...
【云原生】Kubernetes之ConfigMap
ConfigMap ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件 ConfigMap 将你的环境配置信息和 容器镜像 解耦,便于应用配置的修改 说明:…...
8.python设计模式【组合模式】
内容:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。角色: 抽象组建(component)叶子组建(Leaf)复合组建(Composite)客户端 (Client) UML 图 举个例子 需求…...
tkinter制作任意图形窗口
import tkinter from PIL import Image, ImageTkdog tkinter.Tk() # 设置图片描绘的坐标,注意乘号是字母x dog.geometry(500x500200100) # 不允许修改大小 dog.resizable(False, False) # 不显示标题栏 dog.overrideredirect(True) # 设置白色透明色,这…...
视频监控综合管理平台EasyCVR多分屏默认播放协议的配置优化
视频监控综合管理平台EasyCVR具备视频融合汇聚能力,TSINGSEE青犀视频平台基于云边端一体化架构,可支持多协议、多类型设备接入,包括:NVR、IPC、视频编码器、无人机、车载设备、智能手持终端、移动执法仪等。国标GB28181视频平台Ea…...
2023杭电多校第三场 1012.Noblesse Code
传送门:Vjudge 前题提要:一道挺有意思的数论题.赛时对于这道题没什么想法,但是赛后细品之后其实感觉也就那么一回事.但是这种 更相损减术与辗转相除法 相转化的题目还是有点典的,需要好好消化一下. 首先看完题目.我们需要考虑的是 ( A , B ) (A,B) (A,B)与 ( a , b ) (a,b) (…...
ubuntu qt 环境变量配置
ubuntu设置qt环境变量 qt 安装路径为:/home/ljn/Qt5.12 包含bin等目录的路经:/home/ljn/Qt5.14.2/5.14.2/gcc_64 环境变量配置 打开配置文件: sudo gedit /etc/profile在底部添加: export PATH"/home/ljn/Qt5.14.2/Tool…...
按照Vue写WPF(0):功能实现
文章目录 前言VUE具有的功能如何专业到WPF上面 前言 我最近学了WPF之后我终于知道为什么WPF学习曲线那么陡峭了。因为WPF没有组件化的思想,或者说没有按照Vue一样去模板化开发。 为什么我推荐Vue的想法呢。因为Vue最大的特点就是模板化,让Vue工程师去写…...
vb+ACCESS教师管理系统设计设计与实现
--------------前言-------------- 教师管理系统是一个企事业单位不可缺少的部分,它的内容对于企事业单位的决策者和管理者来说都至关重要,所以教师管理系统应该能够为用户提供充足的信息和快捷的查询手段。但一直以来人们使用传统人工的方式管理文件信息,这种管理方式存在…...
Exegol未来展望:AI驱动的安全测试与云原生架构的发展趋势
Exegol未来展望:AI驱动的安全测试与云原生架构的发展趋势 【免费下载链接】Exegol Fully featured and community-driven hacking environment 项目地址: https://gitcode.com/gh_mirrors/ex/Exegol Exegol作为一个功能全面且社区驱动的网络安全测试环境&…...
深度解析Windows驱动管理:DriverStore Explorer高效清理冗余驱动实战指南
深度解析Windows驱动管理:DriverStore Explorer高效清理冗余驱动实战指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer DriverStore Explorer(简称RAPR&#x…...
vue 求助
这个浅灰色的背景框怎么改啊,没招了...
ESP32内存告急?别慌!手把手教你搞定‘iram0_0_seg overflowed’编译错误
ESP32内存告急?别慌!手把手教你搞定‘iram0_0_seg overflowed’编译错误 当你正沉浸在ESP32项目的开发中,突然一个红色的编译错误打断了你的思绪——"iram0_0_seg overflowed"。这个看似晦涩的错误信息,实际上困扰着许多…...
ICDM 2024论文精读:MetaSTC如何用‘聚类+元学习’四两拨千斤,大幅提升预测效率?
MetaSTC技术解析:如何用聚类与元学习重构时空预测范式 清晨的城市交通如同人体血管,数据在其中奔流不息。预测这些流动的规律,是智能交通系统的核心挑战。传统深度学习模型往往陷入"算力黑洞"——为了1%的精度提升,需要…...
保姆级教程:为嵌入式Linux(ARM/AArch64)交叉编译带完整符号支持的Perf工具
ARM架构嵌入式Linux系统性能调优实战:Perf工具深度定制指南 在嵌入式系统开发中,性能优化往往是最具挑战性的环节之一。当你的应用在ARM或AArch64架构的嵌入式设备上运行时出现卡顿、延迟或资源耗尽,传统的打印调试和日志分析往往难以定位深…...
【紧急预警】边缘固件OTA升级因编译产物ABI不兼容导致大规模回滚?立即执行这5项ABI稳定性检查
第一章:边缘C编译优化概览在资源受限的边缘设备(如嵌入式控制器、IoT网关、车载ECU)上运行C应用时,编译阶段的优化决策直接影响内存占用、启动延迟与实时响应能力。与云端服务器不同,边缘场景通常面临固定ROM/RAM容量、…...
泛微OA字段联动与JS代码顺序控制的实战技巧:如何避免数据遍历中的坑
泛微OA字段联动与JS代码顺序控制的实战技巧:如何避免数据遍历中的坑 在泛微OA系统的二次开发中,字段联动和JS代码控制是提升表单交互性的两大核心功能。但当这两个功能需要在同一业务流程中协同工作时,开发者常常会遇到一个棘手的问题&#x…...
开源PDF工具clawPDF:高效办公的终极解决方案
开源PDF工具clawPDF:高效办公的终极解决方案 【免费下载链接】clawPDF Open Source Virtual (Network) Printer for Windows that allows you to create PDFs, OCR text, and print images, with advanced features usually available only in enterprise solutions…...
Open UI5 源代码解析之884:OverflowToolbarAssociativePopover.js
源代码仓库: https://github.com/SAP/openui5 源代码位置:src\sap.m\src\sap\m\OverflowToolbarAssociativePopover.js OverflowToolbarAssociativePopover.js 深度解析 文件定位与整体价值 OverflowToolbarAssociativePopover.js 是 sap.m 库里一个非常典型的内部增强组…...
