You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
1) View.ExposureScale is now a float4 instead of a scalar. This appears to workaround an iOS driver bug. This workaround can be moved in to the cross compiler after 4.2. 2) Clamp the number of supported vertex uniform vectors to be at least 256. The engine assumes it has at least 256 to work with for skinned meshes. This prevents a memory overwrite bug. The iOS driver works with more uniforms than it claims to support. 3) Fixed an off-by-one bug in dirty range tracking for global uniform buffers. [CL 2091350 by Nick Penwarden in Main branch]
248 lines
8.5 KiB
Plaintext
248 lines
8.5 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"
|
|
|
|
#define MATERIAL_NONMETAL 0
|
|
|
|
/** 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)
|
|
half2 c = half2( 0.72134752, 0.25 ) * rcp_a2 + half2( 0.39674113, 0.75 ); // 1 mad
|
|
return c.y * exp2( c.x * RoL - c.x ); // 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,
|
|
#if ES2_PROFILE && (USE_HDR_MOSAIC || !COMPILER_GLSL_ES2)
|
|
in half4 SvPosition : SV_Position,
|
|
#endif
|
|
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);
|
|
|
|
#if COMPILER_HLSL // Not sure why this isn't needed everywhere
|
|
float2 PixelPos = SvPosition - View.ScreenTexelBias.xy;
|
|
MaterialParameters.ScreenPosition.xy = ( PixelPos / View.ViewSizeAndSceneTexelSize.xy - 0.5 ) * float2(2,-2);
|
|
MaterialParameters.ScreenPosition.zw = SvPosition.zw;
|
|
|
|
MaterialParameters.ScreenPosition.xyz *= MaterialParameters.ScreenPosition.w;
|
|
#endif
|
|
|
|
// Store the results in local variables and reuse instead of calling the functions multiple times.
|
|
#if DIFFUSE_SPEC_INPUTS
|
|
half3 DiffuseColor = GetMaterialDiffuseColor( MaterialParameters );
|
|
half3 SpecularColor = GetMaterialSpecularColor( MaterialParameters );
|
|
#else
|
|
// 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
|
|
#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
|
|
|
|
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
|
|
#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.rgb *= View.ExposureScale.xyz;
|
|
#endif
|
|
|
|
#if OUTPUT_GAMMA_SPACE
|
|
OutColor.rgb = sqrt( OutColor.rgb );
|
|
#endif
|
|
|
|
#if ES2_PROFILE && (!OUTPUT_GAMMA_SPACE)
|
|
#if COMPILER_GLSL_ES2
|
|
#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
|
|
}
|