Compare commits
4 Commits
main
...
brdf_rewri
Author | SHA1 | Date | |
---|---|---|---|
e569352f0b | |||
5b5de92890 | |||
0cdb90bdb8 | |||
ddc3a071f4 |
@ -4,6 +4,6 @@ in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
gl_FragDepth = 1.0;
|
||||
fragColor = vec4(0.0,0.0,0.0,1.0);
|
||||
gl_FragDepth = 0.0;
|
||||
}
|
||||
|
@ -4,5 +4,5 @@ in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
gl_FragDepth = 1.0;
|
||||
gl_FragDepth = 0.0;
|
||||
}
|
||||
|
@ -2,12 +2,10 @@
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
#ifdef _Clusters
|
||||
#include "std/clusters.glsl"
|
||||
#endif
|
||||
#ifdef _Irr
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
#include "std/sss.glsl"
|
||||
#endif
|
||||
@ -15,9 +13,26 @@
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
// Environment map
|
||||
uniform float envmapStrength;
|
||||
#ifdef _Irr
|
||||
uniform vec4 shirr[7];
|
||||
uniform float ambientIntensity;
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
#include "std/environment_sample.glsl"
|
||||
#include "std/light.glsl"
|
||||
|
||||
// Gbuffer
|
||||
//uniform sampler2D depthtex; // Raw depth
|
||||
uniform sampler2D gbufferD; // Depth (cheap)
|
||||
uniform sampler2D gbuffer0; // Normal/Metal
|
||||
uniform sampler2D gbuffer1; // Albedo
|
||||
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
uniform mat4 invVP;
|
||||
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
@ -39,10 +54,6 @@ uniform sampler3D voxelsSDF;
|
||||
uniform float clipmaps[10 * voxelgiClipmapCount];
|
||||
#endif
|
||||
|
||||
uniform float envmapStrength;
|
||||
#ifdef _Irr
|
||||
uniform vec4 shirr[7];
|
||||
#endif
|
||||
#ifdef _Brdf
|
||||
uniform sampler2D senvmapBrdf;
|
||||
#endif
|
||||
@ -62,11 +73,6 @@ uniform sampler2D ssaotex;
|
||||
uniform vec2 lightPlane;
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
//!uniform mat4 VP;
|
||||
uniform mat4 invVP;
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
//!uniform sampler2D texIES;
|
||||
#endif
|
||||
@ -96,10 +102,6 @@ uniform mat4 invVP;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
|
||||
#ifdef _Clusters
|
||||
uniform vec4 lightsArray[maxLights * 3];
|
||||
#ifdef _Spot
|
||||
@ -201,6 +203,7 @@ in vec3 viewRay;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0.0);
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||
|
||||
vec3 n;
|
||||
@ -215,13 +218,22 @@ void main() {
|
||||
|
||||
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 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
||||
vec3 envl = vec3(0.0);
|
||||
|
||||
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);
|
||||
// world-space position:
|
||||
float rawDepth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||
float clipZ = rawDepth * 2.0 - 1.0; // depth -> clip-space
|
||||
vec4 clipPos = vec4(texCoord * 2.0 - 1.0, clipZ, 1.0);
|
||||
vec4 worldPos = invVP * clipPos;
|
||||
vec3 p = worldPos.xyz / worldPos.w;
|
||||
vec3 v = normalize(eye - p);
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
// view-space vector for reflection
|
||||
vec3 viewPos = getPosView(viewRay, rawDepth, cameraProj);
|
||||
vec3 viewDir = normalize(-viewPos);
|
||||
|
||||
#ifdef _gbuffer2
|
||||
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
|
||||
@ -235,24 +247,17 @@ void main() {
|
||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
||||
#endif
|
||||
|
||||
// Envmap
|
||||
#ifdef _Irr
|
||||
// Sample ambient diffuse lighting
|
||||
vec3 ambient = sampleDiffuseEnvironment(n);
|
||||
|
||||
vec3 envl = shIrradiance(n, shirr);
|
||||
#ifdef _gbuffer2
|
||||
if (g2.b >= 0.5) {
|
||||
ambient = vec3(0.0); // Mask it if g2 says this surface wants no ambient lighting
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _gbuffer2
|
||||
if (g2.b < 0.5) {
|
||||
envl = envl;
|
||||
} else {
|
||||
envl = vec3(0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _EnvTex
|
||||
envl /= PI;
|
||||
#endif
|
||||
#else
|
||||
vec3 envl = vec3(0.0);
|
||||
fragColor.rgb += ambient * ambientIntensity;
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
@ -295,28 +300,37 @@ void main() {
|
||||
envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r;
|
||||
#endif
|
||||
|
||||
// if voxel GI isn't enabled, we fall back to SSR (SSR also processes indirect)
|
||||
#ifndef _VoxelGI
|
||||
fragColor.rgb = envl;
|
||||
fragColor.rgb += envl;
|
||||
#ifndef _SSR
|
||||
// if SSR is disabled, we fallback to simple environment texture
|
||||
vec3 fallbackEnvColor = sampleSpecularEnvironment(reflect(viewDir, n), roughness);
|
||||
fragColor.rgb += fallbackEnvColor;
|
||||
#endif
|
||||
#endif
|
||||
// Show voxels
|
||||
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
|
||||
// vec3 direction = vec3(0.0, 0.0, -1.0);
|
||||
// vec4 color = vec4(0.0f);
|
||||
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
|
||||
// vec3 point = origin + 0.005 * step * direction;
|
||||
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
|
||||
// }
|
||||
// fragColor.rgb += color.rgb;
|
||||
|
||||
// Show SSAO
|
||||
// fragColor.rgb = texture(ssaotex, texCoord).rrr;
|
||||
// show voxel GI
|
||||
#ifdef _VoxelGI
|
||||
// Show voxels
|
||||
vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
|
||||
vec3 direction = vec3(0.0, 0.0, -1.0);
|
||||
vec4 color = vec4(0.0f);
|
||||
for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
|
||||
vec3 point = origin + 0.005 * step * direction;
|
||||
color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
|
||||
}
|
||||
fragColor.rgb += color.rgb;
|
||||
#endif
|
||||
|
||||
// show SSAO
|
||||
#ifdef _SSAO
|
||||
// #ifdef _RTGI
|
||||
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
|
||||
// #else
|
||||
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
|
||||
// #endif
|
||||
fragColor.rgb = texture(ssaotex, texCoord).rrr;
|
||||
// #ifdef _RTGI
|
||||
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
|
||||
// #else
|
||||
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
#ifdef _EmissionShadeless
|
||||
@ -464,7 +478,8 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _Clusters
|
||||
float viewz = linearize(depth * 0.5 + 0.5, cameraProj);
|
||||
// compute depth for clustering: use the view-space Z component (linearized depth)
|
||||
float viewz = viewPos.z;
|
||||
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
|
||||
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
|
||||
|
||||
@ -508,6 +523,7 @@ void main() {
|
||||
#ifdef _MicroShadowing
|
||||
, occspec.x
|
||||
#endif
|
||||
// TODO: Cleanup. Probably broken
|
||||
#ifdef _SSRS
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
|
@ -49,10 +49,6 @@
|
||||
"link": "$brdf.png",
|
||||
"ifdef": ["_Brdf"]
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "envmapStrength",
|
||||
"link": "_envmapStrength"
|
||||
|
@ -23,8 +23,9 @@ void main() {
|
||||
// fullscreen triangle: http://de.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau
|
||||
// gl_Position = vec4((gl_VertexID % 2) * 4.0 - 1.0, (gl_VertexID / 2) * 4.0 - 1.0, 0.0, 1.0);
|
||||
|
||||
// NDC (at the back of cube)
|
||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
||||
// For reverse-Z, the “far” plane lives at NDC z = 0
|
||||
vec4 ndcFar = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||
vec4 v = invVP * ndcFar;
|
||||
v = vec4(invVP * v);
|
||||
v.xyz /= v.w;
|
||||
viewRay = v.xyz - eye;
|
||||
|
@ -19,8 +19,9 @@ void main() {
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
|
||||
// NDC (at the back of cube)
|
||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
||||
v = vec4(invP * v);
|
||||
// For reverse-Z, far plane sits at NDC z = 0
|
||||
vec4 clip = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||
vec4 v = invP * clip;
|
||||
// reconstruct a view‐space direction
|
||||
viewRay = vec3(v.xy / v.z, 1.0);
|
||||
}
|
||||
|
@ -1,21 +1,35 @@
|
||||
// TODO: Integrate with Blender UI
|
||||
// TODO: Option to disable cone tracing
|
||||
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/math.glsl"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0; // Normal, roughness
|
||||
uniform sampler2D gbuffer1; // basecol, spec
|
||||
uniform mat4 P;
|
||||
uniform mat3 V3;
|
||||
uniform vec2 cameraProj;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp9;
|
||||
uniform vec3 PPComp10;
|
||||
// Environment map
|
||||
uniform float envmapStrength;
|
||||
#ifdef _Irr
|
||||
uniform vec4 shirr[7];
|
||||
uniform float ambientIntensity;
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
#include "std/environment_sample.glsl"
|
||||
|
||||
uniform sampler2D tex; // Environment map
|
||||
//uniform sampler2D depthtex; // Full Depth buffer
|
||||
uniform sampler2D gbufferD; // Cheap Depth buffer
|
||||
uniform sampler2D gbuffer0; // Normal, roughness
|
||||
uniform sampler2D gbuffer1; // Base color, spec
|
||||
uniform mat4 P; // Projection matrix
|
||||
uniform mat3 V3; // View matrix
|
||||
uniform vec2 cameraProj; // Camera projection params
|
||||
uniform vec2 invScreenSize; // (1.0/width, 1.0/height)
|
||||
|
||||
const float ssrPrecision = 0.0; // 0.0 - 100.0 (user slider control)
|
||||
//const float rayThickness = 0.1; // TODO: Adds some thickness to prevent gaps
|
||||
uniform int ssrConetraceMode = 2; // 0 = no weighting, 1 = light, 2 = strong
|
||||
const int ssrConetraceTaps = 18; // Number of taps (higher = more precision)
|
||||
|
||||
in vec3 viewRay;
|
||||
in vec2 texCoord;
|
||||
@ -24,98 +38,214 @@ out vec4 fragColor;
|
||||
vec3 hitCoord;
|
||||
float depth;
|
||||
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||
const int baseBinarySearchSteps = 10; // Parameterize?
|
||||
const int baseMaxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||
|
||||
int dynamicBinarySearchSteps() {
|
||||
return int(mix(7.0, 20.0, clamp(ssrPrecision / 100.0, 0.0, 1.0)));
|
||||
}
|
||||
|
||||
int dynamicMaxSteps() {
|
||||
return int(mix(float(baseMaxSteps), 300.0, clamp(ssrPrecision / 100.0, 0.0, 1.0)));
|
||||
}
|
||||
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
vec4 clip = P * vec4(hit, 1.0);
|
||||
vec2 uv = clip.xy / clip.w;
|
||||
uv = uv * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
uv = clamp(uv, 0.0, 1.0);
|
||||
uv += invScreenSize * 0.5; // half-pixel offset
|
||||
return uv;
|
||||
}
|
||||
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
vec2 screenUV = getProjectedCoord(hit);
|
||||
float raw = textureLod(gbufferD, screenUV, 0.0).r;
|
||||
float sampledDepth = raw * 2.0 - 1.0;
|
||||
float linearSampledDepth = linearize(sampledDepth, cameraProj);
|
||||
|
||||
return linearSampledDepth - hit.z;
|
||||
}
|
||||
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
// Ugly discard of hits too far away
|
||||
#ifdef _CPostprocess
|
||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
||||
#else
|
||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
||||
#endif
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
float ddepth;
|
||||
for (int i = 0; i < dynamicBinarySearchSteps(); i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
|
||||
vec2 projectedCoord = getProjectedCoord(hitCoord);
|
||||
float pixelSize = length(fwidth(projectedCoord)) * 0.5;
|
||||
float epsilon = max(pixelSize * 10.0, 0.01);
|
||||
|
||||
if (abs(ddepth) > epsilon) return vec4(0.0);
|
||||
|
||||
hitCoord.xy = clamp(projectedCoord, 0.0, 1.0);
|
||||
|
||||
return vec4(projectedCoord, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
#endif
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
vec4 rayCast(vec3 dir, float roughness) {
|
||||
vec3 stepDir = normalize(dir);
|
||||
|
||||
// Apply small jitter if high precision
|
||||
if (ssrPrecision > 80.0 && roughness > 0.05) {
|
||||
stepDir = normalize(stepDir + vec3(rand2(texCoord), 0.0) * 0.01);
|
||||
}
|
||||
return vec4(0.0);
|
||||
|
||||
float distance = length(hitCoord - viewRay);
|
||||
float stepDivisor = mix(100.0, 300.0, clamp(ssrPrecision / 100.0, 0.0, 1.0));
|
||||
float stepSize = max(0.01, distance / stepDivisor);
|
||||
float maxStepSize = 0.1;
|
||||
|
||||
for (int i = 0; i < dynamicMaxSteps(); i++) {
|
||||
hitCoord += stepDir * stepSize;
|
||||
|
||||
vec2 projCoord = getProjectedCoord(hitCoord);
|
||||
float sampledDepth = textureLod(gbufferD, projCoord, 0.0).r;
|
||||
float depthTolerance = fwidth(sampledDepth) * 2.0; // Dynamic tolerance
|
||||
|
||||
if (getDeltaDepth(hitCoord) > depthTolerance) {
|
||||
return binarySearch(stepDir);
|
||||
}
|
||||
|
||||
stepSize = min(stepSize * 1.1, maxStepSize);
|
||||
}
|
||||
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
vec3 coneTraceApprox(vec3 reflDir, float roughness) {
|
||||
vec3 result = vec3(0.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
float randAngle = hash12(texCoord) * 6.2831853;
|
||||
mat2 rot = mat2(cos(randAngle), -sin(randAngle), sin(randAngle), cos(randAngle));
|
||||
|
||||
float coneSpread = roughness * 0.5; // widen based on roughness
|
||||
|
||||
for (int i = 0; i < ssrConetraceTaps; ++i) {
|
||||
float angle = float(i) / float(ssrConetraceTaps) * 6.2831853;
|
||||
vec2 offset = rot * vec2(cos(angle), sin(angle)) * coneSpread;
|
||||
vec3 sampleDir = normalize(reflDir + vec3(offset, 0.0));
|
||||
|
||||
float weight = 1.0;
|
||||
if (ssrConetraceMode == 1) {
|
||||
weight = pow(max(dot(reflDir, sampleDir), 0.0), 2.0); // Light cosine lobe
|
||||
}
|
||||
else if (ssrConetraceMode == 2) {
|
||||
weight = pow(max(dot(reflDir, sampleDir), 0.0), 8.0); // Strong GGX lobe
|
||||
}
|
||||
|
||||
// Approximate sampling by using tex at reflection direction
|
||||
vec2 envUV = envMapEquirect(sampleDir);
|
||||
vec3 sampleColor = textureLod(tex, envUV, 0.0).rgb;
|
||||
|
||||
result += sampleColor * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
return result / max(totalWeight, 0.0001);
|
||||
}
|
||||
|
||||
vec3 tangentSpaceGGX(vec3 N, float roughness) {
|
||||
float a = roughness * roughness;
|
||||
float phi = rand(texCoord) * 6.2831853;
|
||||
float cosTheta = sqrt((1.0 - rand(texCoord)) / (1.0 + (a * a - 1.0) * rand(texCoord)));
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
vec3 T = normalize(cross(N, vec3(0.0, 1.0, 0.0)));
|
||||
if (length(T) < 0.01) T = normalize(cross(N, vec3(1.0, 0.0, 0.0)));
|
||||
vec3 B = cross(N, T);
|
||||
|
||||
return normalize(T * cos(phi) * sinTheta + B * sin(phi) * sinTheta + N * cosTheta);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
// sample raw depth, bail if empty
|
||||
float dRaw = textureLod(gbufferD, texCoord, 0.0).r;
|
||||
if (dRaw == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
// convert to NDC z before reconstructing
|
||||
float d = dRaw * 2.0 - 1.0;
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 reflected = reflect(viewPos, viewNormal);
|
||||
hitCoord = viewPos;
|
||||
vec3 n = decode_oct(g0.rg);
|
||||
vec3 viewNormal = V3 * n;
|
||||
viewNormal = normalize(mix(viewNormal, normalize(-viewRay), 0.05)); // slightly bias the normal toward the view direction at glancing angles
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 viewDir = normalize(-viewPos);
|
||||
vec3 idealReflection = reflect(normalize(viewPos), viewNormal);
|
||||
hitCoord = viewPos;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
|
||||
// Apply GGX importance sampling in tangent space
|
||||
vec3 jitteredDir = tangentSpaceGGX(viewNormal, roughness);
|
||||
|
||||
// Blend based on roughness (0 = perfect mirror, 1 = fully scattered)
|
||||
vec3 dir = normalize(mix(idealReflection, jitteredDir, roughness));
|
||||
|
||||
vec4 coords = rayCast(dir, roughness);
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
|
||||
float reflectivity = 1.0 - roughness;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
// Postprocess mode intensity calculation...
|
||||
#else
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
|
||||
float intensity = 0.0;
|
||||
|
||||
if (coords.w > 0.0) {
|
||||
// Ray hit in screen-space
|
||||
intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor *
|
||||
clamp(-idealReflection.z, 0.0, 1.0) *
|
||||
clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0);
|
||||
}
|
||||
else if (roughness < 0.7) {
|
||||
// Ray miss, roughness low enough: do cone trace approximation
|
||||
vec3 coneColor = coneTraceApprox(idealReflection, roughness);
|
||||
vec3 envCol = sampleSpecularEnvironment(idealReflection, roughness);
|
||||
|
||||
coneColor = clamp(coneColor, 0.0, 1.0);
|
||||
envCol = clamp(envCol, 0.0, 1.0);
|
||||
|
||||
vec3 finalColor = mix(envCol, mix(envCol, coneColor, intensity), coords.w);
|
||||
fragColor.rgb = finalColor * 0.5; // match previous intensity scaling
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Ray miss, roughness too high: fallback to environment map
|
||||
vec3 fallbackEnvColor = sampleSpecularEnvironment(reflect(viewDir, n), roughness);
|
||||
fragColor.rgb = fallbackEnvColor;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// * max(ssrMinRayStep, -viewPos.z)
|
||||
vec4 coords = rayCast(dir);
|
||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb; // SSR reflection
|
||||
vec3 envCol = textureLod(tex, texCoord, 0.0).rgb; // Background environment
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
|
||||
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;
|
||||
#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;
|
||||
#endif
|
||||
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
reflCol = clamp(reflCol, 0.0, 1.0);
|
||||
fragColor.rgb = reflCol * intensity * 0.5;
|
||||
}
|
||||
envCol = clamp(envCol, 0.0, 1.0);
|
||||
|
||||
// Roughness-based fade (smoothstep)
|
||||
float roughFade = smoothstep(0.2, 0.7, roughness);
|
||||
float ssrVisibility = coords.w * (1.0 - roughFade);
|
||||
|
||||
// Blend SSR
|
||||
vec3 finalColor = mix(envCol, reflCol, ssrVisibility);
|
||||
|
||||
fragColor.rgb = finalColor;
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"name": "ssr_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"blend_mode": "replace",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
@ -23,14 +24,12 @@
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "PPComp9",
|
||||
"link": "_PPComp9",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
"name": "coneTraceMode",
|
||||
"link": "_coneTraceMode"
|
||||
},
|
||||
{
|
||||
"name": "PPComp10",
|
||||
"link": "_PPComp10",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
"name": "coneTraceTapCount",
|
||||
"link": "_coneTraceTapCount"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
|
@ -1,8 +1,10 @@
|
||||
#ifndef _BRDF_GLSL_
|
||||
#define _BRDF_GLSL_
|
||||
|
||||
// http://xlgames-inc.github.io/posts/improvedibl/
|
||||
// http://blog.selfshadow.com/publications/s2013-shading-course/
|
||||
// Constants
|
||||
//const float PI = 3.1415926535;
|
||||
|
||||
// Fresnel-Schlick with optimized exponential approximation
|
||||
vec3 f_schlick(const vec3 f0, const float vh) {
|
||||
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
|
||||
}
|
||||
@ -11,82 +13,11 @@ float v_smithschlick(const float nl, const float nv, const float a) {
|
||||
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
|
||||
}
|
||||
|
||||
//Uncorrelated masking/shadowing (info below) function
|
||||
//Because it is uncorrelated, G1(NdotL, a) gives us shadowing, and G1(NdotV, a) gives us masking function.
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g1_approx(const float NdotX, const float alpha)
|
||||
{
|
||||
return (2.0 * NdotX) * (1.0 / (NdotX * (2.0 - alpha) + alpha));
|
||||
}
|
||||
|
||||
//Uncorrelated masking-shadowing function
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g2_approx(const float NdotL, const float NdotV, const float alpha)
|
||||
{
|
||||
vec2 helper = (2.0 * vec2(NdotL, NdotV)) * (1.0 / (vec2(NdotL, NdotV) * (2.0 - alpha) + alpha));
|
||||
return max(helper.x * helper.y, 0.0); //This can go negative, let's fix that
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
return d_ggx(nh, a) * g2_approx(nl, nv, a) * f_schlick(f0, vh) / max(4.0 * nv, 1e-5); //NdotL cancels out later
|
||||
}
|
||||
|
||||
// John Hable - Optimizing GGX Shaders
|
||||
// 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);
|
||||
// F
|
||||
const float F_a = 1.0;
|
||||
float F_b = pow(1.0 - dotLH, 5.0);
|
||||
// V
|
||||
float vis;
|
||||
float k = alpha / 2.0;
|
||||
float k2 = k * k;
|
||||
float invK2 = 1.0 - k2;
|
||||
vis = 1.0 / (dotLH * dotLH * invK2 + k2);
|
||||
vec2 FV_helper = vec2((F_a - F_b) * vis, F_b * vis);
|
||||
|
||||
vec3 FV = f0 * FV_helper.x + FV_helper.y;
|
||||
vec3 specular = clamp(dotNL, 0.0, 1.0) * D * FV;
|
||||
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 * nl;
|
||||
}
|
||||
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
return mix(baseColor, vec3(0.0), metalness);
|
||||
}
|
||||
|
||||
vec3 surfaceF0(const vec3 baseColor, const float metalness) {
|
||||
return mix(vec3(0.04), baseColor, metalness);
|
||||
denom = max(denom * denom, 2e-6);
|
||||
return a2 / (PI * denom);
|
||||
}
|
||||
|
||||
float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||
@ -94,47 +25,64 @@ 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 specularBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness)
|
||||
{
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
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);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float VdotH = max(dot(V, H), 0.0);
|
||||
|
||||
float alpha = roughness * roughness;
|
||||
|
||||
float D = d_ggx(NdotH, alpha);
|
||||
float k = alpha / 2.0;
|
||||
float G_V = NdotV / (NdotV * (1.0 - k) + k + 1e-5);
|
||||
float G_L = NdotL / (NdotL * (1.0 - k) + k + 1e-5);
|
||||
float G = G_V * G_L;
|
||||
|
||||
vec3 F = f_schlick(F0, VdotH);
|
||||
|
||||
return F * D * G / max(4.0 * NdotL * NdotV, 1e-5);
|
||||
}
|
||||
|
||||
// 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 };
|
||||
// const vec4 c1 = { 1, 0.0425, 1.04, -0.04 };
|
||||
// vec4 r = Roughness * c0 + c1;
|
||||
// float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
|
||||
// return SpecularColor * AB.x + AB.y;
|
||||
// }
|
||||
// float EnvBRDFApproxNonmetal(float Roughness, float NoV) {
|
||||
// // Same as EnvBRDFApprox( 0.04, Roughness, NoV )
|
||||
// const vec2 c0 = { -1, -0.0275 };
|
||||
// const vec2 c1 = { 1, 0.0425 };
|
||||
// vec2 r = Roughness * c0 + c1;
|
||||
// return min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// }
|
||||
float D_Approx(const float Roughness, const float RoL) {
|
||||
float a = Roughness * Roughness;
|
||||
float a2 = a * a;
|
||||
float rcp_a2 = 1.0 / a2;//rcp(a2);
|
||||
// 0.5 / ln(2), 0.275 / ln(2)
|
||||
float c = 0.72134752 * rcp_a2 + 0.39674113;
|
||||
return rcp_a2 * exp2( c * RoL - c );
|
||||
vec3 burleyDiffuseBRDF(vec3 N, vec3 V, vec3 L, vec3 albedo, float roughness)
|
||||
{
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float LdotH = max(dot(L, normalize(L + V)), 0.0);
|
||||
|
||||
float FD90 = 0.5 + 2.0 * LdotH * LdotH * roughness;
|
||||
float FL = pow(1.0 - NdotL, 5.0);
|
||||
float FV = pow(1.0 - NdotV, 5.0);
|
||||
|
||||
float diffuse = (1.0 + (FD90 - 1.0) * FL) * (1.0 + (FD90 - 1.0) * FV);
|
||||
return albedo * (1.0 / PI) * diffuse * NdotL;
|
||||
}
|
||||
|
||||
// Energy-conserving material albedo (fades out for metals)
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
return baseColor * (1.0 - metalness);
|
||||
}
|
||||
|
||||
// Metal-aware F0 blending
|
||||
vec3 surfaceF0(vec3 baseColor, float metalness) {
|
||||
return mix(vec3(0.04), baseColor, metalness);
|
||||
}
|
||||
|
||||
// LUT-based approximation of IBL BRDF (Unreal-style)
|
||||
vec2 EnvBRDFApprox(float Roughness, float NoV) {
|
||||
const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022);
|
||||
const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04);
|
||||
vec4 r = Roughness * c0 + c1;
|
||||
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
||||
return vec2(-1.04, 1.04) * a004 + r.zw;
|
||||
}
|
||||
|
||||
vec3 IBLSpecularApprox(vec3 specColor, float roughness, float NoV) {
|
||||
vec2 brdf = EnvBRDFApprox(roughness, NoV);
|
||||
return specColor * brdf.x + brdf.y;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
28
leenkx/Shaders/std/environment_sample.glsl
Normal file
28
leenkx/Shaders/std/environment_sample.glsl
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef _ENVIRONMENT_SAMPLE_GLSL_
|
||||
#define _ENVIRONMENT_SAMPLE_GLSL_
|
||||
|
||||
// Sample diffuse ambient environment lighting (irradiance)
|
||||
vec3 sampleDiffuseEnvironment(vec3 normal) {
|
||||
#ifdef _Irr
|
||||
vec3 envl = shIrradiance(normal, shirr);
|
||||
|
||||
#ifdef _EnvTex
|
||||
envl /= PI;
|
||||
#endif
|
||||
|
||||
return envl;
|
||||
#else
|
||||
return vec3(0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Sample specular environment reflection (skybox or cubemap)
|
||||
vec3 sampleSpecularEnvironment(vec3 viewDir, float roughness) {
|
||||
#ifdef _EnvTex
|
||||
return textureLod(texEnvironment, viewDir, roughness * 8.0).rgb;
|
||||
#else
|
||||
return vec3(0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
#ifndef _GBUFFER_GLSL_
|
||||
#define _GBUFFER_GLSL_
|
||||
#include "std/math.glsl"
|
||||
|
||||
vec2 octahedronWrap(const vec2 v) {
|
||||
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
||||
@ -13,23 +14,17 @@ vec3 getNor(const vec2 enc) {
|
||||
return n;
|
||||
}
|
||||
|
||||
vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
float linearDepth = cameraProj.y / (cameraProj.x - depth);
|
||||
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
return viewRay * linearDepth;
|
||||
vec3 getPosView(const vec3 viewRay, float depth, vec2 cameraProj) {
|
||||
return viewRay * linearize(depth, cameraProj);
|
||||
}
|
||||
|
||||
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = eye + viewRay * (linearDepth / viewZDist);
|
||||
return wposition;
|
||||
vec3 getPos(const vec3 eye, mat3 invV, const vec3 viewRay, float depth, vec2 cameraProj) {
|
||||
vec3 pVS = viewRay * linearize(depth, cameraProj);
|
||||
return eye + invV * pVS; // invV == inverse of view-rotation
|
||||
}
|
||||
|
||||
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float linearDepth = linearize(depth, cameraProj);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = viewRay * (linearDepth / viewZDist);
|
||||
return wposition;
|
||||
@ -47,30 +42,34 @@ vec3 getPos2(const mat4 invVP, const float depth, const vec2 coord) {
|
||||
return pos.xyz;
|
||||
}
|
||||
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
|
||||
coord.y = 1.0 - coord.y;
|
||||
#else
|
||||
vec3 getPosView2(const mat4 invP, const float depth, const vec2 coord) {
|
||||
#endif
|
||||
//#if defined(HLSL) || defined(METAL)
|
||||
//vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
|
||||
// coord.y = 1.0 - coord.y;
|
||||
//#else
|
||||
vec3 getPosView2(mat4 invP, float depth, vec2 coord) {
|
||||
vec4 clip = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
vec4 view = invP * clip;
|
||||
return view.xyz / view.w;
|
||||
//#endif
|
||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
pos = invP * pos;
|
||||
pos.xyz /= pos.w;
|
||||
return pos.xyz;
|
||||
}
|
||||
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, vec2 coord) {
|
||||
coord.y = 1.0 - coord.y;
|
||||
#else
|
||||
// Reconstruct view-space position from inverse View×Proj
|
||||
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, const vec2 coord) {
|
||||
vec2 uv = coord;
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
pos = invVP * pos;
|
||||
pos.xyz /= pos.w;
|
||||
return pos.xyz - eye;
|
||||
vec4 clip = vec4(uv * 2.0 - 1.0, depth, 1.0);
|
||||
vec4 world = invVP * clip;
|
||||
world.xyz /= world.w;
|
||||
return world.xyz - eye;
|
||||
}
|
||||
|
||||
// Updated to support separate roughness/metalness storage
|
||||
float packFloat(const float f1, const float f2) {
|
||||
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
@ -80,7 +79,6 @@ vec2 unpackFloat(const float f) {
|
||||
}
|
||||
|
||||
float packFloat2(const float f1, const float f2) {
|
||||
// Higher f1 = less precise f2
|
||||
return floor(f1 * 255.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
|
||||
@ -101,24 +99,21 @@ vec3 decodeRGBM(const vec4 rgbm) {
|
||||
return rgbm.rgb * rgbm.a * maxRange;
|
||||
}
|
||||
|
||||
vec2 signNotZero(vec2 v)
|
||||
{
|
||||
vec2 signNotZero(vec2 v) {
|
||||
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||
}
|
||||
|
||||
vec2 encode_oct(vec3 v)
|
||||
{
|
||||
// Project the sphere onto the octahedron, and then onto the xy plane
|
||||
vec2 encode_oct(vec3 v) {
|
||||
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
|
||||
// Reflect the folds of the lower hemisphere over the diagonals
|
||||
return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p;
|
||||
}
|
||||
|
||||
vec3 decode_oct(vec2 e)
|
||||
{
|
||||
vec3 decode_oct(vec2 e) {
|
||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||
if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
|
||||
return normalize(v);
|
||||
if (v.z < 0.0) {
|
||||
v.xy = (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
||||
}
|
||||
return normalize(v);
|
||||
}
|
||||
|
||||
uint encNor(vec3 n) {
|
||||
@ -147,9 +142,6 @@ vec3 decNor(uint val) {
|
||||
return normal;
|
||||
}
|
||||
|
||||
/**
|
||||
Packs a float in [0, 1] and an integer in [0..15] into a single 16 bit float value.
|
||||
**/
|
||||
float packFloatInt16(const float f, const uint i) {
|
||||
const uint numBitFloat = 12;
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
@ -165,9 +157,8 @@ void unpackFloatInt16(const float val, out float f, out uint i) {
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
|
||||
const uint bitsValue = uint(val);
|
||||
|
||||
i = bitsValue >> numBitFloat;
|
||||
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@ -1,239 +1,241 @@
|
||||
#ifndef _LIGHT_GLSL_
|
||||
#define _LIGHT_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
#include "std/conetrace.glsl"
|
||||
//!uniform sampler2D voxels_shadows;
|
||||
#endif
|
||||
#ifdef _LTC
|
||||
#include "std/ltc.glsl"
|
||||
#endif
|
||||
#ifdef _LightIES
|
||||
#include "std/ies.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
#ifndef _LTC
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform samplerCube shadowMapPointTransparent[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[4];
|
||||
uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
uniform vec3 lightArea0;
|
||||
uniform vec3 lightArea1;
|
||||
uniform vec3 lightArea2;
|
||||
uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
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,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow, bool transparent
|
||||
#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]
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#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
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= lightCol;
|
||||
|
||||
#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
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef _LIGHT_GLSL_
|
||||
#define _LIGHT_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
#include "std/conetrace.glsl"
|
||||
//!uniform sampler2D voxels_shadows;
|
||||
#endif
|
||||
#ifdef _LTC
|
||||
#include "std/ltc.glsl"
|
||||
#endif
|
||||
#ifdef _LightIES
|
||||
#include "std/ies.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
#ifndef _LTC
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform samplerCube shadowMapPointTransparent[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[4];
|
||||
uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
uniform vec3 lightArea0;
|
||||
uniform vec3 lightArea1;
|
||||
uniform vec3 lightArea2;
|
||||
uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
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,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow, bool transparent
|
||||
#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]
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#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 F0 = surfaceF0(albedo, spec); // spec used as the metalness value
|
||||
|
||||
vec3 direct = burleyDiffuseBRDF(n, v, l, albedo, rough) * (1.0 - spec) +
|
||||
specularBRDF(n, v, l, f0, rough) * spec;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= lightCol;
|
||||
|
||||
#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
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7,6 +7,12 @@ float hash(const vec2 p) {
|
||||
return fract(sin(h) * 43758.5453123);
|
||||
}
|
||||
|
||||
float hash12(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
vec2 envMapEquirect(const vec3 normal) {
|
||||
const float PI = 3.1415926535;
|
||||
const float PI2 = PI * 2.0;
|
||||
@ -27,9 +33,9 @@ vec2 rand2(const vec2 coord) {
|
||||
return vec2(noiseX, noiseY);
|
||||
}
|
||||
|
||||
float linearize(const float depth, vec2 cameraProj) {
|
||||
// to viewz
|
||||
return cameraProj.y / (depth - cameraProj.x);
|
||||
float linearize(float depth, vec2 cameraProj) {
|
||||
return cameraProj.y / (cameraProj.x - max(depth, 1e-6));
|
||||
//return cameraProj.y / (cameraProj.x - depth);
|
||||
}
|
||||
|
||||
float attenuate(const float dist) {
|
||||
|
@ -234,7 +234,7 @@ class Inc {
|
||||
var shadowmap = getShadowMapAtlas(atlas, false);
|
||||
path.setTargetStream(shadowmap);
|
||||
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
|
||||
for (tile in atlas.activeTiles) {
|
||||
if (tile.light == null || !tile.light.visible || tile.light.culledLight
|
||||
@ -490,7 +490,7 @@ class Inc {
|
||||
for (i in 0...faces) {
|
||||
if (faces > 1) path.currentFace = i;
|
||||
path.setTarget(shadowmap);
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
if (l.data.raw.cast_shadow) {
|
||||
path.drawMeshes("shadowmap");
|
||||
}
|
||||
@ -1091,8 +1091,8 @@ class Inc {
|
||||
var near = camera.data.raw.near_plane;
|
||||
var far = camera.data.raw.far_plane;
|
||||
var v = new iron.math.Vec2();
|
||||
v.x = far / (far - near);
|
||||
v.y = (-far * near) / (far - near);
|
||||
v.x = 0.0;
|
||||
v.y = near;
|
||||
|
||||
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
|
||||
|
||||
@ -1166,9 +1166,8 @@ class Inc {
|
||||
var near = camera.data.raw.near_plane;
|
||||
var far = camera.data.raw.far_plane;
|
||||
var v = new iron.math.Vec2();
|
||||
v.x = far / (far - near);
|
||||
v.y = (-far * near) / (far - near);
|
||||
|
||||
v.x = 0.0;
|
||||
v.y = near;
|
||||
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
|
||||
|
||||
|
||||
@ -1244,8 +1243,8 @@ class Inc {
|
||||
var near = camera.data.raw.near_plane;
|
||||
var far = camera.data.raw.far_plane;
|
||||
var v = new iron.math.Vec2();
|
||||
v.x = far / (far - near);
|
||||
v.y = (-far * near) / (far - near);
|
||||
v.x = 0.0;
|
||||
v.y = near;
|
||||
|
||||
kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y);
|
||||
|
||||
|
@ -159,7 +159,7 @@ class RenderPathDeferred {
|
||||
#if rp_depth_texture
|
||||
{
|
||||
var t = new RenderTargetRaw();
|
||||
t.name = "depthtex";
|
||||
t.name = "gbufferD";
|
||||
t.width = 0;
|
||||
t.height = 0;
|
||||
t.displayp = Inc.getDisplayp();
|
||||
@ -451,11 +451,11 @@ class RenderPathDeferred {
|
||||
path.setTarget("gbuffer0"); // Only clear gbuffer0
|
||||
#if (rp_background == "Clear")
|
||||
{
|
||||
path.clearTarget(-1, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
}
|
||||
#else
|
||||
{
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
}
|
||||
#end
|
||||
|
||||
@ -1017,7 +1017,7 @@ class RenderPathDeferred {
|
||||
#if rp_overlays
|
||||
{
|
||||
path.setTarget(target);
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
path.drawMeshes("overlay");
|
||||
}
|
||||
#end
|
||||
@ -1086,6 +1086,8 @@ class RenderPathDeferred {
|
||||
path.setTarget("depthtex");
|
||||
path.bindTarget("_main", "tex");
|
||||
path.drawShader("shader_datas/copy_pass/copy_pass");
|
||||
path.drawShader("shader_datas/deferred_light/deferred_light.frag.glsl");
|
||||
path.drawShader("shader_datas/ssr_pass/ssr_pass.frag.glsl");
|
||||
|
||||
#if (!kha_opengl)
|
||||
path.setDepthFrom("gbuffer0", "tex"); // Re-bind depth
|
||||
|
@ -428,11 +428,11 @@ class RenderPathForward {
|
||||
|
||||
#if (rp_background == "Clear")
|
||||
{
|
||||
path.clearTarget(-1, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
}
|
||||
#else
|
||||
{
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
}
|
||||
#end
|
||||
|
||||
@ -703,7 +703,7 @@ class RenderPathForward {
|
||||
|
||||
#if rp_overlays
|
||||
{
|
||||
path.clearTarget(null, 1.0);
|
||||
path.clearTarget(null, 0.0);
|
||||
path.drawMeshes("overlay");
|
||||
}
|
||||
#end
|
||||
|
@ -571,10 +571,18 @@ class LnxRPListItem(bpy.types.PropertyGroup):
|
||||
update=assets.invalidate_shader_cache
|
||||
)
|
||||
lnx_motion_blur_intensity: FloatProperty(name="Intensity", default=1.0, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_precision: FloatProperty(name="Precision", default=0, min=0, max=100, subtype='PERCENTAGE', update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_ray_step: FloatProperty(name="Step", default=0.03, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_search_dist: FloatProperty(name="Search", default=5.0, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_search_dist: FloatProperty(name="Search", default=100.0, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_falloff_exp: FloatProperty(name="Falloff", default=5.0, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_jitter: FloatProperty(name="Jitter", default=0.6, update=assets.invalidate_shader_cache)
|
||||
#lnx_ssr_conetrace_mode: EnumProperty(
|
||||
# items=[(0, 'Fixed', 'Fastest', 'least quality'),
|
||||
# (1, 'Slightly Weighted', 'Samples weighted a bit for realism'),
|
||||
# (2, 'Weighted', 'Samples fully weighted for maximum realism'),
|
||||
# ],
|
||||
# name="Conetrace Mode", description="Fastest is fixed, best is weighted", default=2, update=assets.invalidate_shader_cache)
|
||||
lnx_ssr_conetrace_taps: IntProperty(name="Conetrace Taps", default=18, min=1, update=assets.invalidate_shader_cache)
|
||||
lnx_ss_refraction_ray_step: FloatProperty(name="Step", default=0.05, update=assets.invalidate_shader_cache)
|
||||
lnx_ss_refraction_search_dist: FloatProperty(name="Search", default=5.0, update=assets.invalidate_shader_cache)
|
||||
lnx_ss_refraction_falloff_exp: FloatProperty(name="Falloff", default=5.0, update=assets.invalidate_shader_cache)
|
||||
|
@ -1880,10 +1880,14 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel):
|
||||
col.prop(rpdat, 'lnx_ssr_half_res')
|
||||
col = col.column()
|
||||
col.enabled = rpdat.rp_ssr
|
||||
col.prop(rpdat, 'lnx_ssr_precision')
|
||||
col.prop(rpdat, 'lnx_ssr_ray_step')
|
||||
col.prop(rpdat, 'lnx_ssr_search_dist')
|
||||
col.prop(rpdat, 'lnx_ssr_falloff_exp')
|
||||
col.prop(rpdat, 'lnx_ssr_jitter')
|
||||
col = col.column()
|
||||
col.prop(rpdat, 'lnx_ssr_conetrace_taps')
|
||||
#col.prop(rpdat, 'lnx_ssr_conetrace_mode')
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
|
Reference in New Issue
Block a user