65 lines
2.1 KiB
HLSL
65 lines
2.1 KiB
HLSL
#ifndef PBR_BRDF_HLSLI
|
|
#define PBR_BRDF_HLSLI
|
|
|
|
// [PBR-ADD: NEW FILE]
|
|
static const float PBR_PI = 3.14159265359f;
|
|
static const float PBR_EPSILON = 1.0e-5f;
|
|
|
|
float3 SafeNormalize(float3 value, float3 fallbackValue) {
|
|
const float lengthSquared = dot(value, value);
|
|
return lengthSquared > PBR_EPSILON ?
|
|
value * rsqrt(lengthSquared) : fallbackValue;
|
|
}
|
|
|
|
float3 BuildFallbackTangent(float3 normal) {
|
|
const float3 referenceAxis = abs(normal.y) < 0.999f ?
|
|
float3(0.0f, 1.0f, 0.0f) : float3(1.0f, 0.0f, 0.0f);
|
|
return SafeNormalize(cross(referenceAxis, normal), float3(1.0f, 0.0f, 0.0f));
|
|
}
|
|
|
|
float3 FresnelSchlick(float cosTheta, float3 f0) {
|
|
const float x = 1.0f - saturate(cosTheta);
|
|
const float x2 = x * x;
|
|
const float x5 = x2 * x2 * x;
|
|
return f0 + (1.0f - f0) * x5;
|
|
}
|
|
|
|
float DistributionGGX(float3 n, float3 h, float roughness) {
|
|
const float alpha = roughness * roughness;
|
|
const float alpha2 = alpha * alpha;
|
|
const float nDotH = saturate(dot(n, h));
|
|
const float nDotH2 = nDotH * nDotH;
|
|
const float denominator = nDotH2 * (alpha2 - 1.0f) + 1.0f;
|
|
return alpha2 / max(PBR_PI * denominator * denominator, PBR_EPSILON);
|
|
}
|
|
|
|
float GeometrySchlickGGX(float nDotX, float roughness) {
|
|
// UE4 常用的直接光 Schlick-GGX k。
|
|
const float r = roughness + 1.0f;
|
|
const float k = (r * r) / 8.0f;
|
|
return nDotX / max(nDotX * (1.0f - k) + k, PBR_EPSILON);
|
|
}
|
|
|
|
float GeometrySmith(float3 n, float3 v, float3 l, float roughness) {
|
|
const float nDotV = saturate(dot(n, v));
|
|
const float nDotL = saturate(dot(n, l));
|
|
return GeometrySchlickGGX(nDotV, roughness) * GeometrySchlickGGX(nDotL, roughness);
|
|
}
|
|
|
|
float3 DecodeNormalMap(float3 encodedNormal, float normalScale) {
|
|
float3 normalTS = encodedNormal * 2.0f - 1.0f;
|
|
normalTS.xy *= normalScale;
|
|
return normalize(normalTS);
|
|
}
|
|
|
|
float3 ToneMapACES(float3 color) {
|
|
const float a = 2.51f;
|
|
const float b = 0.03f;
|
|
const float c = 2.43f;
|
|
const float d = 0.59f;
|
|
const float e = 0.14f;
|
|
return saturate((color * (a * color + b)) / max(color * (c * color + d) + e, PBR_EPSILON));
|
|
}
|
|
|
|
#endif // PBR_BRDF_HLSLI
|