Jarvis, Optimise my shit

This commit is contained in:
Halbear 2026-09-25 23:37:22 +01:00
parent d1abde919d
commit 9424b29d0a
50 changed files with 1469 additions and 1232 deletions

View file

@ -0,0 +1,29 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2D inputTexture;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec3 extractBloom(vec2 uv) {
vec3 color = max(texture(inputTexture, uv).rgb, vec3(0.0));
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float contribution = max(brightness - 1.0, 0.0);
return color * (contribution / (contribution + 0.5));
}
void main() {
vec2 offset = 0.25 / config.bloomSize;
vec3 bloom = extractBloom(inTextCoord + vec2(-offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2(-offset.x, offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, offset.y));
outBloomColour = vec4(bloom * 0.25, 1.0);
}

View file

@ -1,61 +1,30 @@
#version 450
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 TexCoords;
layout(set = 0, binding = 0) uniform sampler2D bloomImage;
layout(set = 0, binding = 0) uniform sampler2D image;
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(set = 1 , binding = 0) uniform PassConfig{
int ApplyToFinalImage;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec3 padding;
vec2 bloomSize;
} config;
const float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
const float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
vec3 safeBloomSample(vec2 uv)
{
vec3 value = texture(bloomImage, uv).rgb;
return clamp(value, vec3(0.0), vec3(8.0));
vec3 safeBloomSample(vec2 uv) {
return max(texture(bloomImage, uv).rgb, vec3(0.0));
}
void main()
{
if(config.ApplyToFinalImage != 0){
vec3 bloomColour = safeBloomSample(TexCoords);
vec3 hdrColour = texture(image, TexCoords).rgb;
hdrColour += bloomColour;
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure);
result = pow(result, vec3(1.0 / config.GAMMA_CONST));
FragColor = vec4(result, 1.0);
return;
}
float blurRadius = config.blur_radius;
vec2 tex_offset = blurRadius / vec2(textureSize(bloomImage, 0));
void main() {
vec2 tex_offset = config.blur_radius / vec2(textureSize(bloomImage, 0));
vec2 direction = config.horizontal != 0 ? vec2(tex_offset.x, 0.0) : vec2(0.0, tex_offset.y);
vec3 result = safeBloomSample(TexCoords) * weight[0];
if(config.horizontal != 0)
{
for(int i = 1; i < 5; ++i)
{
result += safeBloomSample(TexCoords + vec2(tex_offset.x * i, 0.0)) * weight[i];
result += safeBloomSample(TexCoords - vec2(tex_offset.x * i, 0.0)) * weight[i];
}
for (int i = 1; i < 5; i++) {
result += safeBloomSample(TexCoords + direction * i) * weight[i];
result += safeBloomSample(TexCoords - direction * i) * weight[i];
}
else
{
for(int i = 1; i < 5; ++i)
{
result += safeBloomSample(TexCoords + vec2(0.0, tex_offset.y * i)) * weight[i];
result += safeBloomSample(TexCoords - vec2(0.0, tex_offset.y * i)) * weight[i];
}
}
FragColor = vec4(result, 1.0);
}
}

View file

@ -68,9 +68,12 @@ float chebyshevUpperBound(vec2 moments, float t) {
return p_max;
}
float calcVisibility(vec4 worldPosition, uint cascadeIndex, float ShadowBias, vec2 texelSize) {
float calcVisibility(vec4 worldPosition, uint cascadeIndex, vec2 texelSize) {
vec4 shadowMapPosition = shadows.cascadeshadows[cascadeIndex].projViewMatrix * worldPosition;
if (!(shadowMapPosition.w > 0.0) || any(isnan(shadowMapPosition)) || any(isinf(shadowMapPosition))) {
return 1.0;
}
shadowMapPosition.xyz /= shadowMapPosition.w;
vec2 uv = vec2(
@ -82,17 +85,27 @@ float calcVisibility(vec4 worldPosition, uint cascadeIndex, float ShadowBias, ve
if (uv.x < 0.0 || uv.x > 1.0 ||
uv.y < 0.0 || uv.y > 1.0 ||
depth < ShadowBias || depth > 1.0) {
depth < 0.0 || depth > 1.0) {
return 1.0;
}
float shadow = 0.0;
// vec2 moments = texture(shadowSampler, vec3((uv), cascadeIndex)).rg;
// float visibility = chebyshevUpperBound(moments, depth);
// shadow += visibility;
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
vec2 moments = texture(shadowSampler, vec3((uv + vec2(x, y) * texelSize), cascadeIndex)).rg;
vec2 sampleUV = uv + vec2(x, y) * texelSize;
if (any(lessThan(sampleUV, vec2(0.0))) || any(greaterThan(sampleUV, vec2(1.0)))) {
shadow += 1.0;
continue;
}
sampleUV = clamp(sampleUV, texelSize * 0.5, vec2(1.0) - texelSize * 0.5);
vec2 moments = texture(shadowSampler, vec3(sampleUV, cascadeIndex)).rg;
float visibility = chebyshevUpperBound(moments, depth);
shadow += visibility;
}
@ -212,8 +225,6 @@ void main() {
// outFragColor = vec4(emissive,1);
// return;
float ShadowBias = 0.05f;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3.0;
@ -228,18 +239,21 @@ void main() {
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
uint cascadeIndex = 0;
vec4 viewPos = sceneInfo.viewMatrix * worldPosW;
for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
if (viewPos.z < shadows.cascadeshadows[i].splitDistance.x) {
cascadeIndex = i + 1;
uint cascadeIndex = SHADOW_MAP_CASCADE_COUNT;
vec4 viewPos = sceneInfo.viewMatrix * vec4(worldPos, 1.0);
float lastSplit = shadows.cascadeshadows[SHADOW_MAP_CASCADE_COUNT - 1].splitDistance.x;
float shadow = 1.0;
if (lastSplit < 0.0 && viewPos.z < 0.0 && viewPos.z >= lastSplit) {
cascadeIndex = 0;
for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
if (viewPos.z < shadows.cascadeshadows[i].splitDistance.x) {
cascadeIndex = i + 1;
}
}
vec2 texelSizeShadow = 1.0 / textureSize(shadowSampler, 0).rg;
shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex, texelSizeShadow);
}
vec2 texelSizeShadow = 1.0 / textureSize(shadowSampler, 0).rg;
float shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex,ShadowBias, texelSizeShadow);
vec3 Lo = vec3(0.0);
for (uint i = 0; i < sceneInfo.numLights; i++) {
Light light = lights.lights[i];
@ -254,7 +268,7 @@ void main() {
outFragColor = vec4(Lo + ambient, 1.0f);
outFragColor = vec4(outFragColor.xyz/2 + (outFragColor.xyz/2) * vec3(ssao,ssao,ssao),1);
if (DEBUG_SHADOWS == 1) {
if (DEBUG_SHADOWS == 1 && cascadeIndex < SHADOW_MAP_CASCADE_COUNT) {
switch (cascadeIndex) {
case 0:
outFragColor.rgb *= vec3(1.0f, 0.25f, 0.25f);

View file

@ -0,0 +1,34 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec3 extractBloom(vec2 uv) {
ivec2 size = textureSize(inputTexture);
ivec2 pixel = clamp(ivec2(uv * vec2(size)), ivec2(0), size - 1);
int samples = textureSamples(inputTexture);
vec3 color = vec3(0.0);
for (int i = 0; i < samples; i++) color += texelFetch(inputTexture, pixel, i).rgb;
color = max(color / float(samples), vec3(0.0));
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float contribution = max(brightness - 1.0, 0.0);
return color * (contribution / (contribution + 0.5));
}
void main() {
vec2 offset = 0.25 / config.bloomSize;
vec3 bloom = extractBloom(inTextCoord + vec2(-offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2(-offset.x, offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, offset.y));
outBloomColour = vec4(bloom * 0.25, 1.0);
}

View file

@ -1,72 +1,42 @@
#version 450
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.4545;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(location = 1) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(set = 1, binding = 0) uniform ScreenSize{
vec2 size;
} screenSize;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec4 gamma(vec4 color){
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
}
vec3 HDR(float Gamma, float Exposure, sampler2D Texture, vec2 TexCoords){
vec3 hdrColor = texture(Texture, TexCoords).rgb;
vec3 mapped = vec3(1.0) - exp(-hdrColor * Exposure);
mapped = pow(mapped, vec3(1.0 / Gamma));
return mapped;
}
vec4 msaa(int sampleCount, sampler2DMS textureIn,vec2 TextCoord){
ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn));
vec4 msaa(int sampleCount, sampler2DMS textureIn, vec2 TextCoord) {
ivec2 size = textureSize(textureIn);
ivec2 pixelCoords = clamp(ivec2(TextCoord * vec2(size)), ivec2(0), size - 1);
vec4 colorSum = vec4(0.0);
for(int i = 0; i < sampleCount; ++i) {
vec4 sampleColor = texelFetch(textureIn, pixelCoords, i);
colorSum += sampleColor;
}
for (int i = 0; i < sampleCount; i++) colorSum += texelFetch(textureIn, pixelCoords, i);
return colorSum / float(sampleCount);
}
void main(){
ivec2 pixelCoords = ivec2(inTextCoord * textureSize(inputTexture));
vec3 bloomAt(ivec2 pixel, ivec2 size) {
return texelFetch(bloomImage, clamp(pixel, ivec2(0), size - 1), 0).rgb;
}
outFragColor = texelFetch(inputTexture, pixelCoords, 0);
vec3 upsampleBloom(vec2 uv) {
ivec2 size = textureSize(bloomImage, 0);
vec2 pixel = uv * vec2(size) - 0.5;
ivec2 base = ivec2(floor(pixel));
vec2 blend = fract(pixel);
return mix(mix(bloomAt(base, size), bloomAt(base + ivec2(1, 0), size), blend.x),
mix(bloomAt(base + ivec2(0, 1), size), bloomAt(base + ivec2(1, 1), size), blend.x), blend.y);
}
if(USE_AA == 0){
outFragColor = texelFetch(inputTexture,pixelCoords,0);
}
if(USE_AA == 1){
outFragColor = texelFetch(inputTexture,pixelCoords,0);
}
if(USE_AA == 2){
outFragColor = msaa(2,inputTexture,inTextCoord);
}
if(USE_AA == 3){
outFragColor = msaa(4,inputTexture,inTextCoord);
}
if(USE_AA == 4){
outFragColor = msaa(8,inputTexture,inTextCoord);
}
vec3 color = outFragColor.rgb;
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float threshold = 1.0;
float softKnee = 0.5;
float contribution = max(brightness - threshold, 0.0);
contribution = contribution / max(contribution + softKnee, 0.0001);
outBloomColour = vec4(color * contribution, 1.0);
}
void main() {
vec4 sceneColor = msaa(textureSamples(inputTexture), inputTexture, inTextCoord);
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0));
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure);
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a);
}

View file

@ -111,6 +111,11 @@ void main() {
vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex];
vec3 Offset = vec3(0,0,0);
if (gl_InstanceIndex != 0) {
uint encoded = uint(gl_InstanceIndex);
Offset = vec3(int(encoded & 1023u) - 512, int((encoded >> 10u) & 1023u) - 512,
int((encoded >> 20u) & 1023u) - 512) * 16.0;
}
vec3 worldPos = localPos + Offset + push_constants.ModelOffset.xyz * 16.0;
vec4 worldPosVec4 = vec4(worldPos, 1.0);

View file

@ -2,36 +2,27 @@
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.4545;
const float Exposure = 2.0;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(location = 1) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2D inputTexture;
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(set = 1, binding = 0) uniform ScreenSize{
vec2 size;
} screenSize;
vec4 gamma(vec4 color){
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
}
vec3 HDR(float Gamma, float Exposure, sampler2D Texture, vec2 TexCoords){
vec3 hdrColor = texture(Texture, TexCoords).rgb;
vec3 mapped = vec3(1.0) - exp(-hdrColor * Exposure);
mapped = pow(mapped, vec3(1.0 / Gamma));
return mapped;
}
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
// Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa
vec4 fxaa(sampler2D tex, vec2 uv) {
vec2 u_texel = 1.0 / screenSize.size;
vec2 u_texel = 1.0 / vec2(textureSize(inputTexture, 0));
//Sample center and 4 corners
vec3 rgbCC = texture(tex, uv).rgb;
@ -79,36 +70,22 @@ vec4 fxaa(sampler2D tex, vec2 uv) {
return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B;
}
vec3 bloomAt(ivec2 pixel, ivec2 size) {
return texelFetch(bloomImage, clamp(pixel, ivec2(0), size - 1), 0).rgb;
}
vec3 upsampleBloom(vec2 uv) {
ivec2 size = textureSize(bloomImage, 0);
vec2 pixel = uv * vec2(size) - 0.5;
ivec2 base = ivec2(floor(pixel));
vec2 blend = fract(pixel);
return mix(mix(bloomAt(base, size), bloomAt(base + ivec2(1, 0), size), blend.x),
mix(bloomAt(base + ivec2(0, 1), size), bloomAt(base + ivec2(1, 1), size), blend.x), blend.y);
}
void main(){
if(USE_AA == 1){
outFragColor = fxaa(inputTexture, inTextCoord);
}
else if(USE_AA == 2){
outFragColor = texture(inputTexture, inTextCoord);
}
else if(USE_AA == 3){
outFragColor = texture(inputTexture, inTextCoord);
}
else if(USE_AA == 4){
outFragColor = texture(inputTexture, inTextCoord);
}
else {
outFragColor = texture(inputTexture, inTextCoord);
}
vec3 color = outFragColor.rgb;
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float threshold = 1.0;
float softKnee = 0.5;
float contribution = max(brightness - threshold, 0.0);
contribution = contribution / max(contribution + softKnee, 0.0001);
outBloomColour = vec4(color * contribution, 1.0);
vec4 sceneColor = USE_AA == 1 ? fxaa(inputTexture, inTextCoord) : texture(inputTexture, inTextCoord);
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0));
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure);
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a);
}

View file

@ -10,9 +10,7 @@ layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
layout(set = 1, binding = 0) uniform CameraProperties {
mat4 projection;
mat4 invProjection;
mat4 view;
mat4 invView;
float ssrStepSize;
float ssrMaxDistance;
int maxSteps;
@ -30,13 +28,12 @@ float edgeFade(vec2 uv) {
}
void main() {
vec4 sceneColor = texture(albedoSampler, fragTexCoord);
outColor = vec4(0.0);
vec4 posSample = texture(worldPosSampler, fragTexCoord);
vec4 normalSample = texture(normalSampler, fragTexCoord);
vec4 pbrSample = texture(pbrSampler, fragTexCoord);
if (posSample.a == 0.0 || length(posSample.xyz) == 0.0 || length(normalSample.xyz) < 0.001) {
outColor = sceneColor;
return;
}
@ -54,11 +51,10 @@ void main() {
float materialReflection = reflectiveness + (refractiveness - 1.05);
materialReflection *= mix(0.75, 1.0, metallic);
materialReflection *= smoothstep(0.7, 0.05, roughness);
materialReflection *= 1.0 - smoothstep(0.05, 0.7, roughness);
materialReflection *= mix(0.45, 1.0, fresnel);
if (materialReflection <= MIN_REFLECTION) {
outColor = sceneColor;
return;
}
@ -66,7 +62,6 @@ void main() {
vec3 reflectDir = normalize(reflect(viewDir, worldNormal));
if (dot(reflectDir, worldNormal) <= 0.0) {
outColor = sceneColor;
return;
}
@ -115,7 +110,6 @@ void main() {
}
if (!hitFound) {
outColor = sceneColor;
return;
}
@ -124,5 +118,5 @@ void main() {
float fade = edgeFade(hitUV);
float weight = clamp(materialReflection * fade, 0.0, 0.85);
outColor = vec4(mix(sceneColor.rgb, reflectedColor, weight), sceneColor.a);
outColor = vec4(reflectedColor * weight, weight);
}

View file

@ -65,7 +65,7 @@ void main()
} else {
albedo = material.diffuseColor;
}
if (albedo.a < 0.5 || Translucency > 0.5 || Opacity < 0.5) {
if (albedo.a < 0.5 || Translucency > 0.95 || Opacity < 0.5) {
discard;
}
@ -77,5 +77,5 @@ void main()
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
outFragColor = vec2(moment1, moment2);
outFragColor = vec2(moment1, moment2) * (1 - Translucency);
}

View file

@ -80,59 +80,11 @@ const vec3 FACE_CORNERS[8][4] = vec3[8][4](
vec3[4](vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)) // Face 7 (cross model pane 2)
);
vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) {
vec3 p = vec3(voxelPos);
if (faceId == 0u) {
if (cornerIndex == 0u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 1.0, 0.0);
}
if (faceId == 1u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 0.0, 1.0);
return p + vec3(0.0, 0.0, 1.0);
}
if (faceId == 2u) {
if (cornerIndex == 0u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 0.0, 1.0);
}
if (faceId == 3u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(0.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 0.0);
}
if (faceId == 4u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 1.0);
}
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 0.0);
return p + vec3(1.0, 0.0, 0.0);
}
void main() {
uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
uint triangleVertex = (uint(gl_VertexIndex))% 6u;
uint cornerIndex = TRI_TO_CORNER[triangleVertex];
//uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
//uint triangleVertex = uint(gl_VertexIndex) % 6u;
//uint cornerIndex = TRI_TO_CORNER[triangleVertex];
uint packedFace = faces[faceRecordIndex];
uint voxelX = packedFace & 0xFu;
@ -143,14 +95,6 @@ void main() {
uint texIdxX = (packedFace >> 26u) & 0x7u;
uint texIdxY = (packedFace >> 29u) & 0x7u;
// (voxelPos.x & 0xFu) |
// ((voxelPos.y & 0xFu) << 4u) |
// ((voxelPos.z & 0xFu) << 8u) |
// ((faceIndex & 0x7u) << 12u) |
// ((materialId & 0x7FFu) << 15u) |
// ((textureIndexX & 0x7u) << 26u) |
// ((textureIndexY & 0x7u) << 29u);
vec2 texID = vec2((texIdxX)/4.0,(texIdxY)/4.0);
vec2 scalar = vec2(1.0/4.0,1.0/4.0);
@ -158,6 +102,11 @@ void main() {
vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex];
vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0;
if (gl_InstanceIndex != 0) {
uint encoded = uint(gl_InstanceIndex);
worldPos += vec3(int(encoded & 1023u) - 512, int((encoded >> 10u) & 1023u) - 512,
int((encoded >> 20u) & 1023u) - 512) * 16.0;
}
outTextCoord = CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex] * scalar + texID;
outMaterialIdx = matId;

View file

@ -7,7 +7,7 @@ layout(set = 0, binding = 0) uniform sampler2D ssaoSampler;
layout(set = 0, binding = 1) uniform sampler2D viewPosSampler;
void main() {
vec2 texelSize = 2.0 / vec2(textureSize(ssaoSampler, 0));
vec2 texelSize = 1.0 / vec2(textureSize(ssaoSampler, 0));
float centerAO = texture(ssaoSampler, inTextCoord).r;
float centerDepth = texture(viewPosSampler, inTextCoord).z;
@ -15,7 +15,7 @@ void main() {
float totalAO = centerAO;
float totalWeight = 1.0;
float weights[4] = float[](0.227027, 0.1216216, 0.054054, 0.016216);
float weights[4] = float[](0.1216216, 0.1945946, 0.1945946, 0.1216216);
int offsets[4] = int[](-2, -1, 1, 2);
const float Sharpness = 20.0;

View file

@ -2,7 +2,6 @@
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out float outAO;
layout(location = 1) out vec4 viewPos;
layout(set = 0, binding = 0) uniform sampler2D posSampler;
layout(set = 0, binding = 1) uniform sampler2D normalSampler;
@ -19,65 +18,52 @@ layout(set = 2, binding = 0) uniform SSAOInfo {
float radius; //140
float bias; //144
int kernelSize; //148
float ResolutionScale; //152;
vec2 Padding; //160;
} ssao;
void main() {
vec2 ScreenSize = ssao.screenSize * ssao.ResolutionScale;
int KERNEL_SIZE = ssao.kernelSize;
int KERNEL_SIZE = clamp(ssao.kernelSize, 1, 64);
vec3 fragPos = texture(posSampler, inTextCoord).xyz;
vec3 worldNorm = normalize(texture(normalSampler, inTextCoord).xyz);
vec3 worldNorm = texture(normalSampler, inTextCoord).xyz;
if (dot(worldNorm, worldNorm) < 0.001) {
if (dot(worldNorm, worldNorm) < 0.001 || fragPos.z >= 0.0) {
outAO = 1.0;
return;
}
vec3 normal = normalize(mat3(ssao.view) * worldNorm);
viewPos = vec4(fragPos, 1);
vec2 noiseScale = ScreenSize / 4.0;
vec3 randomVec = texture(noiseSampler, inTextCoord * noiseScale).xyz;
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
vec3 randomVec = texelFetch(noiseSampler, ivec2(gl_FragCoord.xy) % 4, 0).xyz;
vec3 tangent = randomVec - normal * dot(randomVec, normal);
if (dot(tangent, tangent) < 0.0001) {
tangent = cross(normal, abs(normal.z) < 0.9 ? vec3(0, 0, 1) : vec3(0, 1, 0));
}
tangent = normalize(tangent);
vec3 bitangent = cross(normal, tangent);
mat3 TBN = mat3(tangent, bitangent, normal);
float fragDepth = -fragPos.z;
float minOptimalDistance = 15;
float maxKernelSize = float(ssao.kernelSize);
// Calculate a dynamic loop limit based on proximity
// If closer than 1.5 units, smoothly scale down the loop count
int dynamicKernelSize = int(KERNEL_SIZE);
if (fragDepth < minOptimalDistance) {
float proximityFactor = clamp(fragDepth / minOptimalDistance, 0.2, 1.0);
dynamicKernelSize = int(maxKernelSize * proximityFactor);
}
// Force a hard minimum baseline of samples so SSAO doesn't completely disappear
dynamicKernelSize = max(dynamicKernelSize, 16);
float occlusion = 0.0;
float Passes = 0.0f;
for (int i = 0; i < dynamicKernelSize; i++) {
vec3 samplePos = fragPos + (TBN * kernel.samples[i].xyz) * ssao.radius;
for (int i = 0; i < KERNEL_SIZE; i++) {
// Cover the complete radius distribution, even with a smaller sample budget.
int sampleIndex = i * 64 / KERNEL_SIZE;
vec3 samplePos = fragPos + (TBN * kernel.samples[sampleIndex].xyz) * ssao.radius;
vec4 offset = ssao.projection * vec4(samplePos, 1.0);
if (offset.w <= 0.0) continue;
offset.xyz /= offset.w;
offset.xyz = offset.xyz * 0.5 + 0.5;
vec2 sampleUV = clamp(vec2(offset.x, 1.0 - offset.y), 0.0, 1.0);
vec2 sampleUV = vec2(offset.x, 1.0 - offset.y);
if (any(lessThan(sampleUV, vec2(0))) || any(greaterThan(sampleUV, vec2(1)))) continue;
vec3 sampleViewPos = texture(posSampler, sampleUV).xyz;
if (sampleViewPos.z >= 0.0) continue;
float sampleDepth = -sampleViewPos.z;
float depthDelta = abs(fragDepth - sampleDepth);
if (depthDelta > ssao.radius * 2.0) {
continue;
}
float rangeCheck = smoothstep(0.0, 1.0, ssao.radius / depthDelta);
float rangeCheck = smoothstep(0.0, 1.0, ssao.radius / max(depthDelta, 0.0001));
float isOccluded = step(samplePos.z + ssao.bias, sampleViewPos.z);
occlusion += isOccluded * rangeCheck;
Passes += 1.0;

View file

@ -0,0 +1,34 @@
#version 450
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D sceneSampler;
layout(set = 0, binding = 1) uniform sampler2D reflectionSampler;
layout(set = 0, binding = 2) uniform sampler2D pbrSampler;
layout(set = 0, binding = 3) uniform sampler2D normalSampler;
vec4 reflectionAt(ivec2 pixel, ivec2 size) {
return texelFetch(reflectionSampler, clamp(pixel, ivec2(0), size - 1), 0);
}
void main() {
vec4 sceneColor = texture(sceneSampler, fragTexCoord);
vec4 pbr = texture(pbrSampler, fragTexCoord);
vec4 normal = texture(normalSampler, fragTexCoord);
float materialReflection = (pbr.a + normal.a - 1.05) * (1.0 - smoothstep(0.05, 0.7, pbr.g));
if (dot(normal.xyz, normal.xyz) < 0.001 || materialReflection <= 0.01) {
outColor = sceneColor;
return;
}
// The shared sampler is nearest-filtered. Upsample only premultiplied reflections.
ivec2 size = textureSize(reflectionSampler, 0);
vec2 pixel = fragTexCoord * vec2(size) - 0.5;
ivec2 base = ivec2(floor(pixel));
vec2 blend = fract(pixel);
vec4 reflection = mix(
mix(reflectionAt(base, size), reflectionAt(base + ivec2(1, 0), size), blend.x),
mix(reflectionAt(base + ivec2(0, 1), size), reflectionAt(base + ivec2(1, 1), size), blend.x), blend.y);
outColor = vec4(sceneColor.rgb * (1.0 - reflection.a) + reflection.rgb, sceneColor.a);
}