Extend BRDF

This commit is contained in:
2026-07-27 12:10:11 -07:00
parent 0b4184ccc2
commit 7aeebf2008
24 changed files with 878 additions and 3 deletions

View File

@ -21,6 +21,8 @@ in vec3 wnormal;
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_EMISSION | _EmissionShaded || emission color (RGB) | unused |
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_3 | _Anisotropy || world tangent (XYZ) | unused |
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
The indices as well as the GBUF_SIZE define are defined in "compiled.inc".
*/
@ -54,4 +56,8 @@ void main() {
#ifdef _SSRefraction
fragColor[GBUF_IDX_REFRACTION] = vec4(ior, opacity, 0.0, 0.0);
#endif
#ifdef _Anisotropy
fragColor[GBUF_IDX_3] = vec4(0.0, 0.0, 0.0, 0.0);
#endif
}

View File

@ -14,6 +14,7 @@
#ifdef _SSRS
#include "std/ssrs.glsl"
#endif
#include "std/brdf.glsl"
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
@ -22,6 +23,9 @@ uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
#ifdef _Anisotropy
uniform sampler2D gbuffer3;
#endif
#ifdef _EmissionShaded
uniform sampler2D gbufferEmission;
#endif
@ -254,6 +258,13 @@ void main() {
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
#ifdef _ExtBRDF
matid = min(matid, uint(MAX_MATERIALS - 1));
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
vec4 matp0, matp1, matp2, matp3, matp4, matp5, matp6;
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6);
#endif
vec2 occspec = unpackFloat2(g1.a);
// re-investigate clamp basecolor to prevent extreme values causing glitches
@ -283,6 +294,11 @@ void main() {
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
#endif
#ifdef _Anisotropy
vec4 g3 = textureLod(gbuffer3, texCoord, 0.0);
vec3 wTangent = length(g3.xyz) > 0.0 ? normalize(g3.xyz) : vec3(1.0, 0.0, 0.0);
#endif
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
@ -406,8 +422,50 @@ void main() {
float sdotVH = max(0.0, dot(v, sh));
float sdotNL = max(0.0, dot(n, sunDir));
vec3 svisibility = vec3(1.0);
#ifdef _Anisotropy
vec3 sdirect;
if (abs(matp0.x) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif
float sunSheenWeight = 1.0;
float sunCoatWeight = 1.0;
#ifdef _Sheen
vec3 sunSheen = sheenBRDF(matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x), sdotNL, sdotNH, dotNV);
sunSheenWeight = sheenAttenuation(matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x), dotNV);
#endif
#ifdef _ClearCoat
vec3 sunCoat = clearcoatBRDF(matp1.x, matp1.y, matp1.z, sdotNL, sdotNH, dotNV, sdotVH);
sunCoatWeight = coatAttenuation(matp1.x, matp1.z, dotNV);
#endif
float sunLayerWeight = sunSheenWeight * sunCoatWeight;
sdirect *= sunLayerWeight;
#ifdef _Subsurface
sdirect += subsurfaceBRDF(albedo, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.z, matp3.w, sdotNL) * sunLayerWeight;
#endif
#ifdef _Transmission
sdirect += transmissionBRDF(albedo, matp2.z, matp2.w, matp3.x, matp3.y, sdotNL, dotNV, sdotVH) * sunLayerWeight;
#endif
#ifdef _ClearCoat
sdirect *= coatTintAttenuation(matp1.x, vec3(matp1.w, matp2.x, matp2.y), dotNV);
sdirect += sunCoat * sunSheenWeight;
#endif
#ifdef _Sheen
sdirect += sunSheen;
#endif
#ifdef _ShadowMap
#ifdef _CSM
@ -555,6 +613,21 @@ void main() {
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
#endif
#ifdef _Sheen
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _Subsurface
, matp3.z, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
#ifdef _Spot
@ -618,6 +691,21 @@ void main() {
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
#endif
#ifdef _Sheen
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _Subsurface
, matp3.z, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
}
#endif // _Clusters

View File

@ -277,6 +277,11 @@
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats"
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",

View File

@ -3,6 +3,7 @@
#include "compiled.inc"
#include "std/gbuffer.glsl"
#include "std/math.glsl"
#include "std/brdf.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
@ -13,6 +14,9 @@
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
#ifdef _Anisotropy
uniform sampler2D gbuffer3;
#endif
uniform float envmapStrength;
#ifdef _Irr
@ -132,6 +136,13 @@ void main() {
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
#ifdef _ExtBRDF
matid = min(matid, uint(MAX_MATERIALS - 1));
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
vec4 matp0, matp1, matp2, matp3, matp4, matp5, matp6;
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6);
#endif
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a);
@ -143,6 +154,11 @@ void main() {
vec3 v = normalize(eye - p);
float dotNV = max(dot(n, v), 0.0);
#ifdef _Anisotropy
vec4 g3 = textureLod(gbuffer3, texCoord, 0.0);
vec3 wTangent = length(g3.xyz) > 0.0 ? normalize(g3.xyz) : vec3(1.0, 0.0, 0.0);
#endif
#ifdef _Brdf
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
#endif
@ -189,8 +205,50 @@ void main() {
float sdotVH = max(0.0, dot(v, sh));
float sdotNL = max(0.0, dot(n, sunDir));
float svisibility = 1.0;
#ifdef _Anisotropy
vec3 sdirect;
if (abs(matp0.x) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif
float sunSheenWeight = 1.0;
float sunCoatWeight = 1.0;
#ifdef _Sheen
vec3 sunSheen = sheenBRDF(matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x), sdotNL, sdotNH, dotNV);
sunSheenWeight = sheenAttenuation(matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x), dotNV);
#endif
#ifdef _ClearCoat
vec3 sunCoat = clearcoatBRDF(matp1.x, matp1.y, matp1.z, sdotNL, sdotNH, dotNV, sdotVH);
sunCoatWeight = coatAttenuation(matp1.x, matp1.z, dotNV);
#endif
float sunLayerWeight = sunSheenWeight * sunCoatWeight;
sdirect *= sunLayerWeight;
#ifdef _Subsurface
sdirect += subsurfaceBRDF(albedo, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.z, matp3.w, sdotNL) * sunLayerWeight;
#endif
#ifdef _Transmission
sdirect += transmissionBRDF(albedo, matp2.z, matp2.w, matp3.x, matp3.y, sdotNL, dotNV, sdotVH) * sunLayerWeight;
#endif
#ifdef _ClearCoat
sdirect *= coatTintAttenuation(matp1.x, vec3(matp1.w, matp2.x, matp2.y), dotNV);
sdirect += sunCoat * sunSheenWeight;
#endif
#ifdef _Sheen
sdirect += sunSheen;
#endif
#ifdef _ShadowMap
#ifdef _CSM
@ -235,6 +293,21 @@ void main() {
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight // TODO: Test!
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
#endif
#ifdef _Sheen
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _Subsurface
, matp3.z, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
#endif
@ -277,6 +350,21 @@ void main() {
, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale
, lightsArraySpot[li * 2 + 1].xyz // right
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
#endif
#ifdef _Sheen
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _Subsurface
, matp3.z, vec3(matp4.w, matp5.x, matp5.y), vec3(matp4.x, matp4.y, matp4.z), matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
}
#endif // _Clusters

View File

@ -214,6 +214,11 @@
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats"
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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));