You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
291 lines
10 KiB
Plaintext
291 lines
10 KiB
Plaintext
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
BasePassForForwardShadingPixelShader.usf: Base pass pixel shader used with forward shading
|
|
=============================================================================*/
|
|
|
|
#include "Common.usf"
|
|
#include "BasePassForForwardShadingCommon.usf"
|
|
#include "Material.usf"
|
|
#include "VertexFactory.usf"
|
|
#include "ReflectionEnvironmentShared.usf"
|
|
#include "LightmapCommon.usf"
|
|
#include "BRDF.usf"
|
|
#include "SHCommon.usf"
|
|
#include "ShadowFilteringCommon.usf"
|
|
|
|
/** Prenormalized capture of the scene that's closest to the object being rendered. */
|
|
#if !MATERIAL_FULLY_ROUGH
|
|
TextureCube ReflectionCubemap;
|
|
SamplerState ReflectionCubemapSampler;
|
|
#endif
|
|
|
|
half PhongApprox( half Roughness, half RoL )
|
|
{
|
|
half a = Roughness * Roughness; // 1 mul
|
|
half a2 = a * a; // 1 mul
|
|
float rcp_a2 = rcp(a2); // 1 rcp
|
|
//half rcp_a2 = exp2( -6.88886882 * Roughness + 6.88886882 );
|
|
|
|
// Spherical Gaussian approximation: pow( x, n ) ~= exp( (n + 0.775) * (x - 1) )
|
|
// Phong: n = 0.5 / a2 - 0.5
|
|
// 0.5 / ln(2), 0.275 / ln(2)
|
|
half c = 0.72134752 * rcp_a2 + 0.39674113; // 1 mad
|
|
return rcp_a2 * exp2( c * RoL - c ); // 2 mad, 1 exp2, 1 mul
|
|
// Total 7 instr
|
|
}
|
|
|
|
#if !MATERIAL_FULLY_ROUGH
|
|
half3 GetImageBasedReflectionLighting(FMaterialPixelParameters MaterialParameters, half Roughness)
|
|
{
|
|
half3 ProjectedCaptureVector = MaterialParameters.ReflectionVector;
|
|
|
|
// Compute fractional mip from roughness
|
|
half AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness);
|
|
// Fetch from cubemap and convert to linear HDR
|
|
half3 SpecularIBL = RGBMDecode(ReflectionCubemap.SampleLevel(ReflectionCubemapSampler, ProjectedCaptureVector, AbsoluteSpecularMip), 16.0f);
|
|
SpecularIBL *= SpecularIBL;
|
|
#if WEBGL
|
|
// need a rgb swizzle instead of the existing rgba swizzle, we should add it if another use case comes up.
|
|
return SpecularIBL.bgr;
|
|
#else
|
|
return SpecularIBL;
|
|
#endif
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
half4 IndirectLightingSHCoefficients[3];
|
|
half DirectionalLightShadowing;
|
|
|
|
void Main(
|
|
FVertexFactoryInterpolantsVSToPS Interpolants,
|
|
FForwardShadingBasePassInterpolantsVSToPS BasePassInterpolants,
|
|
in half4 SvPosition : SV_Position,
|
|
OPTIONAL_IsFrontFace,
|
|
out half4 OutColor : SV_Target0
|
|
)
|
|
{
|
|
#if PACK_INTERPOLANTS
|
|
float4 PackedInterpolants[NUM_VF_PACKED_INTERPOLANTS];
|
|
VertexFactoryUnpackInterpolants(Interpolants, PackedInterpolants);
|
|
#endif
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, BasePassInterpolants.PixelPosition);
|
|
|
|
CalcMaterialParameters(MaterialParameters, bIsFrontFace, BasePassInterpolants.PixelPosition
|
|
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
|
|
, BasePassInterpolants.PixelPositionExcludingWPO
|
|
#endif
|
|
);
|
|
|
|
//Clip if the blend mode requires it.
|
|
GetMaterialCoverageAndClipping(MaterialParameters);
|
|
|
|
//@mw todo:
|
|
//Go over with Brian to determine the proper defines to wrap it and test cases to fix it.
|
|
/*
|
|
float2 PixelPos = SvPosition - View.ViewRectMin.xy;
|
|
MaterialParameters.ScreenPosition.xy = ( PixelPos / View.ViewSizeAndSceneTexelSize.xy - 0.5 ) * float2(2,-2);
|
|
MaterialParameters.ScreenPosition.zw = SvPosition.zw;
|
|
|
|
MaterialParameters.ScreenPosition.xyz *= MaterialParameters.ScreenPosition.w;
|
|
*/
|
|
|
|
// Store the results in local variables and reuse instead of calling the functions multiple times.
|
|
// Store the results in local variables and reuse instead of calling the functions multiple times.
|
|
half3 BaseColor = GetMaterialBaseColor( MaterialParameters );
|
|
half Metallic = GetMaterialMetallic( MaterialParameters );
|
|
half Specular = GetMaterialSpecular( MaterialParameters );
|
|
|
|
#if MATERIAL_NONMETAL
|
|
half3 DiffuseColor = BaseColor;
|
|
half SpecularColor = 0.04;
|
|
#else
|
|
half DielectricSpecular = 0.08 * Specular;
|
|
half3 DiffuseColor = BaseColor - BaseColor * Metallic; // 1 mad
|
|
half3 SpecularColor = (DielectricSpecular - DielectricSpecular * Metallic) + BaseColor * Metallic; // 2 mad
|
|
#endif
|
|
|
|
half Roughness = GetMaterialRoughness(MaterialParameters);
|
|
|
|
#if MATERIAL_FULLY_ROUGH
|
|
// Factors derived from EnvBRDFApprox( SpecularColor, 1, 1 ) == SpecularColor * 0.4524 - 0.0024
|
|
DiffuseColor += SpecularColor * 0.45;
|
|
SpecularColor = 0;
|
|
#else
|
|
half NoV = max( dot( MaterialParameters.WorldNormal, MaterialParameters.CameraVector ), 0 );
|
|
|
|
#if MATERIAL_NONMETAL
|
|
// If nothing is hooked up to Metalic and Specular,
|
|
// then defaults are the same as a non-metal,
|
|
// so this define is safe.
|
|
SpecularColor = EnvBRDFApproxNonmetal( Roughness, NoV );
|
|
#else
|
|
SpecularColor = EnvBRDFApprox( SpecularColor, Roughness, NoV );
|
|
#endif
|
|
#endif
|
|
|
|
half3 Color = 0;
|
|
half IndirectIrradiance = 0;
|
|
|
|
#if LQ_TEXTURE_LIGHTMAP
|
|
float2 LightmapUV0, LightmapUV1;
|
|
GetLightMapCoordinates(Interpolants, LightmapUV0, LightmapUV1);
|
|
|
|
half4 LightmapColor = GetLightMapColorLQ( LightmapUV0, LightmapUV1, MaterialParameters.WorldNormal );
|
|
Color += LightmapColor.rgb * DiffuseColor;
|
|
IndirectIrradiance = LightmapColor.a;
|
|
#elif CACHED_POINT_INDIRECT_LIGHTING
|
|
#if MATERIALBLENDING_MASKED || MATERIALBLENDING_SOLID
|
|
|
|
// Take the normal into account for opaque
|
|
FTwoBandSHVectorRGB PointIndirectLighting;
|
|
PointIndirectLighting.R.V = IndirectLightingSHCoefficients[0];
|
|
PointIndirectLighting.G.V = IndirectLightingSHCoefficients[1];
|
|
PointIndirectLighting.B.V = IndirectLightingSHCoefficients[2];
|
|
|
|
FTwoBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH(MaterialParameters.WorldNormal, 1);
|
|
|
|
// Compute diffuse lighting which takes the normal into account
|
|
half3 DiffuseGI = max(half3(0,0,0), DotSH(PointIndirectLighting, DiffuseTransferSH));
|
|
|
|
IndirectIrradiance = Luminance(DiffuseGI);
|
|
Color += DiffuseColor * DiffuseGI;
|
|
|
|
#else
|
|
|
|
// Non-directional for translucency
|
|
// Ambient terms packed in xyz
|
|
// Already divided by PI and SH ambient on CPU
|
|
half3 PointIndirectLighting = IndirectLightingSHCoefficients[0];
|
|
half3 DiffuseGI = PointIndirectLighting;
|
|
|
|
IndirectIrradiance = Luminance(DiffuseGI);
|
|
Color += DiffuseColor * DiffuseGI;
|
|
|
|
#endif
|
|
#endif
|
|
|
|
#if !MATERIAL_SHADINGMODEL_UNLIT
|
|
half Shadow = GetPrimaryPrecomputedShadowMask(Interpolants).r;
|
|
|
|
#if SIMPLE_DYNAMIC_LIGHTING
|
|
Shadow = DirectionalLightShadowing;
|
|
#endif
|
|
|
|
#if MOVABLE_DIRECTIONAL_LIGHT_CSM
|
|
// Cascaded Shadow Map
|
|
{
|
|
FPCFSamplerSettings Settings;
|
|
Settings.ShadowDepthTexture = View.DirectionalLightShadowTexture;
|
|
Settings.ShadowDepthTextureSampler = View.DirectionalLightShadowSampler;
|
|
Settings.TransitionScale = View.DirectionalLightShadowTransition;
|
|
Settings.ShadowBufferSize = View.DirectionalLightShadowSize;
|
|
Settings.bSubsurface = false;
|
|
Settings.DensityMulConstant = 0;
|
|
Settings.ProjectionDepthBiasParameters = 0;
|
|
|
|
float4 ShadowPosition;
|
|
#if MAX_FORWARD_SHADOWCASCADES == 2
|
|
{
|
|
if (MaterialParameters.ScreenPosition.w >= View.DirectionalLightShadowDistances.x)
|
|
{
|
|
ShadowPosition = mul(float4(MaterialParameters.ScreenPosition.xyw, 1), View.DirectionalLightScreenToShadow[1]);
|
|
}
|
|
else
|
|
{
|
|
ShadowPosition = mul(float4(MaterialParameters.ScreenPosition.xyw, 1), View.DirectionalLightScreenToShadow[0]);
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
ShadowPosition = mul(float4(MaterialParameters.ScreenPosition.xyw, 1), View.DirectionalLightScreenToShadow[0]);
|
|
}
|
|
#endif
|
|
|
|
// Clamp pixel depth in light space for shadowing opaque, because areas of the shadow depth buffer that weren't rendered to will have been cleared to 1
|
|
// We want to force the shadow comparison to result in 'unshadowed' in that case, regardless of whether the pixel being shaded is in front or behind that plane
|
|
float LightSpacePixelDepthForOpaque = min(ShadowPosition.z, 0.99999f);
|
|
Settings.SceneDepth = LightSpacePixelDepthForOpaque;
|
|
|
|
#if 0
|
|
half ShadowMap = Manual1x1PCF(ShadowPosition.xy, Settings);
|
|
#else
|
|
half ShadowMap = Manual2x2PCF(ShadowPosition.xy, Settings);
|
|
#endif
|
|
Shadow = min(Shadow, ShadowMap);
|
|
}
|
|
#endif
|
|
|
|
half NoL = max(0, dot(MaterialParameters.WorldNormal, View.DirectionalLightDirection));
|
|
half RoL = max(0, dot(MaterialParameters.ReflectionVector, View.DirectionalLightDirection));
|
|
|
|
Color += (Shadow * NoL) * View.DirectionalLightColor.rgb * (DiffuseColor + SpecularColor * PhongApprox(Roughness, RoL));
|
|
#if !MATERIAL_FULLY_ROUGH
|
|
half3 SpecularIBL = GetImageBasedReflectionLighting(MaterialParameters, Roughness);
|
|
// Environment map has been prenormalized, scale by lightmap luminance
|
|
Color += SpecularIBL * IndirectIrradiance * SpecularColor;
|
|
#endif
|
|
|
|
#if ENABLE_SKY_LIGHT
|
|
//@mw todo
|
|
// TODO: Also need to do specular.
|
|
Color += GetSkySHDiffuseSimple(MaterialParameters.WorldNormal) * View.SkyLightColor.rgb * DiffuseColor;
|
|
#endif
|
|
#endif
|
|
|
|
half Opacity = GetMaterialOpacity(MaterialParameters);
|
|
half3 Emissive = GetMaterialEmissive(MaterialParameters);
|
|
|
|
Color += Emissive;
|
|
|
|
half4 VertexFog = half4(0, 0, 0, 1);
|
|
#if USE_VERTEX_FOG
|
|
#if PACK_INTERPOLANTS
|
|
VertexFog = PackedInterpolants[0];
|
|
#else
|
|
VertexFog = BasePassInterpolants.VertexFog;
|
|
#endif
|
|
#endif
|
|
|
|
#if MATERIALBLENDING_TRANSLUCENT
|
|
OutColor = half4(Color * VertexFog.a + VertexFog.rgb, Opacity);
|
|
#elif MATERIALBLENDING_ADDITIVE
|
|
OutColor = half4(Color * (VertexFog.a * Opacity.x), 0.0f);
|
|
#elif MATERIALBLENDING_MODULATE
|
|
half3 FoggedColor = lerp(half3(1, 1, 1), Color, VertexFog.aaa * VertexFog.aaa);
|
|
OutColor = half4(FoggedColor, Opacity);
|
|
#else
|
|
OutColor.rgb = Color * VertexFog.a + VertexFog.rgb;
|
|
#if USE_HDR_MOSAIC || OUTPUT_GAMMA_SPACE
|
|
// Scene color alpha is not used yet so we set it to 0
|
|
OutColor.a = 0.0;
|
|
#else
|
|
// Place Z in FP16 alpha value.
|
|
OutColor.a = BasePassInterpolants.PixelPosition.w;
|
|
#endif
|
|
#endif
|
|
|
|
#if !MATERIALBLENDING_MODULATE
|
|
// The exposure scale is just a scalar but needs to be a float4 to workaround a driver bug on IOS.
|
|
// After 4.2 we can put the workaround in the cross compiler.
|
|
OutColor.rgba *= View.ExposureScale.xyzw;
|
|
#endif
|
|
|
|
#if OUTPUT_GAMMA_SPACE
|
|
OutColor.rgb = sqrt( OutColor.rgb );
|
|
#endif
|
|
|
|
#if (ES2_PROFILE || ES3_1_PROFILE) && (!OUTPUT_GAMMA_SPACE)
|
|
#if COMPILER_GLSL_ES2 || METAL_PROFILE
|
|
#if USE_HDR_MOSAIC
|
|
OutColor.rgb = HdrMosaic(OutColor.rgb, SvPosition.xy);
|
|
#endif
|
|
#else
|
|
// To enable editor runtime change without recompile, PC always eats the HdrMosaic() cost.
|
|
OutColor.rgb = View.HdrMosaic ? HdrMosaic(OutColor.rgb, SvPosition.xy) : OutColor.rgb;
|
|
#endif
|
|
#endif
|
|
}
|