头文件 MobileBasePassPixelShader.usf
主要看Main函数:
#if MOBILE_MULTI_VIEW
ResolvedView = ResolveView(BasePassInterpolants.MultiViewId);
#else
ResolvedView = 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
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;
};
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;
}
没明白这个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 disabled
SubsurfaceData *= 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_SKIN
else 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 NONMETAL
GBuffer.DiffuseColor = GBuffer.BaseColor;
GBuffer.SpecularColor = 0.04;
#else
GBuffer.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_SKIN
if (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 GI
DiffuseColorForIndirect += SubsurfaceColor;
}
#endif
获取预计算间接光照和天光
GetPrecomputedIndirectLightingAndSkyLight(LightmapVTPageTableResult,
Interpolants, bEvaluateBackface, DiffuseDir, bApplySkyLighting, ResolvedView.SkyLightColor.rgb,
DiffuseIndirectLighting, SubsurfaceIndirectLighting, IndirectIrradiance, WaterDiffuseIndirectLuminance);
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 mad
In.TotalLight += (DiffuseTotalLight + SpecularTotalLight) * CommonMultiplier;
// This should ideally be evaluated statically outside of this function to avoid the branch
if (bNeedsSeparateSubsurfaceLightAccumulation)
{
if (SUBSURFACE_CHANNEL_MODE == 1)
{
if (View.bCheckerboardSubsurfaceProfileRendering == 0)
{
In.ScatterableLightLuma += Luminance(ScatterableLight * CommonMultiplier);
}
}
else if (SUBSURFACE_CHANNEL_MODE == 2)
{
// 3 mad
In.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_SIGNEDDISTANCEFIELD
LightmapUVType ShadowMapCoordinate;
uint LightmapDataIndex;
GetShadowMapCoordinate(Interpolants, ShadowMapCoordinate, LightmapDataIndex);
// Fetch the distance field data
#if LIGHTMAP_VT_ENABLED
half4 DistanceField = SampleLightmapVT(LightmapVTPageTableResult, 2u, LightmapDataIndex, LightmapResourceCluster.VTStaticShadowTexture, LightmapResourceCluster.StaticShadowTextureSampler);
#else
half4 DistanceField = Texture2DSample(LightmapResourceCluster.StaticShadowTexture, LightmapResourceCluster.StaticShadowTextureSampler, ShadowMapCoordinate);
#endif
float4 InvUniformPenumbraSizes = GetLightmapData(LightmapDataIndex).InvUniformPenumbraSizes;
float4 DistanceFieldBias = -.5f * InvUniformPenumbraSizes + .5f;
// Compute shadow factors by scaling and biasing the distance
half4 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 light
return 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==1
return 0.0f;
#else
#if CACHED_POINT_INDIRECT_LIGHTING || CACHED_VOLUME_INDIRECT_LIGHTING
// output per-primitive directional light shadowing if requested
if ((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
#endif
return 1.0f;
}
···
void GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 ShadowMapCoordinate, out uint LightmapDataIndex)
{
ShadowMapCoordinate = Interpolants.ShadowMapCoordinate;
#if VF_USE_PRIMITIVE_SCENE_DATA
LightmapDataIndex = GetPrimitiveData(Interpolants.PrimitiveId).LightmapDataIndex;
#else
LightmapDataIndex = 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;
#endif
float4 LoadLightmapDataElement(uint Index)
{
#if USE_GLOBAL_GPU_LIGHTMAP_DATA
checkStructuredBufferAccessSlow(GPUSceneLightmapData, Index);
return GPUSceneLightmapData[Index];
#else
checkStructuredBufferAccessSlow(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 loads
FLightmapSceneData 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));
UNROLL
for (uint i = 0u; i < 5u; ++i)
{
LightmapData.LightmapVTPackedUniform[i] = asuint(LoadLightmapDataElement(LightmapDataBaseOffset + 10 + i));
}
return LightmapData;
}
动态光照
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_SHADOWMASKTEXTURE
half4 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);
#else
float 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 Map
if (IsCSMEnabled())
{
DynamicShadowing = ShadowMap;
}
#elif MOBILE_DEFERRED_SHADING
DynamicShadowing = ShadowMap;
#endif
#endif
FDeferredLightData 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_MOBILE
const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID);
FDirectLighting Lighting = (FDirectLighting)0;
half NoL = max(0, dot(GBuffer.WorldNormal, L));
#if TRANSLUCENCY_NON_DIRECTIONAL
NoL = 1.0f;
#endif
Lighting = 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_MATERIALS
bool bHasAnisotropy = HasAnisotropy(GBuffer.SelectiveOutputMask);
#else
bool bHasAnisotropy = false;
#endif
float NoV, VoH, NoH;
BRANCH
if (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_MOBILE
InitMobile(Context, N, V, L, NoL);
#else
Init(Context, N, V, L);
#endif
NoV = 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));
#else
Lighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor);
#endif
Lighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);
BRANCH
if (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 component
Lighting.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_MOBILE
half D = GGX_Mobile(Roughness, Context.NoH) * Energy;
return MobileSpecularGGXInner(D, SpecularColor, Roughness, Context.NoV, NoL, Context.VoH, MOBILE_HIGH_QUALITY_BRDF);
#else
// Generalized microfacet specular
float 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 env
return 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_ROUGH
return 0.0f;
#elif MOBILE_USE_PREINTEGRATED_GF
return 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;
#else
return 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 0
float F90 = saturate( 50.0 * SpecularColor.g );
return SpecularColor * AB.x + F90 * AB.y;
}
前向渲染正常走的是EnvBRDFApprox除非勾了材质里的简单IBL的预整合GF。
SpecularIBL
MATERIALBLENDING_SOLID对应的是Opaque Mode
#if MATERIALBLENDING_MASKED || MATERIALBLENDING_SOLID || TRANSLUCENCY_LIGHTING_SURFACE_FORWARDSHADING || MATERIAL_SHADINGMODEL_SINGLELAYERWATER
// Reflection IBL
AccumulateReflection(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 direction
ReflectionVector = 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_REFLECTIONS
BRANCH
if (abs(dot(PlanarReflectionStruct.ReflectionPlane.xyz, 1)) > .0001f)
{
half4 PlanarReflection = GetPlanarReflection(TranslatedWorldPosition, GBuffer.WorldNormal, GBuffer.Roughness);
// Planar reflections win over reflection environment
SpecularIBL = lerp(SpecularIBL, PlanarReflection.rgb, PlanarReflection.a);
}
#endif
half3 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;
}
#endif
half3 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_LIGHTING
float SkyAverageBrightness = 1.0f;
SpecularIBL = GetSkyLightReflection(ReflectionVector, Roughness, SkyAverageBrightness);
#if ALLOW_STATIC_LIGHTING
SpecularIBL *= ComputeMixingWeight(IndirectIrradiance, SkyAverageBrightness, Roughness);
#endif
SpecularIBL *= 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_LIGHTING
SpecularIBL *= ComputeMixingWeight(IndirectIrradiance, MobileReflectionCapture.Params.x, Roughness);
#endif
SpecularIBL *= CompositeAlpha;
#endif
return SpecularIBL;
}
AccumulateReflection函数之后MobileBasePassPixelShader.usf就没有光照计算的的代码了
#if !MATERIAL_SHADINGMODEL_UNLIT
half3 Color = DirectLighting.TotalLight;
#else
half3 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);
以上,完。