**Add Box Projection to Environment Probe** for better indoor areas
This commit is contained in:
@@ -170,18 +170,6 @@ struct AtmosphericFogData
|
||||
float AtmosphericFogDensityOffset;
|
||||
};
|
||||
|
||||
// Packed env probe data
|
||||
struct ProbeData
|
||||
{
|
||||
float4 Data0; // x - Position.x, y - Position.y, z - Position.z, w - unused
|
||||
float4 Data1; // x - Radius , y - 1 / Radius, z - Brightness, w - unused
|
||||
};
|
||||
|
||||
#define ProbePos Data0.xyz
|
||||
#define ProbeRadius Data1.x
|
||||
#define ProbeInvRadius Data1.y
|
||||
#define ProbeBrightness Data1.z
|
||||
|
||||
struct Quad_VS2PS
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/BRDF.hlsl"
|
||||
#include "./Flax/Random.hlsl"
|
||||
#include "./Flax/Noise.hlsl"
|
||||
#include "./Flax/MonteCarlo.hlsl"
|
||||
#include "./Flax/LightingCommon.hlsl"
|
||||
#include "./Flax/GBuffer.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/ReflectionsCommon.hlsl"
|
||||
#include "./Flax/BRDF.hlsl"
|
||||
|
||||
META_CB_BEGIN(0, Data)
|
||||
|
||||
ProbeData PData;
|
||||
EnvProbeData PData;
|
||||
float4x4 WVP;
|
||||
GBufferData GBuffer;
|
||||
|
||||
META_CB_END
|
||||
|
||||
DECLARE_GBUFFERDATA_ACCESS(GBuffer)
|
||||
@@ -25,7 +19,7 @@ TextureCube Probe : register(t4);
|
||||
Texture2D Reflections : register(t5);
|
||||
Texture2D PreIntegratedGF : register(t6);
|
||||
|
||||
// Vertex Shader for models rendering
|
||||
// Vertex Shader for probe shape rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
Model_VS2PS VS_Model(ModelInput_PosOnly input)
|
||||
|
||||
@@ -4,45 +4,86 @@
|
||||
#define __REFLECTIONS_COMMON__
|
||||
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
#include "./Flax/Quaternion.hlsl"
|
||||
|
||||
// Hit depth (view space) threshold to detect if sky was hit (value above it where 1.0f is default)
|
||||
#define REFLECTIONS_HIT_THRESHOLD 0.9f
|
||||
|
||||
// Packed env probe data
|
||||
struct EnvProbeData
|
||||
{
|
||||
float4 Data0; // x - Position.x | y - Position.y | z - Position.z | w - Brightness (negative for BoxProjection)
|
||||
float4 Data1; // x - Radius/BoxExtent.x | y - BoxExtent.y | z - BoxExtent.z | w - BlendDistance
|
||||
float4 Data2; // x - BoxInvQuat.x | y - BoxInvQuat.y | z - BoxInvQuat.z | w - BoxInvQuat.w
|
||||
};
|
||||
|
||||
#define EnvProbePosition(data) data.Data0.xyz
|
||||
#define EnvProbeBrightness(data) abs(data.Data0.w)
|
||||
#define EnvProbeBoxProjection(data) (data.Data0.w < 0.0f)
|
||||
#define EnvProbeBoxExtent(data) data.Data1.xyz
|
||||
#define EnvProbeBoxInvQuat(data) data.Data2
|
||||
#define EnvProbeSphereRadius(data) data.Data1.x
|
||||
#define EnvProbeBlendDistance(data) data.Data1.w
|
||||
|
||||
float GetSpecularOcclusion(float NoV, float roughnessSq, float ao)
|
||||
{
|
||||
return saturate(pow(NoV + ao, roughnessSq) - 1 + ao);
|
||||
}
|
||||
|
||||
float4 SampleReflectionProbe(float3 viewPos, TextureCube probe, ProbeData data, float3 positionWS, float3 normal, float roughness)
|
||||
float4 SampleReflectionProbe(float3 viewPos, TextureCube probe, EnvProbeData data, float3 positionWS, float3 normal, float roughness)
|
||||
{
|
||||
// Calculate distance from probe to the pixel
|
||||
float3 captureVector = positionWS - data.ProbePos;
|
||||
float captureVectorLength = length(captureVector);
|
||||
|
||||
// Check if cannot light pixel
|
||||
// TODO: maybe remove this check?? - test it out with dozens of probes
|
||||
BRANCH
|
||||
if (captureVectorLength >= data.ProbeRadius)
|
||||
// Calculate fade based on distance to the probe
|
||||
float3 captureVector = positionWS - EnvProbePosition(data);
|
||||
float distanceAlpha;
|
||||
if (EnvProbeBoxProjection(data))
|
||||
{
|
||||
// End
|
||||
return 0;
|
||||
// Box shape
|
||||
float3 boxExtent = EnvProbeBoxExtent(data);
|
||||
float blendDistance = EnvProbeBlendDistance(data);
|
||||
float3 pos = QuaternionRotate(EnvProbeBoxInvQuat(data), captureVector);
|
||||
float3 clampedPos = clamp(pos, -boxExtent + blendDistance, boxExtent - blendDistance);
|
||||
float distanceToBox = length(clampedPos - pos);
|
||||
distanceAlpha = saturate(1 - distanceToBox / blendDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sphere shape
|
||||
float normalizedDistanceToCapture = saturate(length(captureVector) / EnvProbeSphereRadius(data));
|
||||
distanceAlpha = 1.0 - smoothstep(0.7f, 1, normalizedDistanceToCapture);
|
||||
}
|
||||
|
||||
// Fade out based on distance to capture
|
||||
float normalizedDistanceToCapture = saturate(captureVectorLength * data.ProbeInvRadius);
|
||||
float distanceAlpha = 1.0 - smoothstep(0.7, 1, normalizedDistanceToCapture);
|
||||
float fade = distanceAlpha * data.ProbeBrightness;
|
||||
// Early out without sampling texture if out of the bounds
|
||||
BRANCH
|
||||
if (distanceAlpha <= 0.0f)
|
||||
return float4(0, 0, 0, 0);
|
||||
|
||||
// Calculate reflection vector
|
||||
// Calculate probe sampling coordinates
|
||||
float3 sampleVector;
|
||||
float3 V = normalize(positionWS - viewPos);
|
||||
float3 R = reflect(V, normal);
|
||||
float3 D = data.ProbeInvRadius * captureVector + R;
|
||||
if (EnvProbeBoxProjection(data))
|
||||
{
|
||||
// Box projection
|
||||
float3 rotatedReflection = QuaternionRotate(EnvProbeBoxInvQuat(data), R);
|
||||
float3 boxExtent = EnvProbeBoxExtent(data);
|
||||
float3 boxMinMax = select(rotatedReflection > 0.0f, boxExtent, -boxExtent);
|
||||
float3 pos = QuaternionRotate(EnvProbeBoxInvQuat(data), captureVector);
|
||||
float3 rotatedPos = float3(boxMinMax - pos) / rotatedReflection;
|
||||
float minDir = min(min(rotatedPos.x, rotatedPos.y), rotatedPos.z);
|
||||
float3 dir = pos + rotatedReflection * minDir;
|
||||
sampleVector = QuaternionRotate(float4(-EnvProbeBoxInvQuat(data).xyz, EnvProbeBoxInvQuat(data).w), dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sphere projection
|
||||
sampleVector = captureVector / EnvProbeSphereRadius(data) + R;
|
||||
}
|
||||
|
||||
// Sample probe at valid mip level based on surface roughness value
|
||||
half mip = ProbeMipFromRoughness(roughness);
|
||||
float4 probeSample = probe.SampleLevel(SamplerLinearClamp, D, mip);
|
||||
float mip = ProbeMipFromRoughness(roughness);
|
||||
float4 probeSample = probe.SampleLevel(SamplerLinearClamp, sampleVector, mip);
|
||||
|
||||
return probeSample * fade;
|
||||
return probeSample * (distanceAlpha * EnvProbeBrightness(data));
|
||||
}
|
||||
|
||||
// Calculates the reflective environment lighting to multiply the raw reflection color for the specular light (eg. from Env Probe or SSR).
|
||||
|
||||
Reference in New Issue
Block a user