Files
UnrealEngineUWP/Engine/Shaders/ReflectionEnvironmentShared.usf
Daniel Wright 1464dcf2c3 Distance field AO using a surface cache
* Provides mid-range stable AO for dynamic rigid meshes
* Movable sky lights are now supported, and distance field AO is used for shadowing Movable sky lighting from dynamic scenes
* Static meshes are preprocessed into signed distance field volumes at mesh build time when the r.AllowMeshDistanceFieldRepresentations project setting is enabled
* Non-uniform scaling does not work with this method (mirroring is fine), animating through world position offset also causes artifacts as the two representations diverge
* Occlusion is computed along cones to reduce over-shadowing, object distance fields are operated on directly (no hierarchy) to obtain enough resolution to prevent leaking, visibility traces are done with cone stepping to allow better parallelization, and shading is done adaptively in space and time using the surface cache.

[CL 2093556 by Daniel Wright in Main branch]
2014-06-03 15:53:13 -04:00

71 lines
3.0 KiB
Plaintext

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
ReflectionEnvironmentShared
=============================================================================*/
#define REFLECTION_CAPTURE_ROUGHEST_MIP 1
#define REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE 1.2
/**
* Compute absolute mip for a reflection capture cubemap given a roughness.
*/
half ComputeReflectionCaptureMipFromRoughness(half Roughness)
{
// Heuristic that maps roughness to mip level
// This is done in a way such that a certain mip level will always have the same roughness, regardless of how many mips are in the texture
// Using more mips in the cubemap just allows sharper reflections to be supported
// Note: this must match the logic in FilterReflectionEnvironment that generates the mip filter samples!
half LevelFrom1x1 = REFLECTION_CAPTURE_ROUGHEST_MIP - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(Roughness);
// Note: must match GReflectionCaptureSize
half HardcodedNumCaptureArrayMips = 7;
return HardcodedNumCaptureArrayMips - 1 - LevelFrom1x1;
}
TextureCube SkyLightCubemap;
SamplerState SkyLightCubemapSampler;
/** X = max mip, Y = 1 if sky light should be rendered, 0 otherwise. */
float2 SkyLightParameters;
float3 GetSkyLightReflection(float3 ReflectionVector, float Roughness, bool Normalized)
{
float AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness);
float3 Reflection = TextureCubeSampleLevel(SkyLightCubemap, SkyLightCubemapSampler, ReflectionVector, AbsoluteSpecularMip).rgb;
FLATTEN
if (Normalized)
{
// Sample the lowest resolution mip to get the average color
//@todo - can't normalize sky lighting and reflection capture lighting separately
float3 LowFrequencyReflection = TextureCubeSampleLevel(SkyLightCubemap, SkyLightCubemapSampler, ReflectionVector, SkyLightParameters.x).rgb;
float LowFrequencyBrightness = Luminance(LowFrequencyReflection);
Reflection /= max(LowFrequencyBrightness, .00001f);
}
return Reflection * View.SkyLightColor.rgb;
}
/**
* Computes sky diffuse lighting from the SH irradiance map.
* This has the SH basis evaluation and diffuse convolusion weights combined for minimal ALU's - see "Stupid Spherical Harmonics (SH) Tricks"
*/
float3 GetSkySHDiffuse(float3 Normal)
{
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0, Intermediate1, Intermediate2;
Intermediate0.x = dot(View.SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(View.SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(View.SkyIrradianceEnvironmentMap[2], NormalVector);
float4 vB = NormalVector.xyzz * NormalVector.yzzx;
Intermediate1.x = dot(View.SkyIrradianceEnvironmentMap[3], vB);
Intermediate1.y = dot(View.SkyIrradianceEnvironmentMap[4], vB);
Intermediate1.z = dot(View.SkyIrradianceEnvironmentMap[5], vB);
float vC = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y;
Intermediate2 = View.SkyIrradianceEnvironmentMap[6].xyz * vC;
return Intermediate0 + Intermediate1 + Intermediate2;
}