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

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...