4 Commits

18 changed files with 702 additions and 571 deletions

View File

@ -4,6 +4,6 @@ in vec2 texCoord;
out vec4 fragColor; out vec4 fragColor;
void main() { void main() {
fragColor = vec4(0.0, 0.0, 0.0, 1.0); fragColor = vec4(0.0,0.0,0.0,1.0);
gl_FragDepth = 1.0; gl_FragDepth = 0.0;
} }

View File

@ -4,5 +4,5 @@ in vec2 texCoord;
out vec4 fragColor; out vec4 fragColor;
void main() { void main() {
gl_FragDepth = 1.0; gl_FragDepth = 0.0;
} }

View File

@ -2,12 +2,10 @@
#include "compiled.inc" #include "compiled.inc"
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#ifdef _Clusters #ifdef _Clusters
#include "std/clusters.glsl" #include "std/clusters.glsl"
#endif #endif
#ifdef _Irr
#include "std/shirr.glsl"
#endif
#ifdef _SSS #ifdef _SSS
#include "std/sss.glsl" #include "std/sss.glsl"
#endif #endif
@ -15,9 +13,26 @@
#include "std/ssrs.glsl" #include "std/ssrs.glsl"
#endif #endif
uniform sampler2D gbufferD; // Environment map
uniform sampler2D gbuffer0; uniform float envmapStrength;
uniform sampler2D gbuffer1; #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 #ifdef _gbuffer2
uniform sampler2D gbuffer2; uniform sampler2D gbuffer2;
@ -39,10 +54,6 @@ uniform sampler3D voxelsSDF;
uniform float clipmaps[10 * voxelgiClipmapCount]; uniform float clipmaps[10 * voxelgiClipmapCount];
#endif #endif
uniform float envmapStrength;
#ifdef _Irr
uniform vec4 shirr[7];
#endif
#ifdef _Brdf #ifdef _Brdf
uniform sampler2D senvmapBrdf; uniform sampler2D senvmapBrdf;
#endif #endif
@ -62,11 +73,6 @@ uniform sampler2D ssaotex;
uniform vec2 lightPlane; uniform vec2 lightPlane;
#endif #endif
#ifdef _SSRS
//!uniform mat4 VP;
uniform mat4 invVP;
#endif
#ifdef _LightIES #ifdef _LightIES
//!uniform sampler2D texIES; //!uniform sampler2D texIES;
#endif #endif
@ -96,10 +102,6 @@ uniform mat4 invVP;
#endif #endif
#endif #endif
uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
#ifdef _Clusters #ifdef _Clusters
uniform vec4 lightsArray[maxLights * 3]; uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot #ifdef _Spot
@ -201,6 +203,7 @@ in vec3 viewRay;
out vec4 fragColor; out vec4 fragColor;
void main() { void main() {
fragColor = vec4(0.0);
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
vec3 n; vec3 n;
@ -215,13 +218,22 @@ void main() {
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a); 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 f0 = surfaceF0(g1.rgb, metallic);
vec3 envl = vec3(0.0);
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; // world-space position:
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); float rawDepth = textureLod(gbufferD, texCoord, 0.0).r;
vec3 v = normalize(eye - p); float clipZ = rawDepth * 2.0 - 1.0; // depth -> clip-space
float dotNV = max(dot(n, v), 0.0); 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 #ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); 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; vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
#endif #endif
// Envmap
#ifdef _Irr #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 fragColor.rgb += ambient * ambientIntensity;
if (g2.b < 0.5) {
envl = envl;
} else {
envl = vec3(0.0);
}
#endif
#ifdef _EnvTex
envl /= PI;
#endif
#else
vec3 envl = vec3(0.0);
#endif #endif
#ifdef _Rad #ifdef _Rad
@ -295,28 +300,37 @@ void main() {
envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r; envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r;
#endif #endif
// if voxel GI isn't enabled, we fall back to SSR (SSR also processes indirect)
#ifndef _VoxelGI #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 #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 // show voxel GI
// fragColor.rgb = texture(ssaotex, texCoord).rrr; #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 _SSAO
// #ifdef _RTGI fragColor.rgb = texture(ssaotex, texCoord).rrr;
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb; // #ifdef _RTGI
// #else // fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; // #else
// #endif fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
// #endif
#endif #endif
#ifdef _EmissionShadeless #ifdef _EmissionShadeless
@ -464,7 +478,8 @@ void main() {
#endif #endif
#ifdef _Clusters #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 clusterI = getClusterI(texCoord, viewz, cameraPlane);
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
@ -508,6 +523,7 @@ void main() {
#ifdef _MicroShadowing #ifdef _MicroShadowing
, occspec.x , occspec.x
#endif #endif
// TODO: Cleanup. Probably broken
#ifdef _SSRS #ifdef _SSRS
, gbufferD, invVP, eye , gbufferD, invVP, eye
#endif #endif

View File

@ -49,10 +49,6 @@
"link": "$brdf.png", "link": "$brdf.png",
"ifdef": ["_Brdf"] "ifdef": ["_Brdf"]
}, },
{
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{ {
"name": "envmapStrength", "name": "envmapStrength",
"link": "_envmapStrength" "link": "_envmapStrength"

View File

@ -23,8 +23,9 @@ void main() {
// fullscreen triangle: http://de.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau // 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); // 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) // For reverse-Z, the “far” plane lives at NDC z = 0
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0); vec4 ndcFar = vec4(pos.x, pos.y, 0.0, 1.0);
vec4 v = invVP * ndcFar;
v = vec4(invVP * v); v = vec4(invVP * v);
v.xyz /= v.w; v.xyz /= v.w;
viewRay = v.xyz - eye; viewRay = v.xyz - eye;

View File

@ -19,8 +19,9 @@ void main() {
gl_Position = vec4(pos.xy, 0.0, 1.0); gl_Position = vec4(pos.xy, 0.0, 1.0);
// NDC (at the back of cube) // For reverse-Z, far plane sits at NDC z = 0
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0); vec4 clip = vec4(pos.x, pos.y, 0.0, 1.0);
v = vec4(invP * v); vec4 v = invP * clip;
// reconstruct a viewspace direction
viewRay = vec3(v.xy / v.z, 1.0); viewRay = vec3(v.xy / v.z, 1.0);
} }

View File

@ -1,21 +1,35 @@
// TODO: Integrate with Blender UI
// TODO: Option to disable cone tracing
#version 450 #version 450
#include "compiled.inc" #include "compiled.inc"
#include "std/math.glsl" #include "std/math.glsl"
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
uniform sampler2D tex; // Environment map
uniform sampler2D gbufferD; uniform float envmapStrength;
uniform sampler2D gbuffer0; // Normal, roughness #ifdef _Irr
uniform sampler2D gbuffer1; // basecol, spec uniform vec4 shirr[7];
uniform mat4 P; uniform float ambientIntensity;
uniform mat3 V3; #include "std/shirr.glsl"
uniform vec2 cameraProj;
#ifdef _CPostprocess
uniform vec3 PPComp9;
uniform vec3 PPComp10;
#endif #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 vec3 viewRay;
in vec2 texCoord; in vec2 texCoord;
@ -24,98 +38,214 @@ out vec4 fragColor;
vec3 hitCoord; vec3 hitCoord;
float depth; float depth;
const int numBinarySearchSteps = 7; const int baseBinarySearchSteps = 10; // Parameterize?
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist); 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) { vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0); vec4 clip = P * vec4(hit, 1.0);
projectedCoord.xy /= projectedCoord.w; vec2 uv = clip.xy / clip.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; uv = uv * 0.5 + 0.5;
#ifdef _InvY #ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y; uv.y = 1.0 - uv.y;
#endif #endif
return projectedCoord.xy; uv = clamp(uv, 0.0, 1.0);
uv += invScreenSize * 0.5; // half-pixel offset
return uv;
} }
float getDeltaDepth(const vec3 hit) { float getDeltaDepth(const vec3 hit) {
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0; vec2 screenUV = getProjectedCoord(hit);
vec3 viewPos = getPosView(viewRay, depth, cameraProj); float raw = textureLod(gbufferD, screenUV, 0.0).r;
return viewPos.z - hit.z; float sampledDepth = raw * 2.0 - 1.0;
float linearSampledDepth = linearize(sampledDepth, cameraProj);
return linearSampledDepth - hit.z;
} }
vec4 binarySearch(vec3 dir) { vec4 binarySearch(vec3 dir) {
float ddepth; float ddepth;
for (int i = 0; i < numBinarySearchSteps; i++) { for (int i = 0; i < dynamicBinarySearchSteps(); i++) {
dir *= 0.5; dir *= 0.5;
hitCoord -= dir; hitCoord -= dir;
ddepth = getDeltaDepth(hitCoord); ddepth = getDeltaDepth(hitCoord);
if (ddepth < 0.0) hitCoord += dir; if (ddepth < 0.0) hitCoord += dir;
} }
// Ugly discard of hits too far away
#ifdef _CPostprocess vec2 projectedCoord = getProjectedCoord(hitCoord);
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0); float pixelSize = length(fwidth(projectedCoord)) * 0.5;
#else float epsilon = max(pixelSize * 10.0, 0.01);
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
#endif if (abs(ddepth) > epsilon) return vec4(0.0);
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
hitCoord.xy = clamp(projectedCoord, 0.0, 1.0);
return vec4(projectedCoord, 0.0, 1.0);
} }
vec4 rayCast(vec3 dir) { vec4 rayCast(vec3 dir, float roughness) {
#ifdef _CPostprocess vec3 stepDir = normalize(dir);
dir *= PPComp9.x;
#else // Apply small jitter if high precision
dir *= ssrRayStep; if (ssrPrecision > 80.0 && roughness > 0.05) {
#endif stepDir = normalize(stepDir + vec3(rand2(texCoord), 0.0) * 0.01);
for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
} }
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() { 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); vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; } 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; float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; } if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
vec2 enc = g0.rg; // sample raw depth, bail if empty
vec3 n; float dRaw = textureLod(gbufferD, texCoord, 0.0).r;
n.z = 1.0 - abs(enc.x) - abs(enc.y); if (dRaw == 0.0) { fragColor.rgb = vec3(0.0); return; }
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); // convert to NDC z before reconstructing
n = normalize(n); float d = dRaw * 2.0 - 1.0;
vec3 viewNormal = V3 * n; vec3 n = decode_oct(g0.rg);
vec3 viewPos = getPosView(viewRay, d, cameraProj); vec3 viewNormal = V3 * n;
vec3 reflected = reflect(viewPos, viewNormal); viewNormal = normalize(mix(viewNormal, normalize(-viewRay), 0.05)); // slightly bias the normal toward the view direction at glancing angles
hitCoord = viewPos; vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 viewDir = normalize(-viewPos);
vec3 idealReflection = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos;
#ifdef _CPostprocess // Apply GGX importance sampling in tangent space
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0; 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 #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 #endif
// * max(ssrMinRayStep, -viewPos.z) vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb; // SSR reflection
vec4 coords = rayCast(dir); vec3 envCol = textureLod(tex, texCoord, 0.0).rgb; // Background environment
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); intensity = clamp(intensity, 0.0, 1.0);
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;
reflCol = clamp(reflCol, 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;
}

