Urho3D/bin/CoreData/Shaders/HLSL/IBL.hlsl

78 lines
3.1 KiB
HLSL

#ifdef COMPILEPS
float GetMipFromRoughness(float roughness)
{
return (roughness * 12.0 - pow(roughness, 6.0) * 1.5);
}
float3 EnvBRDFApprox (float3 specColor, float roughness, float ndv)
{
const float4 c0 = float4(-1, -0.0275, -0.572, 0.022 );
const float4 c1 = float4(1, 0.0425, 1.0, -0.04 );
float4 r = roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( -9.28 * ndv ) ) * r.x + r.y;
float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw;
return specColor * AB.x + AB.y;
}
float3 FixCubeLookup(float3 v)
{
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = (1024 - 1) / 1024;
if (abs(v.x) != M) v.x += scale;
if (abs(v.y) != M) v.y += scale;
if (abs(v.z) != M) v.z += scale;
return v;
}
/// Calculate IBL contributation
/// reflectVec: reflection vector for cube sampling
/// wsNormal: surface normal in word space
/// toCamera: normalized direction from surface point to camera
/// roughness: surface roughness
/// ambientOcclusion: ambient occlusion
float3 ImageBasedLighting(in float3 reflectVec, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor)
{
roughness = max(roughness, 0.08);
reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness);
const float ndv = saturate(dot(-toCamera, wsNormal));
/// Test: Parallax correction, currently not working
// float3 intersectMax = (cZoneMax - toCamera) / reflectVec;
// float3 intersectMin = (cZoneMin - toCamera) / reflectVec;
// float3 furthestPlane = max(intersectMax, intersectMin);
// float planeDistance = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
// // Get the intersection position
// float3 intersectionPos = toCamera + reflectVec * planeDistance;
// // Get corrected reflection
// reflectVec = intersectionPos - ((cZoneMin + cZoneMax )/ 2);
const float mipSelect = GetMipFromRoughness(roughness);
float3 cube = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(reflectVec), mipSelect)).rgb;
float3 cubeD = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(wsNormal), 9.0)).rgb;
// Fake the HDR texture
float brightness = clamp(cAmbientColor.a, 0.0, 1.0);
float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25);
const float hdrMaxBrightness = 5.0;
float3 hdrCube = pow(cube + darknessCutoff, max(1.0, cAmbientColor.a));
hdrCube += max(0.0, hdrCube - 1.0) * hdrMaxBrightness;
float3 hdrCubeD = pow(cubeD + darknessCutoff, max(1.0, cAmbientColor.a));
hdrCubeD += max(0.0, hdrCubeD - 1.0) * hdrMaxBrightness;
const float3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv);
const float3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv);
return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness;
}
#endif