forked from LeenkxTeam/LNXSDK
Extend BRDF
This commit is contained in:
@ -138,4 +138,137 @@ float D_Approx(const float Roughness, const float RoL) {
|
||||
return rcp_a2 * exp2( c * RoL - c );
|
||||
}
|
||||
|
||||
#ifdef _ClearCoat
|
||||
vec3 clearcoatBRDF(const float clearcoat, const float clearcoat_rough,
|
||||
const float coat_ior,
|
||||
const float dotNL, const float dotNH, const float dotNV, const float dotVH) {
|
||||
if (clearcoat <= 0.0) return vec3(0.0);
|
||||
float a = clearcoat_rough * clearcoat_rough;
|
||||
// F0 from Fresnel equation for dielectric
|
||||
float ccF0 = (coat_ior - 1.0) / (coat_ior + 1.0);
|
||||
ccF0 = ccF0 * ccF0;
|
||||
float F = ccF0 + (1.0 - ccF0) * pow(1.0 - dotVH, 5.0);
|
||||
float D = d_ggx(dotNH, a);
|
||||
float G = g2_approx(dotNL, dotNV, a);
|
||||
return vec3(clearcoat * D * G * F / max(4.0 * dotNV, 1e-5));
|
||||
}
|
||||
|
||||
float coatAttenuation(const float clearcoat,
|
||||
const float coat_ior, const float dotNV) {
|
||||
if (clearcoat <= 0.0) return 1.0;
|
||||
float ccF0 = (coat_ior - 1.0) / (coat_ior + 1.0);
|
||||
ccF0 = ccF0 * ccF0;
|
||||
// Schlick with pow(.,5) - cheaper than exp2
|
||||
float F = ccF0 + (1.0 - ccF0) * pow(1.0 - dotNV, 5.0);
|
||||
return max(1.0 - F * clearcoat, 0.0);
|
||||
}
|
||||
|
||||
vec3 coatTintAttenuation(const float clearcoat, const vec3 coat_tint, const float dotNV) {
|
||||
if (clearcoat <= 0.0) return vec3(1.0);
|
||||
float absorption = 1.0 / max(dotNV, 0.3);
|
||||
return mix(vec3(1.0), coat_tint, clamp(absorption * 0.2, 0.0, 1.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Sheen
|
||||
// based on Blender sheen model/Frostbite PBR
|
||||
vec3 sheenBRDF(const float sheen, const float sheen_rough,
|
||||
const vec3 sheen_tint, const float dotNL, const float dotNH, const float dotNV) {
|
||||
if (sheen <= 0.0) return vec3(0.0);
|
||||
float rough = clamp(sheen_rough, 1e-3, 1.0);
|
||||
float a = rough * rough;
|
||||
float sinNH2 = 1.0 - dotNH * dotNH;
|
||||
float a2 = a * a;
|
||||
float D = (2.0 + a2) * sinNH2 / (2.0 * 3.1415926535 * pow(1.0 + a2 * sinNH2, 2.0));
|
||||
float V = 1.0 / (4.0 * dotNL * dotNV + 1e-5);
|
||||
float sheenAlbedo = (1.0 - 0.5 * rough) * mix(1.0, dotNV, 0.5);
|
||||
return sheen_tint * sheen * D * V * dotNL * sheenAlbedo;
|
||||
}
|
||||
|
||||
float sheenAttenuation(const float sheen, const float sheen_rough,
|
||||
const vec3 sheen_tint, const float dotNV) {
|
||||
if (sheen <= 0.0) return 1.0;
|
||||
float rough = clamp(sheen_rough, 1e-3, 1.0);
|
||||
float sheenAlbedo = (1.0 - 0.5 * rough) * mix(1.0, dotNV, 0.5);
|
||||
float maxComp = sheen * max(max(sheen_tint.r, sheen_tint.g), sheen_tint.b) * sheenAlbedo;
|
||||
return max(1.0 - maxComp, 0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Anisotropy
|
||||
// anisotropic GGX Burley 2012
|
||||
vec3 anisotropicBRDF(const vec3 f0, const float roughness, const float anisotropy,
|
||||
const float aniso_rot, const vec3 tangent, const vec3 bitangent,
|
||||
const vec3 n, const vec3 l, const vec3 v,
|
||||
const float dotNL, const float dotNV) {
|
||||
if (abs(anisotropy) <= 0.001) return vec3(0.0);
|
||||
float rot = aniso_rot * 3.1415926535 * 2.0;
|
||||
float cr = cos(rot);
|
||||
float sr = sin(rot);
|
||||
vec3 t = normalize(tangent * cr + bitangent * sr);
|
||||
vec3 b = normalize(bitangent * cr - tangent * sr);
|
||||
float aniso_abs = abs(anisotropy);
|
||||
float at = max(roughness * (1.0 + aniso_abs), 1e-5);
|
||||
float ab = max(roughness * (1.0 - aniso_abs), 1e-5);
|
||||
if (anisotropy < 0.0) { vec3 tmp = t; t = b; b = tmp; }
|
||||
float at2 = at * at;
|
||||
float ab2 = ab * ab;
|
||||
vec3 h = normalize(l + v);
|
||||
float dotTH = dot(t, h);
|
||||
float dotBH = dot(b, h);
|
||||
float dotTV = dot(t, v);
|
||||
float dotBV = dot(b, v);
|
||||
float dotTL = dot(t, l);
|
||||
float dotBL = dot(b, l);
|
||||
float denom = max(dotTH * dotTH / at2 + dotBH * dotBH / ab2, 1e-7);
|
||||
float D = 1.0 / (3.1415926535 * at * ab * denom * denom);
|
||||
float V = 1.0 / max(dotNL * (dotTL / at + dotBL / ab) * (dotTV / at + dotBV / ab), 1e-5);
|
||||
float dotVH = max(dot(v, h), 0.0);
|
||||
vec3 F = f_schlick(f0, dotVH);
|
||||
return D * V * F / max(4.0 * dotNV, 1e-5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Subsurface
|
||||
// Blenders bssrdf_burley implementation
|
||||
vec3 subsurfaceBRDF(const vec3 albedo, const vec3 sss_color,
|
||||
const vec3 sss_radius, const float subsurface, const float sss_anisotropy,
|
||||
const float dotNL) {
|
||||
if (subsurface <= 0.0) return vec3(0.0);
|
||||
vec3 mfp = sss_radius * (0.25 / 3.1415926535);
|
||||
vec3 A = clamp(albedo, 0.0, 1.0);
|
||||
vec3 d = 1.9 - A + 3.5 * (A - 0.8) * (A - 0.8);
|
||||
d = mfp / max(d, 1e-5);
|
||||
float aniso = clamp(sss_anisotropy, 0.0, 0.9);
|
||||
float scatter = subsurface * (1.0 / 3.1415926535);
|
||||
vec3 sssDiffuse = sss_color * scatter * dotNL;
|
||||
float backScatter = max(0.0, 1.0 - dotNL) * (1.0 - aniso) * 0.5;
|
||||
vec3 sssBack = sss_color * subsurface * backScatter;
|
||||
float dist = max(0.0, 1.0 - dotNL);
|
||||
vec3 rcp_d = 1.0 / max(d, vec3(1e-5));
|
||||
vec3 x = vec3(dist) * rcp_d;
|
||||
vec3 extinction = 1.0 / (1.0 + x + 0.5 * x * x);
|
||||
return sssDiffuse * extinction + sssBack * (vec3(1.0) - extinction);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Transmission
|
||||
// Blenders microfacet glass/refraction model
|
||||
vec3 transmissionBRDF(const vec3 albedo, const float transmission,
|
||||
const float trans_rough, const float ior, const float thin_wall,
|
||||
const float dotNL, const float dotNV, const float dotVH) {
|
||||
if (transmission <= 0.0) return vec3(0.0);
|
||||
float F0 = (ior - 1.0) / (ior + 1.0);
|
||||
F0 = F0 * F0;
|
||||
float F = F0 + (1.0 - F0) * pow(1.0 - dotVH, 5.0);
|
||||
float transmittance = 1.0 - F;
|
||||
if (thin_wall > 0.5) {
|
||||
return albedo * transmission * transmittance * dotNL;
|
||||
}
|
||||
float a = trans_rough * trans_rough;
|
||||
float rough_atten = mix(1.0, 1.0 / max(dotNV, 0.1), a);
|
||||
return albedo * transmission * transmittance * rough_atten * dotNL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -170,4 +170,19 @@ void unpackFloatInt16(float val, out float f, out uint i) {
|
||||
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
||||
}
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
// extended material parameters by material slot ID returns vec4s (28 floats) of extended BRDF parameters
|
||||
void getMaterialParams(uint matid, out vec4 p0, out vec4 p1, out vec4 p2, out vec4 p3,
|
||||
out vec4 p4, out vec4 p5, out vec4 p6) {
|
||||
uint base = matid * 8u;
|
||||
p0 = materialParams[base];
|
||||
p1 = materialParams[base + 1u];
|
||||
p2 = materialParams[base + 2u];
|
||||
p3 = materialParams[base + 3u];
|
||||
p4 = materialParams[base + 4u];
|
||||
p5 = materialParams[base + 5u];
|
||||
p6 = materialParams[base + 6u];
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -131,6 +131,21 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, float transmission, float transRough, float ior, float thinWall
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
@ -153,9 +168,49 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#else
|
||||
#ifdef _Anisotropy
|
||||
vec3 direct;
|
||||
if (abs(anisotropy) > 0.001) {
|
||||
vec3 bitangent = normalize(cross(n, tangent));
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
|
||||
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
|
||||
} else {
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
}
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// before attenuate/shadow so everything is properly shadowed in one pass
|
||||
float sheenWeight = 1.0;
|
||||
float coatWeight = 1.0;
|
||||
#ifdef _Sheen
|
||||
vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV);
|
||||
sheenWeight = sheenAttenuation(sheen, sheenRough, sheenTint, dotNV);
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, dotNL, dotNH, dotNV, dotVH);
|
||||
coatWeight = coatAttenuation(clearcoat, coatIOR, dotNV);
|
||||
#endif
|
||||
float layerWeight = sheenWeight * coatWeight;
|
||||
direct *= layerWeight;
|
||||
#ifdef _Subsurface
|
||||
direct += subsurfaceBRDF(albedo, sssColor, sssRadius, subsurface, sssAnisotropy, dotNL) * layerWeight;
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
direct += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
direct *= coatTintAttenuation(clearcoat, coatTint, dotNV);
|
||||
direct += coatContrib * sheenWeight;
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
direct += sheenContrib;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= min(lightCol, vec3(100.0));
|
||||
@ -418,6 +473,21 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, float transmission, float transRough, float ior, float thinWall
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
@ -444,6 +514,32 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
|
||||
float sheenWeight = 1.0;
|
||||
float coatWeight = 1.0;
|
||||
#ifdef _Sheen
|
||||
vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV);
|
||||
sheenWeight = sheenAttenuation(sheen, sheenRough, sheenTint, dotNV);
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, dotNL, dotNH, dotNV, dotVH);
|
||||
coatWeight = coatAttenuation(clearcoat, coatIOR, dotNV);
|
||||
#endif
|
||||
float layerWeight = sheenWeight * coatWeight;
|
||||
direct *= layerWeight;
|
||||
#ifdef _Subsurface
|
||||
direct += subsurfaceBRDF(albedo, sssColor, sssRadius, subsurface, sssAnisotropy, dotNL) * layerWeight;
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
direct += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
direct *= coatTintAttenuation(clearcoat, coatTint, dotNV);
|
||||
direct += coatContrib * sheenWeight;
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
direct += sheenContrib;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
// CRITICAL: Clamp light color to prevent extreme HDR values causing white sphere artifacts
|
||||
direct *= min(lightCol, vec3(100.0));
|
||||
|
||||
@ -53,6 +53,21 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _Spot
|
||||
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, float transmission, float transRough, float ior, float thinWall
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
@ -61,8 +76,47 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _Anisotropy
|
||||
vec3 direct;
|
||||
if (abs(anisotropy) > 0.001) {
|
||||
vec3 bitangent = normalize(cross(n, tangent));
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
|
||||
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
|
||||
} else {
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
}
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
|
||||
float sheenWeight = 1.0;
|
||||
float coatWeight = 1.0;
|
||||
#ifdef _Sheen
|
||||
vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV);
|
||||
sheenWeight = sheenAttenuation(sheen, sheenRough, sheenTint, dotNV);
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, dotNL, dotNH, dotNV, dotVH);
|
||||
coatWeight = coatAttenuation(clearcoat, coatIOR, dotNV);
|
||||
#endif
|
||||
float layerWeight = sheenWeight * coatWeight;
|
||||
direct *= layerWeight;
|
||||
#ifdef _Subsurface
|
||||
direct += subsurfaceBRDF(albedo, sssColor, sssRadius, subsurface, sssAnisotropy, dotNL) * layerWeight;
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
direct += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
direct *= coatTintAttenuation(clearcoat, coatTint, dotNV);
|
||||
direct += coatContrib * sheenWeight;
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
direct += sheenContrib;
|
||||
#endif
|
||||
|
||||
direct *= lightCol;
|
||||
direct *= attenuate(distance(p, lp));
|
||||
|
||||
Reference in New Issue
Block a user