View File

@ -4,6 +4,7 @@
"name": "ssr_pass", "name": "ssr_pass",
"depth_write": false, "depth_write": false,
"compare_mode": "always", "compare_mode": "always",
"blend_mode": "replace",
"cull_mode": "none", "cull_mode": "none",
"links": [ "links": [
{ {
@ -23,14 +24,12 @@
"link": "_cameraPlaneProj" "link": "_cameraPlaneProj"
}, },
{ {
"name": "PPComp9", "name": "coneTraceMode",
"link": "_PPComp9", "link": "_coneTraceMode"
"ifdef": ["_CPostprocess"]
}, },
{ {
"name": "PPComp10", "name": "coneTraceTapCount",
"link": "_PPComp10", "link": "_coneTraceTapCount"
"ifdef": ["_CPostprocess"]
} }
], ],
"texture_params": [], "texture_params": [],

View File

@ -1,8 +1,10 @@
#ifndef _BRDF_GLSL_ #ifndef _BRDF_GLSL_
#define _BRDF_GLSL_ #define _BRDF_GLSL_
// http://xlgames-inc.github.io/posts/improvedibl/ // Constants
// http://blog.selfshadow.com/publications/s2013-shading-course/ //const float PI = 3.1415926535;
// Fresnel-Schlick with optimized exponential approximation
vec3 f_schlick(const vec3 f0, const float vh) { 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((-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)); 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 d_ggx(const float nh, const float a) {
float a2 = a * a; float a2 = a * a;
float denom = nh * nh * (a2 - 1.0) + 1.0; 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 */); denom = max(denom * denom, 2e-6);
return a2 * (1.0 / 3.1415926535) / denom; return a2 / (PI * 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);
} }
float getMipFromRoughness(const float roughness, const float numMipmaps) { float getMipFromRoughness(const float roughness, const float numMipmaps) {
@ -94,47 +25,64 @@ float getMipFromRoughness(const float roughness, const float numMipmaps) {
return roughness * numMipmaps; return roughness * numMipmaps;
} }
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) { vec3 specularBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness)
if(dotNL < 0.0 || dotNV < 0.0) { {
return 0.0; vec3 H = normalize(V + L);
}
// fiberDirection - parse from rotation
// shinyParallel - roughness
// shinyPerpendicular - anisotropy
vec3 fiberParallel = normalize(fiberDirection); float NdotL = max(dot(N, L), 0.0);
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection)); float NdotV = max(dot(N, V), 0.0);
float dotXH = dot(fiberParallel, H); float NdotH = max(dot(N, H), 0.0);
float dotYH = dot(fiberPerpendicular, H); float VdotH = max(dot(V, H), 0.0);
const float PI = 3.1415926535;
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular); float alpha = roughness * roughness;
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 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 burleyDiffuseBRDF(vec3 N, vec3 V, vec3 L, vec3 albedo, float roughness)
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) { {
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 }; float NdotL = max(dot(N, L), 0.0);
// const vec4 c1 = { 1, 0.0425, 1.04, -0.04 }; float NdotV = max(dot(N, V), 0.0);
// vec4 r = Roughness * c0 + c1; float LdotH = max(dot(L, normalize(L + V)), 0.0);
// 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; float FD90 = 0.5 + 2.0 * LdotH * LdotH * roughness;
// return SpecularColor * AB.x + AB.y; float FL = pow(1.0 - NdotL, 5.0);
// } float FV = pow(1.0 - NdotV, 5.0);
// float EnvBRDFApproxNonmetal(float Roughness, float NoV) {
// // Same as EnvBRDFApprox( 0.04, Roughness, NoV ) float diffuse = (1.0 + (FD90 - 1.0) * FL) * (1.0 + (FD90 - 1.0) * FV);
// const vec2 c0 = { -1, -0.0275 }; return albedo * (1.0 / PI) * diffuse * NdotL;
// 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; // Energy-conserving material albedo (fades out for metals)
// } vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
float D_Approx(const float Roughness, const float RoL) { return baseColor * (1.0 - metalness);
float a = Roughness * Roughness; }
float a2 = a * a;
float rcp_a2 = 1.0 / a2;//rcp(a2); // Metal-aware F0 blending
// 0.5 / ln(2), 0.275 / ln(2) vec3 surfaceF0(vec3 baseColor, float metalness) {
float c = 0.72134752 * rcp_a2 + 0.39674113; return mix(vec3(0.04), baseColor, metalness);
return rcp_a2 * exp2( c * RoL - c ); }
// 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 #endif

