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教师管理系统设计设计与实现
--------------前言-------------- 教师管理系统是一个企事业单位不可缺少的部分,它的内容对于企事业单位的决策者和管理者来说都至关重要,所以教师管理系统应该能够为用户提供充足的信息和快捷的查询手段。但一直以来人们使用传统人工的方式管理文件信息,这种管理方式存在…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...