Full BSDF
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbuffer0; // Roughness
|
||||
uniform sampler2D gbufferD; // Depth
|
||||
|
||||
uniform vec2 dirInv;
|
||||
|
||||
@ -14,19 +15,46 @@ out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
float roughness = textureLod(gbuffer0, texCoord, 0.0).b;
|
||||
// if (roughness == 0.0) { // Always blur for now, non blured output can produce noise
|
||||
// fragColor.rgb = textureLod(tex, texCoord).rgb;
|
||||
// return;
|
||||
// }
|
||||
if (roughness >= 0.8) { // No reflections
|
||||
if (roughness >= 0.8) {
|
||||
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
|
||||
return;
|
||||
}
|
||||
|
||||
fragColor.rgb = textureLod(tex, texCoord + dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb /= vec3(5.0);
|
||||
if (roughness < 0.01) {
|
||||
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
|
||||
return;
|
||||
}
|
||||
|
||||
float blurRadius = 1.0 + roughness * 4.0;
|
||||
vec3 center = textureLod(tex, texCoord, 0.0).rgb;
|
||||
|
||||
float centerDepth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||
|
||||
float w0 = 1.0 / (1.0 + roughness * 2.0);
|
||||
float w1 = 1.0 / (1.0 + roughness);
|
||||
float w2 = 1.0 / (1.0 + roughness * 0.5);
|
||||
float totalW = w0;
|
||||
|
||||
fragColor.rgb = center * w0;
|
||||
|
||||
vec2 offsets[4];
|
||||
offsets[0] = dirInv * blurRadius * 2.5;
|
||||
offsets[1] = dirInv * blurRadius * 1.5;
|
||||
offsets[2] = -dirInv * blurRadius * 1.5;
|
||||
offsets[3] = -dirInv * blurRadius * 2.5;
|
||||
float weights[4];
|
||||
weights[0] = w2;
|
||||
weights[1] = w1;
|
||||
weights[2] = w1;
|
||||
weights[3] = w2;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec2 sampleTC = texCoord + offsets[i];
|
||||
float sampleDepth = textureLod(gbufferD, sampleTC, 0.0).r;
|
||||
float depthWeight = exp(-abs(centerDepth - sampleDepth) * 100.0);
|
||||
float w = weights[i] * depthWeight;
|
||||
fragColor.rgb += textureLod(tex, sampleTC, 0.0).rgb * w;
|
||||
totalW += w;
|
||||
}
|
||||
|
||||
fragColor.rgb /= vec3(totalW);
|
||||
}
|
||||
|
||||
@ -17,12 +17,12 @@ in vec3 wnormal;
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_1 | || base color (RGB) | occlusion/specular |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_2 | _gbuffer2 || velocity (XY) | ignore radiance | unused |
|
||||
| GBUF_IDX_2 | _gbuffer2 || velocity (XY) | ignore radiance | tangent angle |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_EMISSION | _EmissionShaded || emission color (RGB) | unused |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_3 | _Anisotropy || world tangent (XYZ) | unused |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_REFRACTION | _SSRefraction || packed IOR | transmittance | surfaceDepth | unused |
|
||||
| | _VoxelRefract || (0-1 range) | | | |
|
||||
|
||||
The indices as well as the GBUF_SIZE define are defined in "compiled.inc".
|
||||
*/
|
||||
@ -54,10 +54,10 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _SSRefraction
|
||||
fragColor[GBUF_IDX_REFRACTION] = vec4(ior, opacity, 0.0, 0.0);
|
||||
fragColor[GBUF_IDX_REFRACTION] = vec4(packIOR(ior), opacity, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _Anisotropy
|
||||
fragColor[GBUF_IDX_3] = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
fragColor[GBUF_IDX_2].a = -1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -7,7 +7,11 @@ out vec4 fragColor[GBUF_SIZE];
|
||||
|
||||
void main() {
|
||||
fragColor[GBUF_IDX_0] = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
#if GBUF_SIZE > 1
|
||||
fragColor[GBUF_IDX_1] = vec4(color, 1.0);
|
||||
#else
|
||||
fragColor[GBUF_IDX_0] = vec4(color, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _EmissionShaded
|
||||
fragColor[GBUF_IDX_EMISSION] = vec4(0.0);
|
||||
|
||||
@ -8,9 +8,6 @@
|
||||
#ifdef _Irr
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
#include "std/sss.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
@ -23,12 +20,12 @@ uniform sampler2D gbuffer1;
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
uniform sampler2D gbuffer3;
|
||||
#endif
|
||||
#ifdef _EmissionShaded
|
||||
uniform sampler2D gbufferEmission;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
uniform sampler2D gbufferCoatNormal;
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelGI
|
||||
uniform sampler2D voxels_diffuse;
|
||||
@ -95,7 +92,7 @@ uniform mat4 invVP;
|
||||
#ifdef _SinglePoint
|
||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||
//!uniform sampler2D shadowMapSpotTransparent[1];
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
//!uniform mat4 LWVPSpotArray[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
//!uniform sampler2DShadow shadowMapSpot[4];
|
||||
@ -140,7 +137,7 @@ uniform vec2 cameraPlane;
|
||||
#ifdef _ShadowMapTransparent
|
||||
//!uniform sampler2D shadowMapSpotTransparent[1];
|
||||
#endif
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
//!uniform mat4 LWVPSpotArray[1];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[1];
|
||||
#ifdef _ShadowMapTransparent
|
||||
@ -203,6 +200,7 @@ uniform vec3 sunCol;
|
||||
uniform sampler2D shadowMapAtlasSunTransparent;
|
||||
#endif
|
||||
#endif
|
||||
//!uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
|
||||
#else
|
||||
uniform sampler2DShadow shadowMap;
|
||||
#ifdef _ShadowMapTransparent
|
||||
@ -239,6 +237,9 @@ uniform float time;
|
||||
#endif
|
||||
|
||||
#include "std/light.glsl"
|
||||
#ifdef _SSS
|
||||
#include "std/sss.glsl"
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
@ -262,8 +263,26 @@ void main() {
|
||||
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);
|
||||
vec4 matp0 = vec4(0.0), matp1 = vec4(0.0), matp2 = vec4(0.0), matp3 = vec4(0.0);
|
||||
vec4 matp4 = vec4(0.0), matp5 = vec4(0.0), matp6 = vec4(0.0), matp7 = vec4(0.0);
|
||||
// TODO: coatIOR=1.5, ior=1.45, thinWall=1.0 move to python make files
|
||||
matp1.z = 1.5;
|
||||
matp3.x = 1.45;
|
||||
matp3.y = 1.0;
|
||||
if (matid >= 3u) {
|
||||
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
|
||||
}
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatTintCol = vec3(matp1.w, matp2.x, matp2.y);
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
vec3 sheenTintCol = vec3(matp5.z, matp5.w, matp6.x);
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
vec3 sssColorVal = vec3(matp4.w, matp5.x, matp5.y);
|
||||
vec3 sssRadiusBase = vec3(matp4.x, matp4.y, matp4.z);
|
||||
float sssRadiusScalar = max(max(matp4.x, matp4.y), matp4.z) * matp7.x;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec2 occspec = unpackFloat2(g1.a);
|
||||
@ -271,7 +290,10 @@ void main() {
|
||||
vec3 basecolor = min(g1.rgb, vec3(2.0));
|
||||
vec3 albedo = surfaceAlbedo(basecolor, metallic);
|
||||
vec3 f0 = surfaceF0(basecolor, metallic);
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
f0 = mix(f0, basecolor, vec3(matp6.y, matp6.z, matp6.w));
|
||||
#endif
|
||||
|
||||
#ifdef _VRStereo
|
||||
bool isLeftEye = texCoord.x < 0.5;
|
||||
vec3 eyePos = isLeftEye ? eyeLeft : eyeRight;
|
||||
@ -290,13 +312,24 @@ void main() {
|
||||
#endif
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
#ifdef _ClearCoat
|
||||
vec4 gCoat = textureLod(gbufferCoatNormal, texCoord, 0.0);
|
||||
vec3 nCoat;
|
||||
nCoat.z = 1.0 - abs(gCoat.x) - abs(gCoat.y);
|
||||
nCoat.xy = nCoat.z >= 0.0 ? gCoat.xy : octahedronWrap(gCoat.xy);
|
||||
nCoat = normalize(nCoat);
|
||||
#endif
|
||||
|
||||
#ifdef _gbuffer2
|
||||
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);
|
||||
#ifdef _gbuffer2
|
||||
vec3 wTangent = decodeTangent(g2.a, n);
|
||||
#else
|
||||
vec3 wTangent = vec3(0.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -311,6 +344,44 @@ void main() {
|
||||
vec3 F = f0;
|
||||
#endif
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
float iblSheenWeight = 1.0;
|
||||
float iblCoatWeight = 1.0;
|
||||
float iblLayerWeight = 1.0;
|
||||
vec3 coatTintAbsorb = vec3(1.0);
|
||||
|
||||
#ifdef _Sheen
|
||||
float sheenAlb = sheenIBLAlbedo(matp0.z, matp0.w, dotNV);
|
||||
iblSheenWeight = max(1.0 - sheenAlb *
|
||||
max(max(sheenTintCol.r, sheenTintCol.g), sheenTintCol.b), 0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
float dotNVCoat = max(dot(nCoat, v), 0.0);
|
||||
float coatF = coatIBLFresnel(matp1.x, matp1.z, dotNVCoat);
|
||||
iblCoatWeight = max(1.0 - coatF, 0.0);
|
||||
coatTintAbsorb = mix(vec3(1.0), clamp(coatTintCol, 0.0, 1.0),
|
||||
clamp(1.0 / max(dotNVCoat, 0.3) * 0.2, 0.0, 1.0));
|
||||
#endif
|
||||
|
||||
iblLayerWeight = iblSheenWeight * iblCoatWeight;
|
||||
|
||||
brdf_sheenWeight = iblSheenWeight;
|
||||
brdf_coatWeight = iblCoatWeight;
|
||||
brdf_coatTintAbsorb = coatTintAbsorb;
|
||||
#ifdef _Sheen
|
||||
brdf_sheenAlbedo = sheenAlb;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
brdf_coatF0 = (matp1.z - 1.0) / (matp1.z + 1.0);
|
||||
brdf_coatF0 = brdf_coatF0 * brdf_coatF0;
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
brdf_transmissionF0 = (matp3.x - 1.0) / (matp3.x + 1.0);
|
||||
brdf_transmissionF0 = brdf_transmissionF0 * brdf_transmissionF0;
|
||||
#endif
|
||||
#endif // _ExtBRDF
|
||||
|
||||
#ifndef _VoxelAOvar
|
||||
#ifndef _VoxelGI
|
||||
// Envmap
|
||||
@ -318,9 +389,7 @@ void main() {
|
||||
vec3 envl = shIrradiance(n, shirr);
|
||||
|
||||
#ifdef _gbuffer2
|
||||
if (g2.b < 0.5) {
|
||||
envl = envl;
|
||||
} else {
|
||||
if (g2.b >= 0.5) {
|
||||
envl = vec3(0.0);
|
||||
}
|
||||
#endif
|
||||
@ -333,16 +402,21 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
#ifdef _Anisotropy
|
||||
vec3 reflectionWorld = anisotropicIBLDirection(n, v, wTangent,
|
||||
matp0.x, roughness);
|
||||
#else
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
#endif
|
||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
prefilteredColor = min(prefilteredColor, vec3(20.0));
|
||||
#endif
|
||||
|
||||
#ifdef _EnvLDR
|
||||
envl.rgb = pow(envl.rgb, vec3(2.2));
|
||||
envl.rgb = srgbToLinear(envl.rgb);
|
||||
#ifdef _Rad
|
||||
prefilteredColor = pow(prefilteredColor, vec3(2.2));
|
||||
prefilteredColor = srgbToLinear(prefilteredColor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -360,6 +434,68 @@ void main() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
envl.rgb *= iblLayerWeight;
|
||||
|
||||
|
||||
#ifdef _Transmission
|
||||
float transF = transmissionIBLFresnel(matp3.x, dotNV);
|
||||
float transmittance = 1.0 - transF;
|
||||
#ifdef _Rad
|
||||
if (matp2.z > 0.0 && transmittance > 0.0) {
|
||||
vec3 refrDir;
|
||||
if (matp3.y > 0.5) {
|
||||
refrDir = reflect(-v, n);
|
||||
} else {
|
||||
refrDir = transmissionIBLDirection(n, v, matp3.x);
|
||||
}
|
||||
float transLod = getMipFromRoughness(matp2.w, envmapNumMipmaps);
|
||||
vec3 transColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(refrDir), transLod).rgb;
|
||||
transColor = min(transColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
transColor = srgbToLinear(transColor);
|
||||
#endif
|
||||
envl.rgb += albedo * matp2.z * transmittance * transColor * dotNV
|
||||
* iblLayerWeight;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
envl.rgb *= coatTintAbsorb;
|
||||
#ifdef _Rad
|
||||
if (coatF > 0.0) {
|
||||
float coatLod = getMipFromRoughness(matp1.y, envmapNumMipmaps);
|
||||
vec3 coatRefl = reflect(-v, nCoat);
|
||||
vec3 coatColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(coatRefl), coatLod).rgb;
|
||||
coatColor = min(coatColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
coatColor = srgbToLinear(coatColor);
|
||||
#endif
|
||||
envl.rgb += coatColor * coatF * iblSheenWeight;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Sheen
|
||||
#ifdef _Rad
|
||||
if (sheenAlb > 0.0) {
|
||||
float sheenLod = getMipFromRoughness(matp0.w, envmapNumMipmaps);
|
||||
vec3 sheenRefl = reflect(-v, n);
|
||||
vec3 sheenColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(sheenRefl), sheenLod).rgb;
|
||||
sheenColor = min(sheenColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
sheenColor = srgbToLinear(sheenColor);
|
||||
#endif
|
||||
envl.rgb += sheenColor * sheenTintCol * sheenAlb;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // _ExtBRDF
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
|
||||
fragColor.rgb = envl;
|
||||
@ -368,11 +504,30 @@ void main() {
|
||||
|
||||
#ifdef _VoxelGI
|
||||
fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff;
|
||||
if(roughness < 1.0 && occspec.y > 0.0)
|
||||
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
|
||||
if(roughness < 1.0) {
|
||||
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl * occspec.y;
|
||||
}
|
||||
#ifdef _Rad
|
||||
vec3 iblReflection = reflect(-v, n);
|
||||
float iblLod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 iblPrefiltered = textureLod(senvmapRadiance, envMapEquirect(iblReflection), iblLod).rgb;
|
||||
iblPrefiltered = min(iblPrefiltered, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
iblPrefiltered = srgbToLinear(iblPrefiltered);
|
||||
#endif
|
||||
#ifdef _ExtBRDF
|
||||
iblPrefiltered *= iblLayerWeight;
|
||||
iblPrefiltered *= coatTintAbsorb;
|
||||
#endif
|
||||
fragColor.rgb += iblPrefiltered * F * envmapStrength * occspec.x;
|
||||
#else
|
||||
#ifdef _EnvCol
|
||||
fragColor.rgb += backgroundCol * F * envmapStrength * occspec.x;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#ifdef _VoxelAOvar
|
||||
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc;
|
||||
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -424,7 +579,7 @@ void main() {
|
||||
vec3 svisibility = vec3(1.0);
|
||||
#ifdef _Anisotropy
|
||||
vec3 sdirect;
|
||||
if (abs(matp0.x) > 0.001) {
|
||||
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
|
||||
vec3 sbitangent = normalize(cross(n, wTangent));
|
||||
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
|
||||
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
|
||||
@ -438,36 +593,26 @@ void main() {
|
||||
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;
|
||||
#ifdef _ExtBRDF
|
||||
float sunLayerWeight;
|
||||
sdirect = applyExtBRDFLayers(sdirect, albedo, f0, roughness,
|
||||
sdotNL, dotNV, sdotNH, sdotVH, n, sunDir, v, sh
|
||||
#ifdef _ClearCoat
|
||||
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, matp0.z, matp0.w, sheenTintCol
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, matp2.z, matp2.w, matp3.x, matp3.y
|
||||
#endif
|
||||
, sunLayerWeight);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSunArray[0];
|
||||
#endif
|
||||
#ifdef _CSM
|
||||
svisibility = shadowTestCascade(
|
||||
#ifdef _ShadowMapAtlas
|
||||
@ -552,23 +697,17 @@ void main() {
|
||||
|
||||
fragColor.rgb += sdirect * sunCol * svisibility;
|
||||
|
||||
// #ifdef _Hair // Aniso
|
||||
// if (matid == 2) {
|
||||
// const float shinyParallel = roughness;
|
||||
// const float shinyPerpendicular = 0.1;
|
||||
// const vec3 v = vec3(0.99146, 0.11664, 0.05832);
|
||||
// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v);
|
||||
// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
#ifdef _SSS
|
||||
if (matid == 2) {
|
||||
#ifdef _ExtBRDF
|
||||
if (matid >= 3u && matp3.z > 0.0) {
|
||||
#ifdef _CSM
|
||||
int casi, casindex;
|
||||
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
|
||||
#endif
|
||||
fragColor.rgb += fragColor.rgb * SSSSTransmittance(
|
||||
vec3 sssColor = sssColorVal;
|
||||
float sssRadius = sssRadiusScalar;
|
||||
float sssStrength = matp3.z;
|
||||
vec3 sssResult = SSSSTransmittance(
|
||||
LWVP, p, n, sunDir, lightPlane.y,
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
@ -579,12 +718,26 @@ void main() {
|
||||
#else
|
||||
shadowMap
|
||||
#endif
|
||||
);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||
, sssColor, sssRadius
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifdef _CSM
|
||||
, tileBoundsSunArray[casi]
|
||||
#else
|
||||
, tileBoundsSunArray[0]
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
fragColor.rgb += sunCol * sssStrength * sssResult;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // _Sun
|
||||
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SinglePoint
|
||||
|
||||
#ifdef _VRStereo
|
||||
@ -614,16 +767,16 @@ void main() {
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
|
||||
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
|
||||
, matp0.z, matp0.w, sheenTintCol
|
||||
#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
|
||||
#ifdef _SSS
|
||||
, matp3.z, sssColorVal, sssRadiusBase * matp7.x, matp3.w
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, matp2.z, matp2.w, matp3.x, matp3.y
|
||||
@ -633,7 +786,33 @@ void main() {
|
||||
#ifdef _Spot
|
||||
#ifdef _SSS
|
||||
#ifdef _ShadowMap
|
||||
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(lightPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||
#ifdef _ExtBRDF
|
||||
if (matid >= 3u && matp3.z > 0.0) {
|
||||
vec3 sssColorSpot = sssColorVal;
|
||||
float sssRadiusSpot = sssRadiusScalar;
|
||||
float sssStrengthSpot = matp3.z;
|
||||
fragColor.rgb += pointCol * sssStrengthSpot * SSSSTransmittance(LWVPSpotArray[0], p, n, normalize(lightPos - p), lightPlane.y, shadowMapSpot[0], sssColorSpot, sssRadiusSpot
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4(0.0, 0.0, 1.0, 1.0)
|
||||
#endif
|
||||
);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _Spot
|
||||
#ifdef _SSS
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ExtBRDF
|
||||
if (matid >= 3u && matp3.z > 0.0) {
|
||||
vec3 sssColorPoint = sssColorVal;
|
||||
float sssRadiusPoint = sssRadiusScalar;
|
||||
float sssStrengthPoint = matp3.z;
|
||||
fragColor.rgb += pointCol * sssStrengthPoint * SSSSTransmittanceCube(shadowMapPoint[0], lightPos, p, n, normalize(lightPos - p), lightPlane.y, lightProj, sssColorPoint, sssRadiusPoint);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@ -692,21 +871,95 @@ void main() {
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
|
||||
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
|
||||
, matp0.z, matp0.w, sheenTintCol
|
||||
#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
|
||||
#ifdef _SSS
|
||||
, matp3.z, sssColorVal, sssRadiusBase * matp7.x, matp3.w
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, matp2.z, matp2.w, matp3.x, matp3.y
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef _SSS
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ExtBRDF
|
||||
if (matid >= 3u && matp3.z > 0.0) {
|
||||
vec3 sssColorCL = sssColorVal;
|
||||
float sssRadiusCL = sssRadiusScalar;
|
||||
float sssStrengthCL = matp3.z;
|
||||
vec3 cLightPos = lightsArray[li * 3].xyz;
|
||||
vec3 cLightCol = lightsArray[li * 3 + 1].xyz;
|
||||
vec3 cLightDir = normalize(cLightPos - p);
|
||||
#ifdef _Spot
|
||||
bool isSpotLight = lightsArray[li * 3 + 2].y != 0.0;
|
||||
if (isSpotLight) {
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[li], p, n, cLightDir, lightPlane.y, shadowMapAtlasSpot, sssColorCL, sssRadiusCL, tileBoundsSpotArray[li]);
|
||||
#else
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[li], p, n, cLightDir, lightPlane.y, shadowMapAtlas, sssColorCL, sssRadiusCL, tileBoundsSpotArray[li]);
|
||||
#endif
|
||||
#else
|
||||
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[0], p, n, cLightDir, lightPlane.y, shadowMapSpot[0], sssColorCL, sssRadiusCL
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4(0.0, 0.0, 1.0, 1.0)
|
||||
#endif
|
||||
);
|
||||
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[1], p, n, cLightDir, lightPlane.y, shadowMapSpot[1], sssColorCL, sssRadiusCL
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4(0.0, 0.0, 1.0, 1.0)
|
||||
#endif
|
||||
);
|
||||
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[2], p, n, cLightDir, lightPlane.y, shadowMapSpot[2], sssColorCL, sssRadiusCL
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4(0.0, 0.0, 1.0, 1.0)
|
||||
#endif
|
||||
);
|
||||
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[3], p, n, cLightDir, lightPlane.y, shadowMapSpot[3], sssColorCL, sssRadiusCL
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4(0.0, 0.0, 1.0, 1.0)
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlasPoint, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
|
||||
#else
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlas, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
|
||||
#endif
|
||||
#else
|
||||
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[0], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[1], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[2], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[3], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlasPoint, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
|
||||
#else
|
||||
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlas, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
|
||||
#endif
|
||||
#else
|
||||
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[0], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[1], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[2], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[3], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif // _Clusters
|
||||
|
||||
|
||||
@ -138,6 +138,16 @@
|
||||
"link": "_cascadeData",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "tileBoundsSunArray",
|
||||
"link": "_tileBoundsSunArray",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "tileBoundsSpotArray",
|
||||
"link": "_tileBoundsSpotArray",
|
||||
"ifdef": ["_Clusters", "_Spot", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "lightPlane",
|
||||
"link": "_lightPlane",
|
||||
@ -281,9 +291,11 @@
|
||||
{
|
||||
"name": "materialParams",
|
||||
"link": "_materialParams",
|
||||
"type": "floats"
|
||||
"type": "floats",
|
||||
"ifdef": ["_ExtBRDF"]
|
||||
}
|
||||
],
|
||||
"texture_units": [],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "deferred_light.frag.glsl",
|
||||
"color_attachments": ["RGBA64"]
|
||||
|
||||
@ -14,8 +14,11 @@
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
#ifdef _Anisotropy
|
||||
uniform sampler2D gbuffer3;
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
uniform sampler2D gbufferCoatNormal;
|
||||
#endif
|
||||
|
||||
uniform float envmapStrength;
|
||||
@ -53,7 +56,7 @@ uniform vec2 cameraPlane;
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
//!uniform mat4 LWVPSpotArray[1];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[1];
|
||||
//!uniform vec2 lightProj;
|
||||
@ -95,6 +98,7 @@ uniform vec3 sunCol;
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSun;
|
||||
#endif
|
||||
//!uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
|
||||
#else
|
||||
uniform sampler2DShadow shadowMap;
|
||||
#endif
|
||||
@ -140,23 +144,55 @@ void main() {
|
||||
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);
|
||||
vec4 matp0 = vec4(0.0), matp1 = vec4(0.0), matp2 = vec4(0.0), matp3 = vec4(0.0);
|
||||
vec4 matp4 = vec4(0.0), matp5 = vec4(0.0), matp6 = vec4(0.0), matp7 = vec4(0.0);
|
||||
// TODO: coatIOR=1.5, ior=1.45, thinWall=1.0 move to python make files
|
||||
matp1.z = 1.5;
|
||||
matp3.x = 1.45;
|
||||
matp3.y = 1.0;
|
||||
if (matid >= 3u) {
|
||||
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
|
||||
}
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatTintCol = vec3(matp1.w, matp2.x, matp2.y);
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
vec3 sheenTintCol = vec3(matp5.z, matp5.w, matp6.x);
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
vec3 sssColorVal = vec3(matp4.w, matp5.x, matp5.y);
|
||||
vec3 sssRadiusScaled = vec3(matp4.x, matp4.y, matp4.z) * matp7.x;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
|
||||
vec2 occspec = unpackFloat2(g1.a);
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
||||
#ifdef _ExtBRDF
|
||||
f0 = mix(f0, min(g1.rgb, vec3(2.0)), vec3(matp6.y, matp6.z, matp6.w));
|
||||
#endif
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||
vec3 v = normalize(eye - p);
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
#ifdef _ClearCoat
|
||||
vec4 gCoat = textureLod(gbufferCoatNormal, texCoord, 0.0);
|
||||
vec3 nCoat;
|
||||
nCoat.z = 1.0 - abs(gCoat.x) - abs(gCoat.y);
|
||||
nCoat.xy = nCoat.z >= 0.0 ? gCoat.xy : octahedronWrap(gCoat.xy);
|
||||
nCoat = normalize(nCoat);
|
||||
#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);
|
||||
#ifdef _gbuffer2
|
||||
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
|
||||
vec3 wTangent = decodeTangent(g2.a, n);
|
||||
#else
|
||||
vec3 wTangent = vec3(0.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Brdf
|
||||
@ -174,15 +210,20 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
#ifdef _Anisotropy
|
||||
vec3 reflectionWorld = anisotropicIBLDirection(n, v, wTangent,
|
||||
matp0.x, roughness);
|
||||
#else
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
#endif
|
||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
#endif
|
||||
|
||||
#ifdef _EnvLDR
|
||||
envl.rgb = pow(envl.rgb, vec3(2.2));
|
||||
envl.rgb = srgbToLinear(envl.rgb);
|
||||
#ifdef _Rad
|
||||
prefilteredColor = pow(prefilteredColor, vec3(2.2));
|
||||
prefilteredColor = srgbToLinear(prefilteredColor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -196,6 +237,98 @@ void main() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
float iblSheenWeight = 1.0;
|
||||
float iblCoatWeight = 1.0;
|
||||
vec3 coatTintAbsorb = vec3(1.0);
|
||||
|
||||
#ifdef _Sheen
|
||||
float sheenAlb = sheenIBLAlbedo(matp0.z, matp0.w, dotNV);
|
||||
iblSheenWeight = max(1.0 - sheenAlb *
|
||||
max(max(sheenTintCol.r, sheenTintCol.g), sheenTintCol.b), 0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
float dotNVCoat = max(dot(nCoat, v), 0.0);
|
||||
float coatF = coatIBLFresnel(matp1.x, matp1.z, dotNVCoat);
|
||||
iblCoatWeight = max(1.0 - coatF, 0.0);
|
||||
if (matp1.x > 0.0) {
|
||||
coatTintAbsorb = mix(vec3(1.0), clamp(coatTintCol, 0.0, 1.0),
|
||||
clamp(1.0 / max(dotNVCoat, 0.3) * 0.2, 0.0, 1.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
float iblLayerWeight = iblSheenWeight * iblCoatWeight;
|
||||
envl.rgb *= iblLayerWeight;
|
||||
|
||||
brdf_sheenWeight = iblSheenWeight;
|
||||
brdf_coatWeight = iblCoatWeight;
|
||||
brdf_coatTintAbsorb = coatTintAbsorb;
|
||||
#ifdef _Sheen
|
||||
brdf_sheenAlbedo = sheenAlb;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
brdf_coatF0 = (matp1.z - 1.0) / (matp1.z + 1.0);
|
||||
brdf_coatF0 = brdf_coatF0 * brdf_coatF0;
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
brdf_transmissionF0 = (matp3.x - 1.0) / (matp3.x + 1.0);
|
||||
brdf_transmissionF0 = brdf_transmissionF0 * brdf_transmissionF0;
|
||||
#endif
|
||||
|
||||
#ifdef _Transmission
|
||||
float transF = transmissionIBLFresnel(matp3.x, dotNV);
|
||||
float transmittance = 1.0 - transF;
|
||||
#ifdef _Rad
|
||||
if (matp2.z > 0.0 && transmittance > 0.0) {
|
||||
vec3 refrDir = transmissionIBLDirection(n, v, matp3.x);
|
||||
float transLod = getMipFromRoughness(matp2.w, envmapNumMipmaps);
|
||||
vec3 transColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(refrDir), transLod).rgb;
|
||||
transColor = min(transColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
transColor = srgbToLinear(transColor);
|
||||
#endif
|
||||
envl.rgb += albedo * matp2.z * transmittance * transColor * dotNV
|
||||
* iblLayerWeight;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
envl.rgb *= coatTintAbsorb;
|
||||
#ifdef _Rad
|
||||
if (coatF > 0.0) {
|
||||
float coatLod = getMipFromRoughness(matp1.y, envmapNumMipmaps);
|
||||
vec3 coatRefl = reflect(-v, nCoat);
|
||||
vec3 coatColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(coatRefl), coatLod).rgb;
|
||||
coatColor = min(coatColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
coatColor = srgbToLinear(coatColor);
|
||||
#endif
|
||||
envl.rgb += coatColor * coatF * iblSheenWeight;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Sheen
|
||||
#ifdef _Rad
|
||||
if (sheenAlb > 0.0) {
|
||||
float sheenLod = getMipFromRoughness(matp0.w, envmapNumMipmaps);
|
||||
vec3 sheenRefl = reflect(-v, n);
|
||||
vec3 sheenColor = textureLod(senvmapRadiance,
|
||||
envMapEquirect(sheenRefl), sheenLod).rgb;
|
||||
sheenColor = min(sheenColor, vec3(20.0));
|
||||
#ifdef _EnvLDR
|
||||
sheenColor = srgbToLinear(sheenColor);
|
||||
#endif
|
||||
envl.rgb += sheenColor * sheenTintCol * sheenAlb;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // _ExtBRDF
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
fragColor.rgb = envl;
|
||||
|
||||
@ -207,7 +340,7 @@ void main() {
|
||||
float svisibility = 1.0;
|
||||
#ifdef _Anisotropy
|
||||
vec3 sdirect;
|
||||
if (abs(matp0.x) > 0.001) {
|
||||
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
|
||||
vec3 sbitangent = normalize(cross(n, wTangent));
|
||||
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
|
||||
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
|
||||
@ -221,29 +354,24 @@ void main() {
|
||||
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
|
||||
#endif
|
||||
|
||||
float sunSheenWeight = 1.0;
|
||||
float sunCoatWeight = 1.0;
|
||||
float sunSheenWeight = brdf_sheenWeight;
|
||||
float sunCoatWeight = brdf_coatWeight;
|
||||
|
||||
#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);
|
||||
vec3 sunSheen = sheenBRDF(matp0.z, matp0.w, sheenTintCol, sdotNL, sdotNH, dotNV);
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
vec3 sunCoat = clearcoatBRDF(matp1.x, matp1.y, matp1.z, sdotNL, sdotNH, dotNV, sdotVH);
|
||||
sunCoatWeight = coatAttenuation(matp1.x, matp1.z, dotNV);
|
||||
vec3 sunCoat = clearcoatBRDF(matp1.x, matp1.y, matp1.z, nCoat, sunDir, v, sh);
|
||||
#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 *= brdf_coatTintAbsorb;
|
||||
sdirect += sunCoat * sunSheenWeight;
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
@ -251,6 +379,9 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSunArray[0];
|
||||
#endif
|
||||
#ifdef _CSM
|
||||
svisibility = shadowTestCascade(
|
||||
#ifdef _ShadowMapAtlas
|
||||
@ -294,16 +425,16 @@ void main() {
|
||||
, 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)
|
||||
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
|
||||
, matp0.z, matp0.w, sheenTintCol
|
||||
#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
|
||||
#ifdef _SSS
|
||||
, matp3.z, sssColorVal, sssRadiusScaled, matp3.w
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, matp2.z, matp2.w, matp3.x, matp3.y
|
||||
@ -351,16 +482,16 @@ void main() {
|
||||
, lightsArraySpot[li * 2 + 1].xyz // right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, matp1.x, matp1.y, matp1.z, vec3(matp1.w, matp2.x, matp2.y)
|
||||
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, matp0.z, matp0.w, vec3(matp5.z, matp5.w, matp6.x)
|
||||
, matp0.z, matp0.w, sheenTintCol
|
||||
#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
|
||||
#ifdef _SSS
|
||||
, matp3.z, sssColorVal, sssRadiusScaled, matp3.w
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, matp2.z, matp2.w, matp3.x, matp3.y
|
||||
@ -368,4 +499,11 @@ void main() {
|
||||
);
|
||||
}
|
||||
#endif // _Clusters
|
||||
|
||||
fragColor.rgb = clamp(fragColor.rgb, vec3(0.0), vec3(65504.0));
|
||||
if (any(isnan(fragColor.rgb)) || any(isinf(fragColor.rgb))) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
}
|
||||
|
||||
fragColor.a = 1.0; // Mark as opaque
|
||||
}
|
||||
|
||||
@ -97,6 +97,16 @@
|
||||
"link": "_cascadeData",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "tileBoundsSunArray",
|
||||
"link": "_tileBoundsSunArray",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "tileBoundsSpotArray",
|
||||
"link": "_tileBoundsSpotArray",
|
||||
"ifdef": ["_Clusters", "_Spot", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "eyeLookRight",
|
||||
"link": "_eyeLookRight",
|
||||
@ -218,7 +228,8 @@
|
||||
{
|
||||
"name": "materialParams",
|
||||
"link": "_materialParams",
|
||||
"type": "floats"
|
||||
"type": "floats",
|
||||
"ifdef": ["_ExtBRDF"]
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
|
||||
@ -11,6 +11,7 @@ uniform sampler2D gbuffer1; // basecol, spec
|
||||
uniform mat4 P;
|
||||
uniform mat3 V3;
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec2 screenSize;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp9;
|
||||
@ -24,8 +25,8 @@ out vec4 fragColor;
|
||||
vec3 hitCoord;
|
||||
float depth;
|
||||
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||
const int numBinarySearchSteps = 8;
|
||||
const int maxSteps = 50;
|
||||
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
@ -38,44 +39,58 @@ vec2 getProjectedCoord(const vec3 hit) {
|
||||
}
|
||||
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec2 tc = getProjectedCoord(hit);
|
||||
if (tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0)
|
||||
return -1.0;
|
||||
depth = textureLod(gbufferD, tc, 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
}
|
||||
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
vec4 binarySearch(vec3 dir, float stepSize) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
stepSize *= 0.5;
|
||||
hitCoord -= dir * stepSize;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
if (ddepth < 0.0) hitCoord += dir * stepSize;
|
||||
}
|
||||
// Ugly discard of hits too far away
|
||||
#ifdef _CPostprocess
|
||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
||||
float maxDist = PPComp9.z;
|
||||
#else
|
||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
||||
float maxDist = ssrSearchDist;
|
||||
#endif
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
if (abs(ddepth) > maxDist * 0.005) return vec4(0.0);
|
||||
vec2 hitTC = getProjectedCoord(hitCoord);
|
||||
if (hitTC.x < 0.0 || hitTC.x > 1.0 || hitTC.y < 0.0 || hitTC.y > 1.0)
|
||||
return vec4(0.0);
|
||||
return vec4(hitTC, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
float baseStep = PPComp9.x;
|
||||
float maxDist = PPComp9.z;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
float baseStep = ssrRayStep;
|
||||
float maxDist = ssrSearchDist;
|
||||
#endif
|
||||
float stepSize = baseStep * max(1.0, -viewRay.z * 0.1);
|
||||
vec3 startPos = hitCoord;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
hitCoord += dir * stepSize;
|
||||
float dist = length(hitCoord - startPos);
|
||||
if (dist > maxDist) break;
|
||||
float ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0) return binarySearch(dir, stepSize);
|
||||
stepSize *= 1.03;
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
float roughness = g0.b;
|
||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
@ -92,30 +107,54 @@ void main() {
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 reflected = reflect(viewPos, viewNormal);
|
||||
float NdotV = clamp(dot(viewNormal, -normalize(viewPos)), 0.0, 1.0);
|
||||
vec3 reflected = reflect(normalize(viewPos), viewNormal);
|
||||
hitCoord = viewPos;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
|
||||
#else
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
|
||||
#endif
|
||||
vec3 dir = reflected;
|
||||
|
||||
// * max(ssrMinRayStep, -viewPos.z)
|
||||
vec4 coords = rayCast(dir);
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
if (coords.w <= 0.0) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = smoothstep(0.5, 0.15, deltaCoords.x)
|
||||
* smoothstep(0.5, 0.15, deltaCoords.y);
|
||||
screenEdgeFactor = max(screenEdgeFactor, 0.15);
|
||||
|
||||
float hitDepth = textureLod(gbufferD, coords.xy, 0.0).r * 2.0 - 1.0;
|
||||
vec3 hitViewPos = getPosView(viewRay, hitDepth, cameraProj);
|
||||
vec3 hitDir = normalize(hitViewPos - viewPos);
|
||||
float hitNdotV = clamp(dot(viewNormal, -hitDir), 0.0, 1.0);
|
||||
float hitBackFace = smoothstep(-0.15, 0.3, hitNdotV);
|
||||
|
||||
float reflectivity = 1.0 - roughness;
|
||||
#ifdef _CPostprocess
|
||||
float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w;
|
||||
float falloffExp = PPComp10.x;
|
||||
float maxDist = PPComp9.z;
|
||||
#else
|
||||
float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0) * coords.w;
|
||||
float falloffExp = ssrFalloffExp;
|
||||
float maxDist = ssrSearchDist;
|
||||
#endif
|
||||
|
||||
float distAttenuation = 1.0 - clamp(length(viewPos - hitCoord) / maxDist, 0.0, 1.0);
|
||||
distAttenuation = pow(distAttenuation, 1.5);
|
||||
|
||||
float fresnel = pow(1.0 - NdotV, 5.0);
|
||||
fresnel = mix(0.04, 1.0, fresnel);
|
||||
|
||||
float intensity = pow(reflectivity, falloffExp) * screenEdgeFactor
|
||||
* smoothstep(0.0, 0.1, -reflected.z)
|
||||
* distAttenuation
|
||||
* hitBackFace
|
||||
* coords.w;
|
||||
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
|
||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
|
||||
reflCol = clamp(reflCol, 0.0, 1.0);
|
||||
fragColor.rgb = reflCol * intensity * 0.5;
|
||||
fragColor.rgb = reflCol * intensity * mix(0.5, 1.0, fresnel);
|
||||
}
|
||||
|
||||
@ -22,6 +22,10 @@
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
},
|
||||
{
|
||||
"name": "PPComp9",
|
||||
"link": "_PPComp9",
|
||||
|
||||
@ -12,6 +12,7 @@ uniform sampler2D tex1;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbufferD1;
|
||||
uniform sampler2D gbuffer1;
|
||||
|
||||
uniform sampler2D gbuffer_refraction; // ior\opacity
|
||||
uniform mat4 P;
|
||||
@ -26,7 +27,7 @@ vec3 hitCoord;
|
||||
float depth;
|
||||
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ss_refractionRayStep) * ss_refractionSearchDist);
|
||||
const int maxSteps = 50;
|
||||
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
@ -39,45 +40,60 @@ vec2 getProjectedCoord(const vec3 hit) {
|
||||
}
|
||||
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD1, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec2 tc = getProjectedCoord(hit);
|
||||
if (tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0)
|
||||
return -1.0;
|
||||
depth = textureLod(gbufferD1, tc, 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
}
|
||||
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
vec4 binarySearch(vec3 dir, float stepSize) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
stepSize *= 0.5;
|
||||
hitCoord -= dir * stepSize;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
if (ddepth < 0.0) hitCoord += dir * stepSize;
|
||||
}
|
||||
if (abs(ddepth) > ss_refractionSearchDist) return vec4(0.0);
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
if (abs(ddepth) > ss_refractionSearchDist * 0.005) return vec4(0.0);
|
||||
vec2 hitTC = getProjectedCoord(hitCoord);
|
||||
if (hitTC.x < 0.0 || hitTC.x > 1.0 || hitTC.y < 0.0 || hitTC.y > 1.0)
|
||||
return vec4(0.0);
|
||||
return vec4(hitTC, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
float ddepth;
|
||||
dir *= ss_refractionRayStep;
|
||||
float stepSize = ss_refractionRayStep * max(1.0, -viewRay.z * 0.1);
|
||||
vec3 startPos = hitCoord;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0) return binarySearch(dir);
|
||||
hitCoord += dir * stepSize;
|
||||
float dist = length(hitCoord - startPos);
|
||||
if (dist > ss_refractionSearchDist) break;
|
||||
float ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0) return binarySearch(dir, stepSize);
|
||||
stepSize *= 1.03;
|
||||
}
|
||||
return vec4(texCoord, 0.0, 0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
|
||||
float ior = gr.x;
|
||||
float ior = unpackIOR(gr.x);
|
||||
float transmittance = gr.y;
|
||||
float surfaceDepth = gr.z;
|
||||
float d = surfaceDepth * 2.0 - 1.0;
|
||||
|
||||
vec4 sceneSample = textureLod(tex, texCoord, 0.0);
|
||||
if (surfaceDepth == 0.0 || transmittance == 0.0 || ior == 1.0) {
|
||||
if (surfaceDepth == 0.0 || surfaceDepth == 1.0) {
|
||||
fragColor = sceneSample;
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0);
|
||||
if (transmittance == 0.0 || ior == 1.0) {
|
||||
vec3 background = textureLod(tex1, texCoord, 0.0).rgb;
|
||||
fragColor.rgb = sceneSample.rgb + background * (1.0 - sceneSample.a);
|
||||
fragColor.rgb = g1.rgb + background * transmittance;
|
||||
fragColor.a = 1.0;
|
||||
return;
|
||||
}
|
||||
@ -96,18 +112,18 @@ void main() {
|
||||
vec3 refracted = refract(incident, viewNormal, 1.0 / ior);
|
||||
if (length(refracted) < 0.001) {
|
||||
vec3 background = textureLod(tex1, texCoord, 0.0).rgb;
|
||||
fragColor.rgb = sceneSample.rgb + background * (1.0 - sceneSample.a);
|
||||
fragColor.rgb = g1.rgb + background * transmittance;
|
||||
fragColor.a = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
hitCoord = viewPos;
|
||||
|
||||
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
|
||||
vec3 dir = normalize(refracted);
|
||||
vec4 coords = rayCast(dir);
|
||||
|
||||
vec2 screenEdge = smoothstep(0.0, 0.1, coords.xy) * smoothstep(0.0, 0.1, 1.0 - coords.xy);
|
||||
float screenEdgeFactor = screenEdge.x * screenEdge.y;
|
||||
vec2 screenEdge = smoothstep(0.0, 0.05, coords.xy) * smoothstep(0.0, 0.05, 1.0 - coords.xy);
|
||||
float screenEdgeFactor = max(screenEdge.x * screenEdge.y, 0.05);
|
||||
float refractivity = 1.0 - roughness;
|
||||
|
||||
float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * coords.w;
|
||||
@ -118,6 +134,6 @@ void main() {
|
||||
|
||||
vec3 behindColor = mix(straightBackground, refractedBackground, intensity);
|
||||
|
||||
fragColor.rgb = sceneSample.rgb + behindColor * (1.0 - sceneSample.a);
|
||||
fragColor.rgb = g1.rgb + behindColor * transmittance;
|
||||
fragColor.a = 1.0;
|
||||
}
|
||||
|
||||
@ -40,100 +40,148 @@
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform vec2 dir;
|
||||
uniform vec2 cameraProj;
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const vec3 SKIN_SSS_RADIUS = vec3(4.8, 2.4, 1.5);
|
||||
const float SSS_DISTANCE_SCALE = 0.001;
|
||||
// TODO: finish the SSS
|
||||
const float SSS_SCALE = 0.05;
|
||||
const float DEPTH_THRESHOLD = 0.05;
|
||||
|
||||
// Temp hash func -
|
||||
float hash13(vec3 p3) {
|
||||
p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973));
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
vec4 SSSSBlur() {
|
||||
const int SSSS_N_SAMPLES = 15;
|
||||
vec4 SSSSBlur(vec3 sssRadius, float sssWeight) {
|
||||
const int SSSS_N_SAMPLES = 11;
|
||||
vec4 kernel[SSSS_N_SAMPLES];
|
||||
|
||||
kernel[0] = vec4(0.233, 0.455, 0.649, 0.0); // Center sample
|
||||
kernel[1] = vec4(0.100, 0.336, 0.344, 0.37); // +0.37mm
|
||||
kernel[2] = vec4(0.118, 0.198, 0.0, 0.97); // +0.97mm
|
||||
kernel[3] = vec4(0.113, 0.007, 0.007, 1.93); // +1.93mm
|
||||
kernel[4] = vec4(0.358, 0.004, 0.0, 3.87); // +3.87mm
|
||||
kernel[5] = vec4(0.078, 0.0, 0.0, 6.53); // +6.53mm (red only)
|
||||
kernel[6] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
||||
kernel[7] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
||||
kernel[8] = vec4(0.100, 0.336, 0.344, -0.37); // -0.37mm
|
||||
kernel[9] = vec4(0.118, 0.198, 0.0, -0.97); // -0.97mm
|
||||
kernel[10] = vec4(0.113, 0.007, 0.007, -1.93); // -1.93mm
|
||||
kernel[11] = vec4(0.358, 0.004, 0.0, -3.87); // -3.87mm
|
||||
kernel[12] = vec4(0.078, 0.0, 0.0, -6.53); // -6.53mm (red only)
|
||||
kernel[13] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
||||
kernel[14] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
||||
|
||||
vec4 colorM = textureLod(tex, texCoord, 0.0);
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||
kernel[0] = vec4(0.233, 0.455, 0.649, 0.0); // Center sample
|
||||
kernel[1] = vec4(0.100, 0.336, 0.344, 0.37); // +0.37
|
||||
kernel[2] = vec4(0.118, 0.198, 0.0, 0.97); // +0.97
|
||||
kernel[3] = vec4(0.113, 0.007, 0.007, 1.93); // +1.93
|
||||
kernel[4] = vec4(0.358, 0.004, 0.0, 3.87); // +3.87
|
||||
kernel[5] = vec4(0.078, 0.0, 0.0, 6.53); // +6.53 (red only)
|
||||
kernel[6] = vec4(0.100, 0.336, 0.344, -0.37); // -0.37
|
||||
kernel[7] = vec4(0.118, 0.198, 0.0, -0.97); // -0.97
|
||||
kernel[8] = vec4(0.113, 0.007, 0.007, -1.93); // -1.93
|
||||
kernel[9] = vec4(0.358, 0.004, 0.0, -3.87); // -3.87
|
||||
kernel[10] = vec4(0.078, 0.0, 0.0, -6.53); // -6.53 (red only)
|
||||
|
||||
vec2 texSize = vec2(textureSize(tex, 0));
|
||||
ivec2 texelCoord = ivec2(texCoord * texSize);
|
||||
|
||||
vec4 colorM = texelFetch(tex, texelCoord, 0);
|
||||
vec3 albedo = texelFetch(gbuffer1, texelCoord, 0).rgb;
|
||||
|
||||
vec3 irradianceM = colorM.rgb / max(albedo, vec3(0.00001));
|
||||
|
||||
float depth = texelFetch(gbufferD, texelCoord, 0).r;
|
||||
float depthM = cameraProj.y / (depth - cameraProj.x);
|
||||
|
||||
float distanceScale = 1.0 / max(depthM, 0.1);
|
||||
|
||||
vec2 finalStep = sssWidth * distanceScale * dir * SSS_DISTANCE_SCALE;
|
||||
|
||||
float blurWidth = max(max(sssRadius.r, sssRadius.g), sssRadius.b);
|
||||
float projScale = dot(dir, vec2(projectionMatrix[0][0], projectionMatrix[1][1]));
|
||||
vec2 finalStep = blurWidth * (1.0 / depthM) * dir * projScale * SSS_SCALE;
|
||||
|
||||
vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001));
|
||||
float jitterOffset = (hash13(jitterSeed) * 2.0 - 1.0) * 0.15;
|
||||
|
||||
finalStep *= (1.0 + jitterOffset);
|
||||
vec3 colorBlurred = vec3(0.0);
|
||||
vec3 weightSum = vec3(0.0);
|
||||
colorBlurred += colorM.rgb * kernel[0].rgb;
|
||||
weightSum += kernel[0].rgb;
|
||||
|
||||
|
||||
vec3 colorBlurred = irradianceM * kernel[0].rgb;
|
||||
vec3 weightSum = kernel[0].rgb;
|
||||
|
||||
for (int i = 1; i < SSSS_N_SAMPLES; i++) {
|
||||
float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05;
|
||||
vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep;
|
||||
vec4 color = textureLod(tex, offset, 0.0);
|
||||
const float DEPTH_THRESHOLD = 0.05;
|
||||
float sampleDepth = textureLod(gbufferD, offset, 0.0).r;
|
||||
float sampleDepthM = cameraProj.y / (sampleDepth - cameraProj.x);
|
||||
|
||||
float depthDiff = abs(depthM - sampleDepthM);
|
||||
float depthWeight = exp(-depthDiff * 10.0);
|
||||
|
||||
if (depthDiff > DEPTH_THRESHOLD) {
|
||||
color.rgb = mix(colorM.rgb, color.rgb, depthWeight);
|
||||
|
||||
vec3 irradiance = irradianceM;
|
||||
float s = 0.0;
|
||||
if (all(greaterThanEqual(offset, vec2(0.0))) && all(lessThan(offset, vec2(1.0)))) {
|
||||
ivec2 sampleTexel = ivec2(offset * texSize);
|
||||
|
||||
float sampleDepth = texelFetch(gbufferD, sampleTexel, 0).r;
|
||||
float sampleDepthM = cameraProj.y / (sampleDepth - cameraProj.x);
|
||||
float depthDiff = abs(depthM - sampleDepthM);
|
||||
|
||||
if (depthDiff < 1.0) {
|
||||
vec4 sampleG0 = texelFetch(gbuffer0, sampleTexel, 0);
|
||||
float sampleMetallic;
|
||||
uint sampleMatid;
|
||||
unpackFloatInt16(sampleG0.a, sampleMetallic, sampleMatid);
|
||||
bool sampleIsSSS = false;
|
||||
#ifdef _ExtBRDF
|
||||
if (sampleMatid >= 3u && sampleMatid < uint(MAX_MATERIALS)) {
|
||||
if (materialParams[sampleMatid * 8u + 3u].z > 0.0) sampleIsSSS = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sampleIsSSS) {
|
||||
vec3 sampleColor = texelFetch(tex, sampleTexel, 0).rgb;
|
||||
vec3 sampleAlbedo = texelFetch(gbuffer1, sampleTexel, 0).rgb;
|
||||
irradiance = sampleColor / max(sampleAlbedo, vec3(0.00001));
|
||||
}
|
||||
|
||||
if (depthDiff <= DEPTH_THRESHOLD) {
|
||||
s = 1.0;
|
||||
} else {
|
||||
s = exp(-depthDiff * 10.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colorBlurred += color.rgb * kernel[i].rgb;
|
||||
|
||||
colorBlurred += kernel[i].rgb * mix(irradianceM, irradiance, s);
|
||||
weightSum += kernel[i].rgb;
|
||||
}
|
||||
vec3 normalizedColor = colorBlurred / max(weightSum, vec3(0.00001));
|
||||
|
||||
vec3 normalizedIrradiance = colorBlurred / max(weightSum, vec3(0.00001));
|
||||
float dither = hash13(vec3(texCoord * 1333.0, 0.0)) * 0.003 - 0.0015;
|
||||
normalizedColor = max(normalizedColor + vec3(dither), vec3(0.0));
|
||||
return vec4(normalizedColor, colorM.a);
|
||||
normalizedIrradiance = max(normalizedIrradiance + vec3(dither), vec3(0.0));
|
||||
vec3 blurredColor = normalizedIrradiance * albedo;
|
||||
vec3 result = mix(colorM.rgb, blurredColor, sssWeight);
|
||||
return vec4(result, colorM.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
vec2 texSize0 = vec2(textureSize(gbuffer0, 0));
|
||||
ivec2 texelCoord0 = ivec2(texCoord * texSize0);
|
||||
vec4 g0 = texelFetch(gbuffer0, texelCoord0, 0);
|
||||
float metallic;
|
||||
uint matid;
|
||||
unpackFloatInt16(g0.a, metallic, matid);
|
||||
|
||||
if (matid == 2u) {
|
||||
vec4 originalColor = textureLod(tex, texCoord, 0.0);
|
||||
vec4 blurredColor = SSSSBlur();
|
||||
vec4 sssContribution = blurredColor - originalColor;
|
||||
vec4 combined = originalColor + max(vec4(0.0), sssContribution) * 0.8;
|
||||
fragColor = max(vec4(0.0), min(combined, vec4(10.0)));
|
||||
bool applySSS = false;
|
||||
vec3 sssRadius = vec3(1.0);
|
||||
float sssWeight = 1.0;
|
||||
vec4 matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7;
|
||||
#ifdef _ExtBRDF
|
||||
if (matid >= 3u && matid < uint(MAX_MATERIALS)) {
|
||||
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
|
||||
// matp3.z = subsurface, matp4.xyz = subsurfaceRadiusRGB, matp7.x = subsurfaceScale
|
||||
if (matp3.z > 0.0) {
|
||||
applySSS = true;
|
||||
sssRadius = matp4.xyz * matp7.x;
|
||||
sssWeight = matp3.z;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (applySSS) {
|
||||
fragColor = SSSSBlur(sssRadius, sssWeight);
|
||||
} else {
|
||||
fragColor = textureLod(tex, texCoord, 0.0);
|
||||
vec2 texSizeMain = vec2(textureSize(tex, 0));
|
||||
ivec2 texelCoordMain = ivec2(texCoord * texSizeMain);
|
||||
fragColor = texelFetch(tex, texelCoordMain, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,16 @@
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "projectionMatrix",
|
||||
"link": "_projectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "materialParams",
|
||||
"link": "_materialParams",
|
||||
"type": "floats",
|
||||
"ifdef": ["_ExtBRDF"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
@ -32,6 +42,16 @@
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "projectionMatrix",
|
||||
"link": "_projectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "materialParams",
|
||||
"link": "_materialParams",
|
||||
"type": "floats",
|
||||
"ifdef": ["_ExtBRDF"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
|
||||
@ -1,10 +1,30 @@
|
||||
#ifndef _BRDF_GLSL_
|
||||
#define _BRDF_GLSL_
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.1415926535
|
||||
#endif
|
||||
#ifndef INV_PI
|
||||
#define INV_PI 0.3183098861
|
||||
#endif
|
||||
#ifndef INV_TWO_PI
|
||||
#define INV_TWO_PI 0.1591549430
|
||||
#endif
|
||||
#ifndef SCHLICK_A
|
||||
#define SCHLICK_A -5.55473
|
||||
#endif
|
||||
#ifndef SCHLICK_B
|
||||
#define SCHLICK_B -6.98316
|
||||
#endif
|
||||
#ifndef SRGB_GAMMA
|
||||
#define SRGB_GAMMA 2.2
|
||||
#endif
|
||||
#define srgbToLinear(x) pow(x, vec3(SRGB_GAMMA))
|
||||
|
||||
// http://xlgames-inc.github.io/posts/improvedibl/
|
||||
// http://blog.selfshadow.com/publications/s2013-shading-course/
|
||||
vec3 f_schlick(const vec3 f0, const float vh) {
|
||||
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
|
||||
return f0 + (1.0 - f0) * exp2((SCHLICK_A * vh + SCHLICK_B) * vh);
|
||||
}
|
||||
|
||||
float v_smithschlick(const float nl, const float nv, const float a) {
|
||||
@ -31,7 +51,7 @@ float d_ggx(const float nh, const float a) {
|
||||
float a2 = a * a;
|
||||
float denom = nh * nh * (a2 - 1.0) + 1.0;
|
||||
denom = max(denom * denom, 0.00006103515625 /* 2^-14 = smallest possible half float value, prevent div by zero */);
|
||||
return a2 * (1.0 / 3.1415926535) / denom;
|
||||
return a2 * INV_PI / denom;
|
||||
}
|
||||
|
||||
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
|
||||
@ -44,11 +64,10 @@ vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const fl
|
||||
// http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/
|
||||
vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, const float dotNH, const float dotLH) {
|
||||
// D
|
||||
const float pi = 3.1415926535;
|
||||
float alpha = roughness * roughness;
|
||||
float alphaSqr = alpha * alpha;
|
||||
float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
|
||||
float D = alphaSqr / (pi * denom * denom);
|
||||
float D = alphaSqr / (PI * denom * denom);
|
||||
// F
|
||||
const float F_a = 1.0;
|
||||
float F_b = pow(1.0 - dotLH, 5.0);
|
||||
@ -65,21 +84,8 @@ vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, cons
|
||||
return specular / 4.0; // TODO: get rid of / 4.0
|
||||
}
|
||||
|
||||
vec3 orenNayarDiffuseBRDF(const vec3 albedo, const float roughness, const float nv, const float nl, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
float s = a;
|
||||
float s2 = s * s;
|
||||
float vl = 2.0 * vh * vh - 1.0; // Double angle identity
|
||||
float Cosri = vl - nv * nl;
|
||||
float C1 = 1.0 - 0.5 * s2 / (s2 + 0.33);
|
||||
float test = 1.0;
|
||||
if (Cosri >= 0.0) test = (1.0 / (max(nl, nv)));
|
||||
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * test;
|
||||
return albedo * max(0.0, nl) * (C1 + C2) * (1.0 + roughness * 0.5);
|
||||
}
|
||||
|
||||
vec3 lambertDiffuseBRDF(const vec3 albedo, const float nl) {
|
||||
return albedo * (1.0 / 3.1415926535) * nl;
|
||||
return albedo * INV_PI * nl;
|
||||
}
|
||||
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
@ -95,24 +101,6 @@ float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||
return roughness * numMipmaps;
|
||||
}
|
||||
|
||||
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) {
|
||||
if(dotNL < 0.0 || dotNV < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
// fiberDirection - parse from rotation
|
||||
// shinyParallel - roughness
|
||||
// shinyPerpendicular - anisotropy
|
||||
|
||||
vec3 fiberParallel = normalize(fiberDirection);
|
||||
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection));
|
||||
float dotXH = dot(fiberParallel, H);
|
||||
float dotYH = dot(fiberPerpendicular, H);
|
||||
const float PI = 3.1415926535;
|
||||
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular);
|
||||
float theta = (pow(dotXH/shinyParallel, 2.0) + pow(dotYH/shinyPerpendicular, 2.0)) / (1.0 + dotNH);
|
||||
return clamp(coeff * exp(-2.0 * theta), 0.0, 1.0);
|
||||
}
|
||||
|
||||
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
||||
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) {
|
||||
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
|
||||
@ -139,38 +127,39 @@ float D_Approx(const float Roughness, const float RoL) {
|
||||
}
|
||||
|
||||
#ifdef _ClearCoat
|
||||
float brdf_coatF0;
|
||||
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) {
|
||||
const float coat_ior, const vec3 coatN, const vec3 l, const vec3 v, const vec3 h) {
|
||||
if (clearcoat <= 0.0) return vec3(0.0);
|
||||
float cdotNL = max(0.0, dot(coatN, l));
|
||||
float cdotNH = max(0.0, dot(coatN, h));
|
||||
float cdotNV = max(0.0, dot(coatN, v));
|
||||
float cdotVH = max(0.0, dot(v, h));
|
||||
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 F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * cdotVH + SCHLICK_B) * cdotVH);
|
||||
float D = d_ggx(cdotNH, a);
|
||||
float G = g2_approx(cdotNL, cdotNV, a);
|
||||
return vec3(clearcoat * D * G * F / max(4.0 * cdotNV, 1e-5));
|
||||
}
|
||||
|
||||
float coatAttenuation(const float clearcoat,
|
||||
const float coat_ior, const float dotNV) {
|
||||
const float coat_ior, const vec3 coatN, const vec3 v) {
|
||||
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);
|
||||
float cdotNV = max(0.0, dot(coatN, v));
|
||||
float F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * cdotNV + SCHLICK_B) * cdotNV);
|
||||
return max(1.0 - F * clearcoat, 0.0);
|
||||
}
|
||||
|
||||
vec3 coatTintAttenuation(const float clearcoat, const vec3 coat_tint, const float dotNV) {
|
||||
vec3 coatTintAttenuation(const float clearcoat, const vec3 coat_tint, const vec3 coatN, const vec3 v) {
|
||||
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));
|
||||
float cdotNV = max(0.0, dot(coatN, v));
|
||||
float absorption = 1.0 / max(cdotNV, 0.3);
|
||||
return mix(vec3(1.0), clamp(coat_tint, 0.0, 1.0), clamp(absorption * 0.2, 0.0, 1.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Sheen
|
||||
float brdf_sheenAlbedo;
|
||||
// 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) {
|
||||
@ -179,18 +168,16 @@ vec3 sheenBRDF(const float sheen, const float sheen_rough,
|
||||
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 denom = 1.0 + a2 * sinNH2;
|
||||
float D = (2.0 + a2) * sinNH2 * INV_TWO_PI / (denom * denom);
|
||||
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;
|
||||
return sheen_tint * sheen * D * V * dotNL * brdf_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;
|
||||
float maxComp = sheen * max(max(sheen_tint.r, sheen_tint.g), sheen_tint.b) * brdf_sheenAlbedo;
|
||||
return max(1.0 - maxComp, 0.0);
|
||||
}
|
||||
#endif
|
||||
@ -202,7 +189,7 @@ vec3 anisotropicBRDF(const vec3 f0, const float roughness, const float anisotrop
|
||||
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 rot = aniso_rot * PI * 2.0;
|
||||
float cr = cos(rot);
|
||||
float sr = sin(rot);
|
||||
vec3 t = normalize(tangent * cr + bitangent * sr);
|
||||
@ -221,7 +208,7 @@ vec3 anisotropicBRDF(const vec3 f0, const float roughness, const float anisotrop
|
||||
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 D = INV_PI / (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);
|
||||
@ -229,46 +216,117 @@ vec3 anisotropicBRDF(const vec3 f0, const float roughness, const float anisotrop
|
||||
}
|
||||
#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
|
||||
float brdf_transmissionF0;
|
||||
// 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 F = brdf_transmissionF0 + (1.0 - brdf_transmissionF0) * exp2((SCHLICK_A * dotVH + SCHLICK_B) * dotVH);
|
||||
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);
|
||||
float rough_atten = min(mix(1.0, 1.0 / max(dotNV, 0.1), a), 4.0);
|
||||
return albedo * transmission * transmittance * rough_atten * dotNL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _ExtBRDF
|
||||
float brdf_sheenWeight = 1.0;
|
||||
float brdf_coatWeight = 1.0;
|
||||
vec3 brdf_coatTintAbsorb = vec3(1.0);
|
||||
|
||||
vec3 applyExtBRDFLayers(
|
||||
const vec3 direct,
|
||||
const vec3 albedo,
|
||||
const vec3 f0,
|
||||
const float roughness,
|
||||
const float dotNL, const float dotNV, const float dotNH, const float dotVH,
|
||||
const vec3 n, const vec3 l, const vec3 v, const vec3 h,
|
||||
#ifdef _ClearCoat
|
||||
const float clearcoat, const float clearcoatRough, const float coatIOR,
|
||||
const vec3 coatTint, const vec3 coatN,
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
const float sheen, const float sheenRough, const vec3 sheenTint,
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
const float transmission, const float transRough, const float ior, const float thinWall,
|
||||
#endif
|
||||
out float layerWeight
|
||||
) {
|
||||
float sheenWeight = brdf_sheenWeight;
|
||||
float coatWeight = brdf_coatWeight;
|
||||
#ifdef _Sheen
|
||||
vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV);
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, coatN, l, v, h);
|
||||
#endif
|
||||
layerWeight = sheenWeight * coatWeight;
|
||||
vec3 result = direct * layerWeight;
|
||||
#ifdef _Transmission
|
||||
result += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight;
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
result *= brdf_coatTintAbsorb;
|
||||
result += coatContrib * sheenWeight;
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
result += sheenContrib;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _ClearCoat
|
||||
float coatIBLFresnel(const float clearcoat, const float coat_ior,
|
||||
const float dotNV_coat) {
|
||||
if (clearcoat <= 0.0) return 0.0;
|
||||
float F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * dotNV_coat + SCHLICK_B) * dotNV_coat);
|
||||
return F * clearcoat;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Sheen
|
||||
float sheenIBLAlbedo(const float sheen, const float sheen_rough,
|
||||
const float dotNV) {
|
||||
if (sheen <= 0.0) return 0.0;
|
||||
float rough = clamp(sheen_rough, 1e-3, 1.0);
|
||||
return sheen * (1.0 - 0.5 * rough) * mix(1.0, dotNV, 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Anisotropy
|
||||
vec3 anisotropicIBLDirection(const vec3 n, const vec3 v, const vec3 tangent,
|
||||
const float anisotropy, const float roughness) {
|
||||
if (abs(anisotropy) <= 0.001 || dot(tangent, tangent) < 0.001)
|
||||
return reflect(-v, n);
|
||||
vec3 bitangent = normalize(cross(n, tangent));
|
||||
vec3 r = reflect(-v, n);
|
||||
float aniso_abs = abs(anisotropy);
|
||||
vec3 stretchDir = anisotropy > 0.0 ? tangent : bitangent;
|
||||
float stretchAmt = aniso_abs * roughness;
|
||||
return normalize(r + stretchDir * stretchAmt * dot(r, stretchDir) * 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _Transmission
|
||||
float transmissionIBLFresnel(const float ior, const float dotNV) {
|
||||
return brdf_transmissionF0 + (1.0 - brdf_transmissionF0) * exp2((SCHLICK_A * dotNV + SCHLICK_B) * dotNV);
|
||||
}
|
||||
|
||||
vec3 transmissionIBLDirection(const vec3 n, const vec3 v, const float ior) {
|
||||
float eta = 1.0 / ior;
|
||||
vec3 refrDir = refract(-v, n, eta);
|
||||
if (dot(refrDir, refrDir) < 0.001) {
|
||||
refrDir = reflect(-v, n);
|
||||
}
|
||||
return refrDir;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -34,17 +34,19 @@ THE SOFTWARE.
|
||||
// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
|
||||
|
||||
const float MAX_DISTANCE = voxelgiRange;
|
||||
const int MAX_CONE_STEPS = 32;
|
||||
|
||||
#ifdef _VoxelGI
|
||||
uniform sampler3D dummy;
|
||||
|
||||
vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
|
||||
vec4 col = vec4(0.0);
|
||||
vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
tc = tc * 0.5 + 0.5;
|
||||
tc = clamp(tc, half_texel, 1.0 - half_texel);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
@ -55,7 +57,7 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
|
||||
else
|
||||
col = textureLod(voxels, tc, 0);
|
||||
|
||||
col *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
col *= step_dist / voxelSize;
|
||||
|
||||
return col;
|
||||
}
|
||||
@ -64,11 +66,13 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
|
||||
#ifdef _VoxelAOvar
|
||||
float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
|
||||
float opac = 0.0;
|
||||
vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
tc = tc * 0.5 + 0.5;
|
||||
tc = clamp(tc, half_texel, 1.0 - half_texel);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
@ -79,7 +83,7 @@ float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapC
|
||||
else
|
||||
opac = textureLod(voxels, tc, 0).r;
|
||||
|
||||
opac *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
opac *= step_dist / voxelSize;
|
||||
|
||||
return opac;
|
||||
}
|
||||
@ -92,7 +96,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -100,12 +104,14 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
int steps = 0;
|
||||
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
vec4 mipSample = vec4(0.0);
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -113,7 +119,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, fract(lod));
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if (any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0)))) {
|
||||
@ -129,8 +137,11 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
mipSampleNext *= voxelSizeCoarse / voxelSize;
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
|
||||
@ -138,8 +149,6 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
|
||||
float stepSizeCurrent = step_size;
|
||||
if (use_sdf) {
|
||||
// half texel correction is applied to avoid sampling over current clipmap:
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
|
||||
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
|
||||
float sdf = textureLod(voxelsSDF, tc0, 0).r;
|
||||
@ -147,6 +156,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
}
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -154,13 +164,13 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sum = 0.0;
|
||||
vec4 amount = vec4(0.0);
|
||||
for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
|
||||
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
|
||||
for (int i = 0; i < diffuseConeCount; ++i) {
|
||||
vec3 coneDir = diffuseConeDirections[i];
|
||||
const float cosTheta = dot(normal, coneDir);
|
||||
if (cosTheta <= 0)
|
||||
continue;
|
||||
int precomputed_direction = 6 + i;
|
||||
amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
|
||||
amount += traceCone(voxels, voxels, origin, normal, coneDir, precomputed_direction, false, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
|
||||
@ -191,7 +201,7 @@ vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sam
|
||||
amount.rgb = max(vec3(0.0), amount.rgb);
|
||||
amount.a = clamp(amount.a, 0.0, 1.0);
|
||||
|
||||
return amount * voxelgiOcc;
|
||||
return amount * voxelgiOcc * voxelgiRefr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -202,7 +212,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -210,12 +220,13 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
int steps = 0;
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -223,7 +234,9 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, fract(lod));
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) {
|
||||
@ -239,8 +252,11 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
mipSampleNext *= voxelSizeCoarse / voxelSize;
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
|
||||
@ -248,6 +264,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
|
||||
step_dist = diam * step_size;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -256,18 +273,18 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sum = 0.0;
|
||||
float amount = 0.0;
|
||||
for (int i = 0; i < DIFFUSE_CONE_COUNT; i++) {
|
||||
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
|
||||
for (int i = 0; i < diffuseConeCount; i++) {
|
||||
vec3 coneDir = diffuseConeDirections[i];
|
||||
int precomputed_direction = 6 + i;
|
||||
const float cosTheta = dot(normal, coneDir);
|
||||
if (cosTheta <= 0)
|
||||
continue;
|
||||
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
|
||||
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
amount /= max(sum, 0.0001);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
return amount;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -278,7 +295,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -286,11 +303,13 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
int steps = 0;
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -298,7 +317,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, fract(lod));
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
|
||||
@ -318,11 +339,14 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight).a;
|
||||
#endif
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
float scaleRatio = voxelSizeCoarse / voxelSize;
|
||||
#ifdef _VoxelAOvar
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight);
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight) * scaleRatio;
|
||||
#else
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a;
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a * scaleRatio;
|
||||
#endif
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
@ -331,8 +355,6 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
float stepSizeCurrent = step_size;
|
||||
|
||||
// half texel correction is applied to avoid sampling over current clipmap:
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
|
||||
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
|
||||
float sdf = textureLod(voxelsSDF, tc0, 0.0).r;
|
||||
@ -340,6 +362,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -347,7 +370,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps);
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, voxelgiAperture, voxelgiStep, clipmaps);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
|
||||
@ -20,13 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
const int DIFFUSE_CONE_COUNT = 16;
|
||||
const float diffuseConeAperture = radians(39.0);
|
||||
|
||||
const float SHADOW_CONE_APERTURE = radians(15.0);
|
||||
|
||||
const float DIFFUSE_CONE_APERTURE = 1.0;
|
||||
|
||||
const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[](
|
||||
const vec3 diffuseConeDirections[16] = vec3[](
|
||||
vec3( 0.3480, 0.0000, 0.9375),
|
||||
vec3(-0.4299, 0.3938, 0.8125),
|
||||
vec3( 0.0635, -0.7234, 0.6875),
|
||||
|
||||
@ -173,16 +173,85 @@ void unpackFloatInt16(float val, out float f, out uint i) {
|
||||
#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) {
|
||||
out vec4 p4, out vec4 p5, out vec4 p6, out vec4 p7) {
|
||||
uint base = matid * 8u;
|
||||
#if defined(_Anisotropy) || defined(_Sheen)
|
||||
p0 = materialParams[base];
|
||||
#else
|
||||
p0 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_ClearCoat)
|
||||
p1 = materialParams[base + 1u];
|
||||
#else
|
||||
p1 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_ClearCoat) || defined(_Transmission)
|
||||
p2 = materialParams[base + 2u];
|
||||
#else
|
||||
p2 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_Transmission) || defined(_SSS)
|
||||
p3 = materialParams[base + 3u];
|
||||
#else
|
||||
p3 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_SSS)
|
||||
p4 = materialParams[base + 4u];
|
||||
#else
|
||||
p4 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_Sheen) || defined(_SSS)
|
||||
p5 = materialParams[base + 5u];
|
||||
#else
|
||||
p5 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_ExtBRDF)
|
||||
p6 = materialParams[base + 6u];
|
||||
#else
|
||||
p6 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(_SSS)
|
||||
p7 = materialParams[base + 7u];
|
||||
#else
|
||||
p7 = vec4(0.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
float packIOR(float ior) {
|
||||
return clamp((ior - 1.0) / 1.5, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float unpackIOR(float packed) {
|
||||
return packed * 1.5 + 1.0;
|
||||
}
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.1415926535
|
||||
#endif
|
||||
#ifndef PI2
|
||||
#define PI2 6.2831853071
|
||||
#endif
|
||||
|
||||
float encodeTangent(vec3 tangent, vec3 normal) {
|
||||
if (length(tangent) < 0.5) return -1.0;
|
||||
vec3 t = normalize(tangent);
|
||||
vec3 n = normalize(normal);
|
||||
vec3 ref = abs(n.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 r = normalize(ref - n * dot(ref, n));
|
||||
vec3 b = cross(n, r);
|
||||
float angle = atan(dot(t, b), dot(t, r));
|
||||
return (angle / (2.0 * PI) + 0.5);
|
||||
}
|
||||
|
||||
vec3 decodeTangent(float enc, vec3 normal) {
|
||||
if (enc < 0.0) return vec3(1.0, 0.0, 0.0);
|
||||
vec3 n = normalize(normal);
|
||||
vec3 ref = abs(n.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 r = normalize(ref - n * dot(ref, n));
|
||||
vec3 b = cross(n, r);
|
||||
float angle = (enc - 0.5) * 2.0 * PI;
|
||||
return normalize(r * cos(angle) + b * sin(angle));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,7 +3,9 @@ uniform sampler2D texIES;
|
||||
|
||||
float iesAttenuation(vec3 l) {
|
||||
|
||||
const float PI = 3.1415926535;
|
||||
#ifndef PI
|
||||
#define PI 3.1415926535
|
||||
#endif
|
||||
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
||||
// Sample direction into light space
|
||||
// vec3 iesSampleDirection = mul(light.worldToLight , -L);
|
||||
|
||||
@ -51,7 +51,9 @@
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef _SinglePoint
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
@ -92,7 +94,6 @@ uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
#ifdef _ShadowMapTransparent
|
||||
@ -100,18 +101,10 @@ uniform sampler2D sltcMag;
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
#ifdef _ShadowMapTransparent
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
vec3 sampleLightCore(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
@ -122,17 +115,8 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
@ -140,20 +124,25 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
#ifdef _SSS
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, float transmission, float transRough, float ior, float thinWall
|
||||
#endif
|
||||
, out vec3 l_out
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
float dist = length(ld);
|
||||
vec3 l = ld / dist;
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _VoxelPass
|
||||
vec3 direct = vec3(dotNL);
|
||||
#else
|
||||
#ifdef _LTC
|
||||
float theta = acos(dotNV);
|
||||
vec2 tuv = vec2(rough, theta / (0.5 * PI));
|
||||
@ -170,7 +159,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#else
|
||||
#ifdef _Anisotropy
|
||||
vec3 direct;
|
||||
if (abs(anisotropy) > 0.001) {
|
||||
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
|
||||
vec3 bitangent = normalize(cross(n, tangent));
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
|
||||
@ -181,62 +170,36 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
}
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
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);
|
||||
#ifdef _ExtBRDF
|
||||
float layerWeight;
|
||||
direct = applyExtBRDFLayers(direct, albedo, f0, rough,
|
||||
dotNL, dotNV, dotNH, dotVH, n, l, v, h
|
||||
#ifdef _ClearCoat
|
||||
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, sheen, sheenRough, sheenTint
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, transmission, transRough, ior, thinWall
|
||||
#endif
|
||||
, layerWeight);
|
||||
#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 *= attenuate(dist);
|
||||
direct *= min(lightCol, vec3(100.0));
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
vec3 lightDir = l;
|
||||
#ifdef _Spot
|
||||
if (isSpot)
|
||||
lightDir = spotDir;
|
||||
#endif
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
@ -248,7 +211,29 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSpotArray[index];
|
||||
direct *= shadowTest(
|
||||
#ifdef _ShadowMapTransparent
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
@ -286,8 +271,10 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
l_out = l;
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
@ -312,25 +299,26 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifdef _ShadowMapTransparent
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
tileBounds = tileBoundsSpotArray[index];
|
||||
direct *= shadowTest(
|
||||
#ifdef _ShadowMapTransparent
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
@ -372,6 +360,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
l_out = l;
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
@ -458,9 +447,157 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
}
|
||||
#endif
|
||||
|
||||
l_out = l;
|
||||
return direct;
|
||||
}
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, bool transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, float transmission, float transRough, float ior, float thinWall
|
||||
#endif
|
||||
) {
|
||||
vec3 l;
|
||||
vec3 direct = sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
|
||||
#ifdef _ShadowMap
|
||||
, index, bias, receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, isSpot, spotSize, spotBlend, spotDir, scale, right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, sheen, sheenRough, sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, anisotropy, anisoRot, tangent
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, subsurface, sssColor, sssRadius, sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, transmission, transRough, ior, thinWall
|
||||
#endif
|
||||
, l);
|
||||
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
vec3 lightDir = l;
|
||||
#ifdef _Spot
|
||||
if (isSpot)
|
||||
lightDir = spotDir;
|
||||
#endif
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
|
||||
#ifdef _ExtBRDF
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, bool transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
) {
|
||||
return sampleLight(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
|
||||
#ifdef _ShadowMap
|
||||
, index, bias, receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, isSpot, spotSize, spotBlend, spotDir, scale, right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, voxels, voxelsSDF, clipmaps, velocity
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, 0.0, 0.0, 1.5, vec3(1.0), n
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, 0.0, 0.0, vec3(1.0)
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, 0.0, 0.0, vec3(0.0)
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, 0.0, vec3(0.0), vec3(0.0), 0.0
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, 0.0, 0.0, 1.45, 1.0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif // _ExtBRDF
|
||||
|
||||
#ifdef _VoxelGI
|
||||
vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
@ -474,7 +611,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
||||
, 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
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
@ -482,295 +619,85 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
#ifdef _SSS
|
||||
, 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);
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _LTC
|
||||
float theta = acos(dotNV);
|
||||
vec2 tuv = vec2(rough, theta / (0.5 * PI));
|
||||
tuv = tuv * LUT_SCALE + LUT_BIAS;
|
||||
vec4 t = textureLod(sltcMat, tuv, 0.0);
|
||||
mat3 invM = mat3(
|
||||
vec3(1.0, 0.0, t.y),
|
||||
vec3(0.0, t.z, 0.0),
|
||||
vec3(t.w, 0.0, t.x));
|
||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#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 *= attenuate(distance(p, lp));
|
||||
// CRITICAL: Clamp light color to prevent extreme HDR values causing white sphere artifacts
|
||||
direct *= min(lightCol, vec3(100.0));
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[1],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[2],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[3],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
) {
|
||||
vec3 l;
|
||||
return sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifdef _ShadowMapTransparent
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[0],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[1],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[2],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapSpotTransparent[3],
|
||||
#endif
|
||||
lPos.xyz / lPos.w, bias
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
, index, bias, receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapPointTransparent[0],
|
||||
#endif
|
||||
ld, -l, bias, lightProj, n
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifdef _ShadowMapTransparent
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapPointTransparent[0],
|
||||
#endif
|
||||
ld, -l, bias, lightProj, n
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapPointTransparent[1],
|
||||
#endif
|
||||
ld, -l, bias, lightProj, n
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapPointTransparent[2],
|
||||
#endif
|
||||
ld, -l, bias, lightProj, n
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3],
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapPointTransparent[3],
|
||||
#endif
|
||||
ld, -l, bias, lightProj, n
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, isSpot, spotSize, spotBlend, spotDir, scale, right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, sheen, sheenRough, sheenTint
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, anisotropy, anisoRot, tangent
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, subsurface, sssColor, sssRadius, sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, transmission, transRough, ior, thinWall
|
||||
#endif
|
||||
, l);
|
||||
}
|
||||
|
||||
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
|
||||
#ifdef _ExtBRDF
|
||||
vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, bool transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
) {
|
||||
vec3 l;
|
||||
return sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
|
||||
#ifdef _ShadowMap
|
||||
, index, bias, receiveShadow
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, isSpot, spotSize, spotBlend, spotDir, scale, right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, 0.0, 0.0, 1.5, vec3(1.0), n
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, 0.0, 0.0, vec3(1.0)
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, 0.0, 0.0, vec3(0.0)
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, 0.0, vec3(0.0), vec3(0.0), 0.0
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, 0.0, 0.0, 1.45, 1.0
|
||||
#endif
|
||||
, l);
|
||||
}
|
||||
#endif // _ExtBRDF
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
uniform mat4 LWVPSpotArray[1];
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform vec2 lightProj;
|
||||
@ -24,7 +24,9 @@
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
#endif
|
||||
#ifndef _SinglePoint
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
@ -54,7 +56,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint
|
||||
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, float sheen, float sheenRough, vec3 sheenTint
|
||||
@ -62,7 +64,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _Anisotropy
|
||||
, float anisotropy, float anisoRot, vec3 tangent
|
||||
#endif
|
||||
#ifdef _Subsurface
|
||||
#ifdef _SSS
|
||||
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
@ -70,7 +72,8 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
float dist = length(ld);
|
||||
vec3 l = ld / dist;
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
@ -78,7 +81,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
|
||||
#ifdef _Anisotropy
|
||||
vec3 direct;
|
||||
if (abs(anisotropy) > 0.001) {
|
||||
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
|
||||
vec3 bitangent = normalize(cross(n, tangent));
|
||||
direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
|
||||
@ -92,34 +95,24 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
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;
|
||||
#ifdef _ExtBRDF
|
||||
float layerWeight;
|
||||
direct = applyExtBRDFLayers(direct, albedo, f0, rough, dotNL, dotNV, dotNH, dotVH, n, l, v, h
|
||||
#ifdef _ClearCoat
|
||||
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, sheen, sheenRough, sheenTint
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, transmission, transRough, ior, thinWall
|
||||
#endif
|
||||
, layerWeight
|
||||
);
|
||||
#endif
|
||||
|
||||
direct *= lightCol;
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= attenuate(dist);
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
@ -128,12 +121,13 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSpotArray[index];
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
@ -186,4 +180,41 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
return direct;
|
||||
}
|
||||
|
||||
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
|
||||
#ifdef _ExtBRDF
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
) {
|
||||
return sampleLight(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
|
||||
#ifdef _ShadowMap
|
||||
, index, bias, receiveShadow
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, isSpot, spotSize, spotBlend, spotDir, scale, right
|
||||
#endif
|
||||
#ifdef _ClearCoat
|
||||
, 0.0, 0.0, 1.5, vec3(1.0), n
|
||||
#endif
|
||||
#ifdef _Sheen
|
||||
, 0.0, 0.0, vec3(1.0)
|
||||
#endif
|
||||
#ifdef _Anisotropy
|
||||
, 0.0, 0.0, vec3(0.0)
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
, 0.0, vec3(0.0), vec3(0.0), 0.0
|
||||
#endif
|
||||
#ifdef _Transmission
|
||||
, 0.0, 0.0, 1.45, 1.0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif // _ExtBRDF
|
||||
|
||||
#endif
|
||||
|
||||
@ -8,8 +8,12 @@ float hash(const vec2 p) {
|
||||
}
|
||||
|
||||
vec2 envMapEquirect(const vec3 normal) {
|
||||
const float PI = 3.1415926535;
|
||||
const float PI2 = PI * 2.0;
|
||||
#ifndef PI
|
||||
#define PI 3.1415926535
|
||||
#endif
|
||||
#ifndef PI2
|
||||
#define PI2 6.2831853071
|
||||
#endif
|
||||
float phi = acos(normal.z);
|
||||
float theta = atan(-normal.y, normal.x) + PI;
|
||||
return vec2(theta / PI2, phi / PI);
|
||||
|
||||
@ -22,6 +22,14 @@ uniform vec2 smSizeUniform;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMapAtlas
|
||||
uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
|
||||
#if defined(_Clusters) && defined(_Spot) && defined(_ShadowMap)
|
||||
uniform vec4 tileBoundsSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
vec4 tileBounds = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMapAtlas
|
||||
// PCF that clamps samples to tile boundaries to prevent bleeding
|
||||
vec3 PCFTileAware(sampler2DShadow shadowMap,
|
||||
@ -291,13 +299,13 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
||||
, const bool transparent
|
||||
#endif
|
||||
) {
|
||||
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
||||
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||
ml = ml + n * bias * 20;
|
||||
int faceIndex = 0;
|
||||
const int lightIndex = index * 6;
|
||||
const vec2 uv = sampleCube(ml, faceIndex);
|
||||
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
||||
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
||||
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||
#ifdef _FlipY
|
||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||
@ -387,10 +395,6 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMapAtlas
|
||||
uniform vec4 tileBounds;
|
||||
#endif
|
||||
|
||||
vec3 shadowTest(sampler2DShadow shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
sampler2D shadowMapTransparent,
|
||||
@ -405,9 +409,9 @@ vec3 shadowTest(sampler2DShadow shadowMap,
|
||||
#ifdef _ShadowMapAtlas
|
||||
// use tile PCF
|
||||
#ifdef _SMSizeUniform
|
||||
vec2 smSizeAtlas = smSizeUniform;
|
||||
vec2 smSizeAtlas = smSizeUniform * (tileBounds.zw - tileBounds.xy);
|
||||
#else
|
||||
const vec2 smSizeAtlas = shadowmapSize;
|
||||
vec2 smSizeAtlas = shadowmapSize * (tileBounds.zw - tileBounds.xy);
|
||||
#endif
|
||||
return PCFTileAware(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
@ -455,7 +459,7 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
||||
float(d > casData[c * 4].y),
|
||||
float(d > casData[c * 4].z),
|
||||
float(d > casData[c * 4].w));
|
||||
casi = int(min(dot(ci, comp), c));
|
||||
casi = int(min(dot(ci, comp), float(c - 1)));
|
||||
// Get cascade mat
|
||||
casIndex = casi * 4;
|
||||
return mat4(
|
||||
@ -479,8 +483,12 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
||||
#ifdef _SMSizeUniform
|
||||
vec2 smSize = smSizeUniform;
|
||||
#else
|
||||
#ifdef _ShadowMapAtlas
|
||||
vec2 smSize = shadowmapSize * (tileBoundsSunArray[0].zw - tileBoundsSunArray[0].xy);
|
||||
#else
|
||||
const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
const int c = shadowmapCascades;
|
||||
float d = distance(eye, p);
|
||||
int casi;
|
||||
@ -489,16 +497,35 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||
lPos.xyz /= lPos.w;
|
||||
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSunArray[casi];
|
||||
#endif
|
||||
|
||||
vec3 visibility = vec3(1.0);
|
||||
if (lPos.w > 0.0) visibility = PCF(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos.xy, lPos.z - shadowsBias, smSize
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
if (lPos.w > 0.0) {
|
||||
#ifdef _ShadowMapAtlas
|
||||
visibility = PCFTileAware(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos.xy, lPos.z - shadowsBias, smSize,
|
||||
tileBounds.xy, tileBounds.zw
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
visibility = PCF(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos.xy, lPos.z - shadowsBias, smSize
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Blend cascade
|
||||
// https://github.com/TheRealMJP/Shadows
|
||||
@ -518,15 +545,33 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
||||
lPos2.xyz /= lPos2.w;
|
||||
vec3 visibility2 = vec3(1.0);
|
||||
// use lPos2 coordinates for second cascade, not lPos
|
||||
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos2.xy, lPos2.z - shadowsBias, smSize
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#ifdef _ShadowMapAtlas
|
||||
tileBounds = tileBoundsSunArray[casi + 1];
|
||||
#endif
|
||||
if (lPos2.w > 0.0) {
|
||||
#ifdef _ShadowMapAtlas
|
||||
visibility2 = PCFTileAware(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos2.xy, lPos2.z - shadowsBias, smSize,
|
||||
tileBounds.xy, tileBounds.zw
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
visibility2 = PCF(shadowMap,
|
||||
#ifdef _ShadowMapTransparent
|
||||
shadowMapTransparent,
|
||||
#endif
|
||||
lPos2.xy, lPos2.z - shadowsBias, smSize
|
||||
#ifdef _ShadowMapTransparent
|
||||
, transparent
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
||||
return mix(visibility2, visibility, lerpAmt);
|
||||
|
||||
@ -26,7 +26,7 @@ uniform sampler2D singleScatterLUT;
|
||||
uniform vec2 skyDensity;
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.141592
|
||||
#define PI 3.1415926535
|
||||
#endif
|
||||
#ifndef HALF_PI
|
||||
#define HALF_PI 1.570796
|
||||
|
||||
@ -1,15 +1,25 @@
|
||||
|
||||
// Separable SSS Transmittance Function, ref to sss_pass
|
||||
vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sampler2DShadow shadowMap) {
|
||||
const float translucency = 1.0;
|
||||
vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sampler2DShadow shadowMap, vec3 sssColor, float sssRadius
|
||||
#ifdef _ShadowMapAtlas
|
||||
, vec4 tileBounds
|
||||
#endif
|
||||
) {
|
||||
const float translucency = 0.85;
|
||||
vec4 shrinkedPos = vec4(p - 0.005 * n, 1.0);
|
||||
vec4 shadowPos = LWVP * shrinkedPos;
|
||||
float scale = 8.25 * (1.0 - translucency) / (sssWidth / 10.0);
|
||||
float d1 = texture(shadowMap, vec3(shadowPos.xy / shadowPos.w, shadowPos.z)).r; // 'd1' has a range of 0..1
|
||||
float d2 = shadowPos.z; // 'd2' has a range of 0..'lightFarPlane'
|
||||
d1 *= lightFar; // So we scale 'd1' accordingly:
|
||||
float d = scale * abs(d1 - d2);
|
||||
vec2 shadowUV = shadowPos.xy / shadowPos.w;
|
||||
#ifdef _ShadowMapAtlas
|
||||
shadowUV = clamp(shadowUV, tileBounds.xy, tileBounds.zw);
|
||||
#endif
|
||||
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
|
||||
float d1 = texture(shadowMap, vec3(shadowUV, shadowPos.z)).r;
|
||||
float d2 = shadowPos.z;
|
||||
d1 *= lightFar;
|
||||
d2 *= lightFar;
|
||||
float d = scale * abs(d1 - d2) * 1000.0;
|
||||
|
||||
if (d > 10.0) return vec3(0.0);
|
||||
float dd = -d * d;
|
||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||
@ -17,10 +27,70 @@ vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sample
|
||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||
return profile * clamp(0.3 + dot(l, -n), 0.0, 1.0);
|
||||
profile *= mix(vec3(1.0), sssColor, 0.8);
|
||||
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 SSSSTransmittanceCube(float translucency, vec4 shadowPos, vec3 n, vec3 l, float lightFar) {
|
||||
// TODO
|
||||
return vec3(0.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
vec3 SSSSTransmittanceCubeAtlas(sampler2DShadow shadowMap, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, int index, vec3 sssColor, float sssRadius) {
|
||||
const float translucency = 0.85;
|
||||
vec3 shrinkedPos = p - 0.005 * n;
|
||||
vec3 ld = normalize(shrinkedPos - lightPos);
|
||||
#ifdef _InvY
|
||||
ld.y = -ld.y;
|
||||
#endif
|
||||
float d2 = lpToDepth(ld, lightProj);
|
||||
int faceIndex = 0;
|
||||
int lightIndex = index * 6;
|
||||
vec2 uv = sampleCube(ld, faceIndex);
|
||||
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex];
|
||||
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||
#ifdef _FlipY
|
||||
uvtiled.y = 1.0 - uvtiled.y;
|
||||
#endif
|
||||
float d1 = texture(shadowMap, vec3(uvtiled, d2)).r;
|
||||
d1 *= lightFar;
|
||||
d2 *= lightFar;
|
||||
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
|
||||
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
|
||||
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
|
||||
|
||||
if (d > 10.0) return vec3(0.0);
|
||||
float dd = -d * d;
|
||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||
profile *= mix(vec3(1.0), sssColor, 0.8);
|
||||
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 SSSSTransmittanceCube(samplerCubeShadow shadowMapCube, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, vec3 sssColor, float sssRadius) {
|
||||
const float translucency = 0.85;
|
||||
vec3 shrinkedPos = p - 0.005 * n;
|
||||
vec3 ld = normalize(shrinkedPos - lightPos);
|
||||
#ifdef _InvY
|
||||
ld.y = -ld.y;
|
||||
#endif
|
||||
float d2 = lpToDepth(ld, lightProj);
|
||||
float d1 = texture(shadowMapCube, vec4(ld, d2)).r;
|
||||
d1 *= lightFar;
|
||||
d2 *= lightFar;
|
||||
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
|
||||
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
|
||||
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
|
||||
|
||||
if (d > 10.0) return vec3(0.0);
|
||||
float dd = -d * d;
|
||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||
profile *= mix(vec3(1.0), sssColor, 0.8);
|
||||
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
|
||||
}
|
||||
|
||||
@ -38,7 +38,6 @@ uniform layout(r8) image3D voxelsOut;
|
||||
#endif
|
||||
|
||||
uniform int clipmapLevel;
|
||||
uniform float voxelBlend;
|
||||
|
||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||
|
||||
@ -47,7 +46,7 @@ void main() {
|
||||
ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
|
||||
src.y += clipmapLevel * res;
|
||||
|
||||
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
|
||||
for (int i = 0; i < 6 + diffuseConeCount; i++)
|
||||
{
|
||||
vec4 col = vec4(0.0);
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ void main() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
envl.rgb *= envmapStrength * voxelgiEnv * occspec.x;
|
||||
|
||||
vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps));
|
||||
|
||||
|
||||
@ -53,13 +53,6 @@ uniform float shirr[7 * 4];
|
||||
#ifdef _Brdf
|
||||
uniform sampler2D senvmapBrdf;
|
||||
#endif
|
||||
#ifdef _Rad
|
||||
uniform sampler2D senvmapRadiance;
|
||||
uniform int envmapNumMipmaps;
|
||||
#endif
|
||||
#ifdef _EnvCol
|
||||
uniform vec3 backgroundCol;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||
@ -140,17 +133,8 @@ void main() {
|
||||
vec3 envl = vec3(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
#endif
|
||||
|
||||
#ifdef _EnvLDR
|
||||
envl.rgb = pow(envl.rgb, vec3(2.2));
|
||||
#ifdef _Rad
|
||||
prefilteredColor = pow(prefilteredColor, vec3(2.2));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= albedo;
|
||||
@ -159,15 +143,7 @@ void main() {
|
||||
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
|
||||
#endif
|
||||
|
||||
#ifdef _Rad // Indirect specular
|
||||
envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
|
||||
#else
|
||||
#ifdef _EnvCol
|
||||
envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
envl.rgb *= envmapStrength * voxelgiEnv * occspec.x;
|
||||
|
||||
vec4 trace = traceDiffuse(P, n, voxels, clipmaps);
|
||||
vec3 color = trace.rgb * albedo * (1.0 - F);
|
||||
|
||||
@ -48,13 +48,15 @@ void main() {
|
||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
||||
#ifdef _InvY
|
||||
uv.y = 1.0 - uv.y
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
|
||||
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
||||
if (depth == 0) return;
|
||||
|
||||
vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy;
|
||||
float ior = unpackIOR(ior_opac.x);
|
||||
float opacity = ior_opac.y;
|
||||
|
||||
float x = uv.x * 2 - 1;
|
||||
float y = uv.y * 2 - 1;
|
||||
@ -72,8 +74,8 @@ void main() {
|
||||
n = normalize(n);
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
if(ior_opac.y < 1.0)
|
||||
color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb;
|
||||
if(opacity < 1.0)
|
||||
color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior, g0.b, clipmaps, pixel).rgb;
|
||||
|
||||
imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0));
|
||||
}
|
||||
|
||||
@ -66,9 +66,13 @@ void main() {
|
||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||
n = normalize(n);
|
||||
|
||||
float roughness = g0.b;
|
||||
|
||||
vec3 v = normalize(eye - P);
|
||||
|
||||
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
|
||||
|
||||
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb;
|
||||
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, v, roughness * roughness, clipmaps, pixel, velocity).rgb;
|
||||
|
||||
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ void main() {
|
||||
float aniso_colors[6];
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
|
||||
for (int i = 0; i < 6 + diffuseConeCount; i++)
|
||||
{
|
||||
ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
|
||||
src.x += i * res;
|
||||
@ -136,7 +136,7 @@ void main() {
|
||||
radiance = basecol;
|
||||
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps);
|
||||
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
|
||||
radiance.rgb *= light.rgb + indirect.rgb;
|
||||
radiance.rgb *= light.rgb * INV_PI + indirect.rgb;
|
||||
radiance.rgb += emission.rgb;
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ void main() {
|
||||
}
|
||||
else {
|
||||
// precompute cone sampling:
|
||||
vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6];
|
||||
vec3 coneDirection = diffuseConeDirections[i - 6];
|
||||
vec3 aniso_direction = -coneDirection;
|
||||
uvec3 face_offsets = uvec3(
|
||||
aniso_direction.x > 0 ? 0 : 1,
|
||||
|
||||
Reference in New Issue
Block a user