View 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

View File

@ -1,5 +1,6 @@
#ifndef _GBUFFER_GLSL_ #ifndef _GBUFFER_GLSL_
#define _GBUFFER_GLSL_ #define _GBUFFER_GLSL_
#include "std/math.glsl"
vec2 octahedronWrap(const vec2 v) { 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)); 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; return n;
} }
vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) { vec3 getPosView(const vec3 viewRay, float depth, vec2 cameraProj) {
float linearDepth = cameraProj.y / (cameraProj.x - depth); return viewRay * linearize(depth, cameraProj);
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
return viewRay * linearDepth;
} }
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) { vec3 getPos(const vec3 eye, mat3 invV, const vec3 viewRay, float depth, vec2 cameraProj) {
// eyeLook, viewRay should be normalized vec3 pVS = viewRay * linearize(depth, cameraProj);
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x); return eye + invV * pVS; // invV == inverse of view-rotation
float viewZDist = dot(eyeLook, viewRay);
vec3 wposition = eye + viewRay * (linearDepth / viewZDist);
return wposition;
} }
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) { vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
// eyeLook, viewRay should be normalized float linearDepth = linearize(depth, cameraProj);
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
float viewZDist = dot(eyeLook, viewRay); float viewZDist = dot(eyeLook, viewRay);
vec3 wposition = viewRay * (linearDepth / viewZDist); vec3 wposition = viewRay * (linearDepth / viewZDist);
return wposition; return wposition;
@ -47,30 +42,34 @@ vec3 getPos2(const mat4 invVP, const float depth, const vec2 coord) {
return pos.xyz; return pos.xyz;
} }
#if defined(HLSL) || defined(METAL) //#if defined(HLSL) || defined(METAL)
vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) { //vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
coord.y = 1.0 - coord.y; // coord.y = 1.0 - coord.y;
#else //#else
vec3 getPosView2(const mat4 invP, const float depth, const vec2 coord) { vec3 getPosView2(mat4 invP, float depth, vec2 coord) {
#endif 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); vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
pos = invP * pos; pos = invP * pos;
pos.xyz /= pos.w; pos.xyz /= pos.w;
return pos.xyz; return pos.xyz;
} }
#if defined(HLSL) || defined(METAL) // Reconstruct view-space position from inverse View×Proj
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, vec2 coord) {
coord.y = 1.0 - coord.y;
#else
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, const vec2 coord) { 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 #endif
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0); vec4 clip = vec4(uv * 2.0 - 1.0, depth, 1.0);
pos = invVP * pos; vec4 world = invVP * clip;
pos.xyz /= pos.w; world.xyz /= world.w;
return pos.xyz - eye; return world.xyz - eye;
} }
// Updated to support separate roughness/metalness storage
float packFloat(const float f1, const float f2) { float packFloat(const float f1, const float f2) {
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0); 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) { 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); 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; 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); return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
} }
vec2 encode_oct(vec3 v) vec2 encode_oct(vec3 v) {
{
// Project the sphere onto the octahedron, and then onto the xy plane
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z))); 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; 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)); 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); if (v.z < 0.0) {
return normalize(v); 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) { uint encNor(vec3 n) {
@ -147,9 +142,6 @@ vec3 decNor(uint val) {
return normal; 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) { float packFloatInt16(const float f, const uint i) {
const uint numBitFloat = 12; const uint numBitFloat = 12;
const float maxValFloat = float((1 << numBitFloat) - 1); 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 float maxValFloat = float((1 << numBitFloat) - 1);
const uint bitsValue = uint(val); const uint bitsValue = uint(val);
i = bitsValue >> numBitFloat; i = bitsValue >> numBitFloat;
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat; f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
} }
#endif #endif

View File

@ -1,239 +1,241 @@
#ifndef _LIGHT_GLSL_ #ifndef _LIGHT_GLSL_
#define _LIGHT_GLSL_ #define _LIGHT_GLSL_
#include "compiled.inc" #include "compiled.inc"
#include "std/brdf.glsl" #include "std/brdf.glsl"
#include "std/math.glsl" #include "std/math.glsl"
#ifdef _ShadowMap #ifdef _ShadowMap
#include "std/shadows.glsl" #include "std/shadows.glsl"
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
//!uniform sampler2D voxels_shadows; //!uniform sampler2D voxels_shadows;
#endif #endif
#ifdef _LTC #ifdef _LTC
#include "std/ltc.glsl" #include "std/ltc.glsl"
#endif #endif
#ifdef _LightIES #ifdef _LightIES
#include "std/ies.glsl" #include "std/ies.glsl"
#endif #endif
#ifdef _SSRS #ifdef _SSRS
#include "std/ssrs.glsl" #include "std/ssrs.glsl"
#endif #endif
#ifdef _Spot #ifdef _Spot
#include "std/light_common.glsl" #include "std/light_common.glsl"
#endif #endif
#ifdef _ShadowMap #ifdef _ShadowMap
#ifdef _SinglePoint #ifdef _SinglePoint
#ifdef _Spot #ifdef _Spot
#ifndef _LTC #ifndef _LTC
uniform sampler2DShadow shadowMapSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
uniform sampler2D shadowMapSpotTransparent[1]; uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1]; uniform mat4 LWVPSpot[1];
#endif #endif
#else #else
uniform samplerCubeShadow shadowMapPoint[1]; uniform samplerCubeShadow shadowMapPoint[1];
uniform samplerCube shadowMapPointTransparent[1]; uniform samplerCube shadowMapPointTransparent[1];
uniform vec2 lightProj; uniform vec2 lightProj;
#endif #endif
#endif #endif
#ifdef _Clusters #ifdef _Clusters
#ifdef _SingleAtlas #ifdef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlas; //!uniform sampler2DShadow shadowMapAtlas;
//!uniform sampler2D shadowMapAtlasTransparent; //!uniform sampler2D shadowMapAtlasTransparent;
#endif #endif
uniform vec2 lightProj; uniform vec2 lightProj;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint; uniform sampler2DShadow shadowMapAtlasPoint;
uniform sampler2D shadowMapAtlasPointTransparent; uniform sampler2D shadowMapAtlasPointTransparent;
#endif #endif
#else #else
uniform samplerCubeShadow shadowMapPoint[4]; uniform samplerCubeShadow shadowMapPoint[4];
uniform samplerCube shadowMapPointTransparent[4]; uniform samplerCube shadowMapPointTransparent[4];
#endif #endif
#ifdef _Spot #ifdef _Spot
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSpot; uniform sampler2DShadow shadowMapAtlasSpot;
uniform sampler2D shadowMapAtlasSpotTransparent; uniform sampler2D shadowMapAtlasSpotTransparent;
#endif #endif
#else #else
uniform sampler2DShadow shadowMapSpot[4]; uniform sampler2DShadow shadowMapSpot[4];
uniform sampler2D shadowMapSpotTransparent[4]; uniform sampler2D shadowMapSpotTransparent[4];
#endif #endif
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
#endif #endif
#ifdef _LTC #ifdef _LTC
uniform vec3 lightArea0; uniform vec3 lightArea0;
uniform vec3 lightArea1; uniform vec3 lightArea1;
uniform vec3 lightArea2; uniform vec3 lightArea2;
uniform vec3 lightArea3; uniform vec3 lightArea3;
uniform sampler2D sltcMat; uniform sampler2D sltcMat;
uniform sampler2D sltcMag; uniform sampler2D sltcMag;
#ifdef _ShadowMap #ifdef _ShadowMap
#ifndef _Spot #ifndef _Spot
#ifdef _SinglePoint #ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
uniform sampler2D shadowMapSpotTransparent[1]; uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1]; uniform mat4 LWVPSpot[1];
#endif #endif
#ifdef _Clusters #ifdef _Clusters
uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
#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 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 const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap #ifdef _ShadowMap
, int index, float bias, bool receiveShadow, bool transparent , int index, float bias, bool receiveShadow, bool transparent
#endif #endif
#ifdef _Spot #ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
#endif #endif
#ifdef _MicroShadowing #ifdef _MicroShadowing
, float occ , float occ
#endif #endif
#ifdef _SSRS #ifdef _SSRS
, sampler2D gbufferD, mat4 invVP, vec3 eye , sampler2D gbufferD, mat4 invVP, vec3 eye
#endif #endif
) { ) {
vec3 ld = lp - p; vec3 ld = lp - p;
vec3 l = normalize(ld); vec3 l = normalize(ld);
vec3 h = normalize(v + l); vec3 h = normalize(v + l);
float dotNH = max(0.0, dot(n, h)); float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h)); float dotVH = max(0.0, dot(v, h));
float dotNL = max(0.0, dot(n, l)); float dotNL = max(0.0, dot(n, l));
#ifdef _LTC #ifdef _LTC
float theta = acos(dotNV); float theta = acos(dotNV);
vec2 tuv = vec2(rough, theta / (0.5 * PI)); vec2 tuv = vec2(rough, theta / (0.5 * PI));
tuv = tuv * LUT_SCALE + LUT_BIAS; tuv = tuv * LUT_SCALE + LUT_BIAS;
vec4 t = textureLod(sltcMat, tuv, 0.0); vec4 t = textureLod(sltcMat, tuv, 0.0);
mat3 invM = mat3( mat3 invM = mat3(
vec3(1.0, 0.0, t.y), vec3(1.0, 0.0, t.y),
vec3(0.0, t.z, 0.0), vec3(0.0, t.z, 0.0),
vec3(t.w, 0.0, t.x)); vec3(t.w, 0.0, t.x));
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
ltcspec *= textureLod(sltcMag, tuv, 0.0).a; ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
#else #else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + vec3 F0 = surfaceF0(albedo, spec); // spec used as the metalness value
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif vec3 direct = burleyDiffuseBRDF(n, v, l, albedo, rough) * (1.0 - spec) +
specularBRDF(n, v, l, f0, rough) * spec;
direct *= attenuate(distance(p, lp)); #endif
direct *= lightCol;
direct *= attenuate(distance(p, lp));
#ifdef _MicroShadowing direct *= lightCol;
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#endif #ifdef _MicroShadowing
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#ifdef _SSRS #endif
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#endif #ifdef _SSRS
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#ifdef _VoxelShadow #endif
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
#endif #ifdef _VoxelShadow
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
#ifdef _LTC #endif
#ifdef _ShadowMap
if (receiveShadow) { #ifdef _LTC
#ifdef _SinglePoint #ifdef _ShadowMap
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); if (receiveShadow) {
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); #ifdef _SinglePoint
#endif vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
#ifdef _Clusters direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); #endif
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); #ifdef _Clusters
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
#endif 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 #endif
return direct;
#ifdef _Spot #endif
if (isSpot) {
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); #ifdef _Spot
if (isSpot) {
#ifdef _ShadowMap direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
if (receiveShadow) {
#ifdef _SinglePoint #ifdef _ShadowMap
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); if (receiveShadow) {
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); #ifdef _SinglePoint
#endif vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
#ifdef _Clusters direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); #endif
#ifdef _ShadowMapAtlas #ifdef _Clusters
direct *= shadowTest( vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifndef _SingleAtlas #ifdef _ShadowMapAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent direct *= shadowTest(
#else #ifndef _SingleAtlas
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#endif #else
, lPos.xyz / lPos.w, bias, transparent shadowMapAtlas, shadowMapAtlasTransparent
); #endif
#else , lPos.xyz / lPos.w, bias, transparent
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
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
} #endif
#endif #endif
return direct; }
} #endif
#endif return direct;
}
#ifdef _LightIES #endif
direct *= iesAttenuation(-l);
#endif #ifdef _LightIES
direct *= iesAttenuation(-l);
#ifdef _ShadowMap #endif
if (receiveShadow) {
#ifdef _SinglePoint #ifdef _ShadowMap
#ifndef _Spot if (receiveShadow) {
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); #ifdef _SinglePoint
#endif #ifndef _Spot
#endif direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
#ifdef _Clusters #endif
#ifdef _ShadowMapAtlas #endif
direct *= PCFFakeCube( #ifdef _Clusters
#ifndef _SingleAtlas #ifdef _ShadowMapAtlas
shadowMapAtlasPoint, shadowMapAtlasPointTransparent direct *= PCFFakeCube(
#else #ifndef _SingleAtlas
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlasPoint, shadowMapAtlasPointTransparent
#endif #else
, ld, -l, bias, lightProj, n, index, transparent shadowMapAtlas, shadowMapAtlasTransparent
); #endif
#else , ld, -l, bias, lightProj, n, index, transparent
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
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
#endif else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
#endif else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
} #endif
#endif #endif
}
return direct; #endif
}
return direct;
#endif }
#endif

