ADD: Docs and shader optim
This commit is contained in:
@@ -10,10 +10,11 @@ void main()
|
||||
{
|
||||
// Reconstruct world-space direction from screen UV
|
||||
vec2 ndc = inUV * 2.0 - 1.0; // [-1,1]
|
||||
vec4 clip = vec4(ndc, 1.0, 1.0);
|
||||
vec4 vpos = inverse(sceneData.proj) * clip;
|
||||
vec3 viewDir = normalize(vpos.xyz / max(vpos.w, 1e-6));
|
||||
vec3 worldDir = normalize((inverse(sceneData.view) * vec4(viewDir, 0.0)).xyz);
|
||||
|
||||
// Avoid per-pixel matrix inverses. With a perspective projection, a view-space ray can be
|
||||
// reconstructed directly from the projection diagonal and then rotated to world space.
|
||||
vec3 viewDir = normalize(vec3(ndc.x / sceneData.proj[0][0], ndc.y / sceneData.proj[1][1], -1.0));
|
||||
vec3 worldDir = normalize(transpose(mat3(sceneData.view)) * viewDir);
|
||||
|
||||
vec2 uv = dir_to_equirect(worldDir);
|
||||
// Sample a dedicated background environment map when available.
|
||||
|
||||
@@ -35,6 +35,17 @@ const float SHADOW_MIN_BIAS = 1e-5;
|
||||
const float SHADOW_RAY_TMIN = 0.02;// start a bit away from the surface
|
||||
const float SHADOW_RAY_ORIGIN_BIAS = 0.01;// world units
|
||||
|
||||
vec3 getCameraWorldPosition()
|
||||
{
|
||||
// view = [ R^T -R^T*C ]
|
||||
// [ 0 1 ]
|
||||
// => C = -R * T, where T is view[3].xyz and R = transpose(mat3(view))
|
||||
mat3 rotT = mat3(sceneData.view);
|
||||
mat3 rot = transpose(rotT);
|
||||
vec3 T = sceneData.view[3].xyz;
|
||||
return -rot * T;
|
||||
}
|
||||
|
||||
float hash12(vec2 p)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
@@ -290,7 +301,7 @@ void main(){
|
||||
float ao = extraSample.x;
|
||||
vec3 emissive = extraSample.yzw;
|
||||
|
||||
vec3 camPos = vec3(inverse(sceneData.view)[3]);
|
||||
vec3 camPos = getCameraWorldPosition();
|
||||
vec3 V = normalize(camPos - pos);
|
||||
|
||||
// Directional sun term using evaluate_brdf + cascaded shadowing
|
||||
|
||||
@@ -27,6 +27,17 @@ const float SHADOW_RPDB_SCALE = 1.0;
|
||||
// Minimum clamp to keep a tiny bias even on perpendicular receivers
|
||||
const float SHADOW_MIN_BIAS = 1e-5;
|
||||
|
||||
vec3 getCameraWorldPosition()
|
||||
{
|
||||
// view = [ R^T -R^T*C ]
|
||||
// [ 0 1 ]
|
||||
// => C = -R * T, where T is view[3].xyz and R = transpose(mat3(view))
|
||||
mat3 rotT = mat3(sceneData.view);
|
||||
mat3 rot = transpose(rotT);
|
||||
vec3 T = sceneData.view[3].xyz;
|
||||
return -rot * T;
|
||||
}
|
||||
|
||||
float hash12(vec2 p)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
@@ -219,7 +230,7 @@ void main(){
|
||||
float ao = extraSample.x;
|
||||
vec3 emissive = extraSample.yzw;
|
||||
|
||||
vec3 camPos = vec3(inverse(sceneData.view)[3]);
|
||||
vec3 camPos = getCameraWorldPosition();
|
||||
vec3 V = normalize(camPos - pos);
|
||||
|
||||
// Directional sun term using evaluate_brdf + cascaded shadowing
|
||||
|
||||
@@ -30,6 +30,7 @@ layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
layout(push_constant) uniform constants
|
||||
{
|
||||
mat4 render_matrix;
|
||||
mat3 normal_matrix;
|
||||
VertexBuffer vertexBuffer;
|
||||
uint objectID;
|
||||
} PushConstants;
|
||||
|
||||
@@ -13,6 +13,17 @@ layout (location = 4) in vec4 inTangent;
|
||||
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
vec3 getCameraWorldPosition()
|
||||
{
|
||||
// view = [ R^T -R^T*C ]
|
||||
// [ 0 1 ]
|
||||
// => C = -R * T, where T is view[3].xyz and R = transpose(mat3(view))
|
||||
mat3 rotT = mat3(sceneData.view);
|
||||
mat3 rot = transpose(rotT);
|
||||
vec3 T = sceneData.view[3].xyz;
|
||||
return -rot * T;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Base color with material factor and texture
|
||||
@@ -43,7 +54,7 @@ void main()
|
||||
vec3 T = normalize(inTangent.xyz);
|
||||
vec3 B = normalize(cross(Nn, T)) * inTangent.w;
|
||||
vec3 N = normalize(T * Nm.x + B * Nm.y + Nn * Nm.z);
|
||||
vec3 camPos = vec3(inverse(sceneData.view)[3]);
|
||||
vec3 camPos = getCameraWorldPosition();
|
||||
vec3 V = normalize(camPos - inWorldPos);
|
||||
|
||||
// Directional sun term (no shadows in forward path)
|
||||
|
||||
@@ -29,6 +29,7 @@ layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
layout(push_constant) uniform constants
|
||||
{
|
||||
mat4 render_matrix;
|
||||
mat3 normal_matrix;
|
||||
VertexBuffer vertexBuffer;
|
||||
uint objectID;
|
||||
} PushConstants;
|
||||
@@ -37,8 +38,7 @@ void main()
|
||||
{
|
||||
Vertex v = PushConstants.vertexBuffer.vertices[gl_VertexIndex];
|
||||
|
||||
mat3 M = mat3(PushConstants.render_matrix);
|
||||
mat3 normalMatrix = transpose(inverse(M));
|
||||
mat3 normalMatrix = PushConstants.normal_matrix;
|
||||
|
||||
vec4 worldPos = PushConstants.render_matrix * vec4(v.position, 1.0);
|
||||
gl_Position = sceneData.viewproj * worldPos;
|
||||
@@ -52,4 +52,3 @@ void main()
|
||||
outUV = vec2(v.uv_x, v.uv_y);
|
||||
outWorldPos = worldPos.xyz;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ vec3 getCameraWorldPosition()
|
||||
return -rot * T; // C = -R * T
|
||||
}
|
||||
|
||||
vec3 projectToScreen(vec3 worldPos)
|
||||
vec3 projectToScreenFromView(vec3 viewPos)
|
||||
{
|
||||
vec4 clip = sceneData.viewproj * vec4(worldPos, 1.0);
|
||||
vec4 clip = sceneData.proj * vec4(viewPos, 1.0);
|
||||
|
||||
if (clip.w <= 0.0)
|
||||
return vec3(0.0, 0.0, -1.0);
|
||||
@@ -64,6 +64,8 @@ void main()
|
||||
vec3 camPos = getCameraWorldPosition();
|
||||
vec3 V = normalize(camPos - worldPos);
|
||||
vec3 R = reflect(-V, N);
|
||||
vec3 viewPos = (sceneData.view * vec4(worldPos, 1.0)).xyz;
|
||||
vec3 viewDir = normalize((sceneData.view * vec4(R, 0.0)).xyz);
|
||||
|
||||
float gloss = 1.0 - roughness;
|
||||
float F0 = mix(0.04, 1.0, metallic);
|
||||
@@ -87,9 +89,9 @@ void main()
|
||||
float t = STEP_LENGTH;
|
||||
for (int i = 0; i < maxSteps && t <= MAX_DISTANCE; ++i, t += STEP_LENGTH)
|
||||
{
|
||||
vec3 samplePos = worldPos + R * t;
|
||||
vec3 sampleViewPos = viewPos + viewDir * t;
|
||||
|
||||
vec3 proj = projectToScreen(samplePos);
|
||||
vec3 proj = projectToScreenFromView(sampleViewPos);
|
||||
if (proj.z < 0.0)
|
||||
{
|
||||
break;
|
||||
@@ -102,10 +104,9 @@ void main()
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 viewSample = (sceneData.view * vec4(samplePos, 1.0)).xyz;
|
||||
vec3 viewScene = (sceneData.view * vec4(scenePosSample.xyz, 1.0)).xyz;
|
||||
|
||||
float depthRay = -viewSample.z;
|
||||
float depthRay = -sampleViewPos.z;
|
||||
float depthScene = -viewScene.z;
|
||||
float depthDiff = depthRay - depthScene;
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ vec3 getCameraWorldPosition()
|
||||
return -rot * T; // C = -R * T
|
||||
}
|
||||
|
||||
vec3 projectToScreen(vec3 worldPos)
|
||||
vec3 projectToScreenFromView(vec3 viewPos)
|
||||
{
|
||||
vec4 clip = sceneData.viewproj * vec4(worldPos, 1.0);
|
||||
vec4 clip = sceneData.proj * vec4(viewPos, 1.0);
|
||||
|
||||
if (clip.w <= 0.0)
|
||||
{
|
||||
@@ -71,6 +71,8 @@ void main()
|
||||
vec3 camPos = getCameraWorldPosition();
|
||||
vec3 V = normalize(camPos - worldPos);
|
||||
vec3 R = reflect(-V, N);
|
||||
vec3 viewPos = (sceneData.view * vec4(worldPos, 1.0)).xyz;
|
||||
vec3 viewDir = normalize((sceneData.view * vec4(R, 0.0)).xyz);
|
||||
|
||||
float gloss = 1.0 - roughness;
|
||||
float F0 = mix(0.04, 1.0, metallic);
|
||||
@@ -107,9 +109,9 @@ void main()
|
||||
float t = STEP_LENGTH_SSR;
|
||||
for (int i = 0; i < maxSteps && t <= MAX_DISTANCE_SSR; ++i, t += STEP_LENGTH_SSR)
|
||||
{
|
||||
vec3 samplePos = worldPos + R * t;
|
||||
vec3 sampleViewPos = viewPos + viewDir * t;
|
||||
|
||||
vec3 proj = projectToScreen(samplePos);
|
||||
vec3 proj = projectToScreenFromView(sampleViewPos);
|
||||
if (proj.z < 0.0)
|
||||
{
|
||||
break;
|
||||
@@ -122,10 +124,9 @@ void main()
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 viewSample = (sceneData.view * vec4(samplePos, 1.0)).xyz;
|
||||
vec3 viewScene = (sceneData.view * vec4(scenePosSample.xyz, 1.0)).xyz;
|
||||
|
||||
float depthRay = -viewSample.z;
|
||||
float depthRay = -sampleViewPos.z;
|
||||
float depthScene = -viewScene.z;
|
||||
float depthDiff = depthRay - depthScene;
|
||||
|
||||
@@ -190,7 +191,7 @@ void main()
|
||||
float tHit = rayQueryGetIntersectionTEXT(rq, true);
|
||||
vec3 hitPos = origin + R * tHit;
|
||||
|
||||
vec3 proj = projectToScreen(hitPos);
|
||||
vec3 proj = projectToScreenFromView((sceneData.view * vec4(hitPos, 1.0)).xyz);
|
||||
if (proj.z >= 0.0)
|
||||
{
|
||||
vec2 hitUV = proj.xy;
|
||||
|
||||
@@ -31,36 +31,50 @@ vec3 aces_tonemap(vec3 x)
|
||||
return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void accum_bloom(vec3 c, float kernel_weight, inout vec3 bloom, inout float weight_sum)
|
||||
{
|
||||
float bright = max(max(c.r, c.g), c.b) - pc.bloomThreshold;
|
||||
bright = max(bright, 0.0);
|
||||
|
||||
// Match the old behavior: only normalize over samples that pass the threshold.
|
||||
float contribute = step(1e-5, bright);
|
||||
|
||||
bloom += c * bright * kernel_weight;
|
||||
weight_sum += kernel_weight * contribute;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 hdr = texture(uHdr, inUV).rgb;
|
||||
|
||||
// Simple bloom in HDR space: gather bright neighbors and add a small blurred contribution.
|
||||
if (pc.bloomEnabled != 0)
|
||||
// Simple bloom in HDR space: approximate a 5x5 Gaussian blur using 9 bilinear samples (vs. 25 taps).
|
||||
if (pc.bloomEnabled != 0 && pc.bloomIntensity > 0.0)
|
||||
{
|
||||
vec2 texel = 1.0 / vec2(textureSize(uHdr, 0));
|
||||
vec2 d = texel * 1.2; // Combines 1- and 2-texel taps via linear filtering (4:1 weight).
|
||||
|
||||
vec3 bloom = vec3(0.0);
|
||||
int radius = 2;
|
||||
int count = 0;
|
||||
for (int x = -radius; x <= radius; ++x)
|
||||
float wsum = 0.0;
|
||||
|
||||
// 1D weights [1 4 6 4 1] collapsed to 3 linear samples => weights [5 6 5]
|
||||
// 2D separable => center 36, axis 30, corners 25 (sum 256).
|
||||
accum_bloom(hdr, 36.0, bloom, wsum); // reuse center sample
|
||||
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2( d.x, 0.0), vec2(0.0), vec2(1.0))).rgb, 30.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2(-d.x, 0.0), vec2(0.0), vec2(1.0))).rgb, 30.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2(0.0, d.y), vec2(0.0), vec2(1.0))).rgb, 30.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2(0.0, -d.y), vec2(0.0), vec2(1.0))).rgb, 30.0, bloom, wsum);
|
||||
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2( d.x, d.y), vec2(0.0), vec2(1.0))).rgb, 25.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2(-d.x, d.y), vec2(0.0), vec2(1.0))).rgb, 25.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2( d.x, -d.y), vec2(0.0), vec2(1.0))).rgb, 25.0, bloom, wsum);
|
||||
accum_bloom(texture(uHdr, clamp(inUV + vec2(-d.x, -d.y), vec2(0.0), vec2(1.0))).rgb, 25.0, bloom, wsum);
|
||||
|
||||
if (wsum > 0.0)
|
||||
{
|
||||
for (int y = -radius; y <= radius; ++y)
|
||||
{
|
||||
vec2 offset = vec2(x, y) * texel;
|
||||
vec3 c = texture(uHdr, clamp(inUV + offset, vec2(0.0), vec2(1.0))).rgb;
|
||||
float bright = max(max(c.r, c.g), c.b) - pc.bloomThreshold;
|
||||
if (bright > 0.0)
|
||||
{
|
||||
bloom += c * bright;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
bloom /= wsum;
|
||||
hdr += pc.bloomIntensity * bloom;
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
bloom /= float(count);
|
||||
}
|
||||
hdr += pc.bloomIntensity * bloom;
|
||||
}
|
||||
|
||||
// Simple exposure
|
||||
@@ -77,4 +91,3 @@ void main()
|
||||
|
||||
outColor = vec4(mapped, 1.0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user