View File

@ -7,6 +7,12 @@ float hash(const vec2 p) {
return fract(sin(h) * 43758.5453123); 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) { vec2 envMapEquirect(const vec3 normal) {
const float PI = 3.1415926535; const float PI = 3.1415926535;
const float PI2 = PI * 2.0; const float PI2 = PI * 2.0;
@ -27,9 +33,9 @@ vec2 rand2(const vec2 coord) {
return vec2(noiseX, noiseY); return vec2(noiseX, noiseY);
} }
float linearize(const float depth, vec2 cameraProj) { float linearize(float depth, vec2 cameraProj) {
// to viewz return cameraProj.y / (cameraProj.x - max(depth, 1e-6));
return cameraProj.y / (depth - cameraProj.x); //return cameraProj.y / (cameraProj.x - depth);
} }
float attenuate(const float dist) { float attenuate(const float dist) {

View File

@ -234,7 +234,7 @@ class Inc {
var shadowmap = getShadowMapAtlas(atlas, false); var shadowmap = getShadowMapAtlas(atlas, false);
path.setTargetStream(shadowmap); path.setTargetStream(shadowmap);
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
for (tile in atlas.activeTiles) { for (tile in atlas.activeTiles) {
if (tile.light == null || !tile.light.visible || tile.light.culledLight if (tile.light == null || !tile.light.visible || tile.light.culledLight
@ -490,7 +490,7 @@ class Inc {
for (i in 0...faces) { for (i in 0...faces) {
if (faces > 1) path.currentFace = i; if (faces > 1) path.currentFace = i;
path.setTarget(shadowmap); path.setTarget(shadowmap);
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
if (l.data.raw.cast_shadow) { if (l.data.raw.cast_shadow) {
path.drawMeshes("shadowmap"); path.drawMeshes("shadowmap");
} }
@ -1091,8 +1091,8 @@ class Inc {
var near = camera.data.raw.near_plane; var near = camera.data.raw.near_plane;
var far = camera.data.raw.far_plane; var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2(); var v = new iron.math.Vec2();
v.x = far / (far - near); v.x = 0.0;
v.y = (-far * near) / (far - near); v.y = near;
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
@ -1166,9 +1166,8 @@ class Inc {
var near = camera.data.raw.near_plane; var near = camera.data.raw.near_plane;
var far = camera.data.raw.far_plane; var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2(); var v = new iron.math.Vec2();
v.x = far / (far - near); v.x = 0.0;
v.y = (-far * near) / (far - near); v.y = near;
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
@ -1244,8 +1243,8 @@ class Inc {
var near = camera.data.raw.near_plane; var near = camera.data.raw.near_plane;
var far = camera.data.raw.far_plane; var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2(); var v = new iron.math.Vec2();
v.x = far / (far - near); v.x = 0.0;
v.y = (-far * near) / (far - near); v.y = near;
kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y); kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y);

View File

@ -159,7 +159,7 @@ class RenderPathDeferred {
#if rp_depth_texture #if rp_depth_texture
{ {
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "depthtex"; t.name = "gbufferD";
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
@ -451,11 +451,11 @@ class RenderPathDeferred {
path.setTarget("gbuffer0"); // Only clear gbuffer0 path.setTarget("gbuffer0"); // Only clear gbuffer0
#if (rp_background == "Clear") #if (rp_background == "Clear")
{ {
path.clearTarget(-1, 1.0); path.clearTarget(null, 0.0);
} }
#else #else
{ {
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
} }
#end #end
@ -1017,7 +1017,7 @@ class RenderPathDeferred {
#if rp_overlays #if rp_overlays
{ {
path.setTarget(target); path.setTarget(target);
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
path.drawMeshes("overlay"); path.drawMeshes("overlay");
} }
#end #end
@ -1086,6 +1086,8 @@ class RenderPathDeferred {
path.setTarget("depthtex"); path.setTarget("depthtex");
path.bindTarget("_main", "tex"); path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass"); 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) #if (!kha_opengl)
path.setDepthFrom("gbuffer0", "tex"); // Re-bind depth path.setDepthFrom("gbuffer0", "tex"); // Re-bind depth

View File

@ -428,11 +428,11 @@ class RenderPathForward {
#if (rp_background == "Clear") #if (rp_background == "Clear")
{ {
path.clearTarget(-1, 1.0); path.clearTarget(null, 0.0);
} }
#else #else
{ {
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
} }
#end #end
@ -703,7 +703,7 @@ class RenderPathForward {
#if rp_overlays #if rp_overlays
{ {
path.clearTarget(null, 1.0); path.clearTarget(null, 0.0);
path.drawMeshes("overlay"); path.drawMeshes("overlay");
} }
#end #end

View File

@ -571,10 +571,18 @@ class LnxRPListItem(bpy.types.PropertyGroup):
update=assets.invalidate_shader_cache update=assets.invalidate_shader_cache
) )
lnx_motion_blur_intensity: FloatProperty(name="Intensity", default=1.0, 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_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_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_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_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_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) lnx_ss_refraction_falloff_exp: FloatProperty(name="Falloff", default=5.0, update=assets.invalidate_shader_cache)

View File

@ -1880,10 +1880,14 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel):
col.prop(rpdat, 'lnx_ssr_half_res') col.prop(rpdat, 'lnx_ssr_half_res')
col = col.column() col = col.column()
col.enabled = rpdat.rp_ssr col.enabled = rpdat.rp_ssr
col.prop(rpdat, 'lnx_ssr_precision')
col.prop(rpdat, 'lnx_ssr_ray_step') col.prop(rpdat, 'lnx_ssr_ray_step')
col.prop(rpdat, 'lnx_ssr_search_dist') col.prop(rpdat, 'lnx_ssr_search_dist')
col.prop(rpdat, 'lnx_ssr_falloff_exp') col.prop(rpdat, 'lnx_ssr_falloff_exp')
col.prop(rpdat, 'lnx_ssr_jitter') 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() layout.separator()
col = layout.column() col = layout.column()