Skip to content

Commit

Permalink
vsm: split mark-pages and draw
Browse files Browse the repository at this point in the history
  • Loading branch information
Try committed Sep 29, 2024
1 parent b146204 commit 2e701d9
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 188 deletions.
21 changes: 6 additions & 15 deletions game/graphics/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,8 @@ void Renderer::resetSwapchain() {
vsm.uboAlloc = device.descriptors(Shaders::inst().vsmAllocPages);

vsm.directLightPso = &Shaders::inst().vsmDirectLight;
vsm.uboLight = device.descriptors(*vsm.directLightPso);

vsm.pagesDbgPso = &Shaders::inst().vsmDbg;
vsm.uboDbg = device.descriptors(*vsm.pagesDbgPso);
vsm.uboLight = device.descriptors(*vsm.directLightPso);

vsm.pageDbg = device.image2d(TextureFormat::R32U, 32, 32);
vsm.pageTbl = device.image3d(TextureFormat::R32U, 32, 32, 16);
Expand Down Expand Up @@ -462,7 +460,7 @@ void Renderer::prepareUniforms() {
vsm.uboPages.set(2, gbufNormal, Sampler::nearest());
vsm.uboPages.set(3, zbuffer, Sampler::nearest());
vsm.uboPages.set(4, vsm.pageTbl);
vsm.uboPages.set(6, vsm.pageHiZ);
vsm.uboPages.set(5, vsm.pageHiZ);
//vsm.uboPages.set(7, vsm.pageList);

vsm.uboClump.set(0, vsm.pageList);
Expand All @@ -477,17 +475,10 @@ void Renderer::prepareUniforms() {
vsm.uboLight.set(2, gbufNormal, Sampler::nearest());
vsm.uboLight.set(3, zbuffer, Sampler::nearest());
vsm.uboLight.set(4, vsm.pageTbl);
vsm.uboLight.set(5, vsm.pageList);
if(!vsm.pageDataCs.isEmpty())
vsm.uboLight.set(5, vsm.pageDataCs); else
vsm.uboLight.set(5, vsm.pageData);
vsm.uboLight.set(7, vsm.pageList);

vsm.uboDbg.set(0, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
vsm.uboDbg.set(1, gbufDiffuse, Sampler::nearest());
vsm.uboDbg.set(2, gbufNormal, Sampler::nearest());
vsm.uboDbg.set(3, zbuffer, Sampler::nearest());
vsm.uboDbg.set(4, vsm.pageTbl);
vsm.uboDbg.set(5, vsm.pageData);
vsm.uboLight.set(6, vsm.pageDataCs); else
vsm.uboLight.set(6, vsm.pageData);
}

if(settings.swrEnabled) {
Expand Down Expand Up @@ -779,7 +770,7 @@ void Renderer::drawVsmDbg(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t

cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}});
cmd.setDebugMarker("VSM-dbg");
cmd.setUniforms(*vsm.pagesDbgPso, vsm.uboDbg, &settings.vsmMipBias, sizeof(settings.vsmMipBias));
cmd.setUniforms(*vsm.pagesDbgPso, vsm.uboLight, &settings.vsmMipBias, sizeof(settings.vsmMipBias));
cmd.draw(Resources::fsqVbo());
}

Expand Down
4 changes: 1 addition & 3 deletions game/graphics/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,8 @@ class Renderer final {
Tempest::DescriptorSet uboClump, uboAlloc;

Tempest::RenderPipeline* directLightPso = nullptr;
Tempest::DescriptorSet uboLight;

Tempest::RenderPipeline* pagesDbgPso = nullptr;
Tempest::DescriptorSet uboDbg;
Tempest::DescriptorSet uboLight;

Tempest::StorageImage pageDbg;
Tempest::StorageImage pageTbl;
Expand Down
190 changes: 190 additions & 0 deletions shader/virtual_shadow/vsm_direct_light.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#version 450

#extension GL_GOOGLE_include_directive : enable
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_samplerless_texture_functions : enable
#extension GL_KHR_memory_scope_semantics : enable

// #define DEBUG 1
#define LWC 1

#include "virtual_shadow/vsm_common.glsl"
#include "lighting/tonemapping.glsl"
#include "scene.glsl"
#include "common.glsl"

const vec3 debugColors[] = {
vec3(1,1,1),
vec3(1,0,0),
vec3(0,1,0),
vec3(0,0,1),
vec3(1,1,0),
vec3(1,0,1),
vec3(0,1,1),
vec3(1,0.5,0),
vec3(0.5,1,0),
vec3(0,0.5,1),
};

layout(std140, push_constant) uniform Push {
float vsmMipBias;
};
layout(binding = 0, std140) uniform UboScene {
SceneDesc scene;
};
layout(binding = 1) uniform texture2D gbufDiffuse;
layout(binding = 2) uniform utexture2D gbufNormal;
layout(binding = 3) uniform texture2D depth;
layout(binding = 4) uniform utexture3D pageTbl;
layout(binding = 5, std430) readonly buffer Pages { VsmHeader header; uint pageList[]; } vsm;
#if defined(VSM_ATOMIC)
layout(binding = 6) uniform utexture2D pageData;
#else
layout(binding = 6) uniform texture2D pageData;
#endif


layout(location = 0) out vec4 outColor;

float drawInt(in vec2 where, in int n) {
const float RESOLUTION = 0.5;
int i=int((where*=RESOLUTION).y);
if(0<i && i<6) {
i = 6-i;
for(int k=1, j=int(where.x); k-->0 || n>0; n/=10)
if ((j+=4)<3 && j>=0) {
int x = 0;
if(i>4)
x = 972980223;
else if(i>3)
x = 690407533;
else if(i>2)
x = 704642687;
else if(i>1)
x = 696556137;
else
x = 972881535;
return float(x >> (29-j-(n%10)*3)&1);
}
}
return 0;
}

uint hash(uvec3 gridPos) {
return (gridPos.x * 18397) + (gridPos.y * 20483) + (gridPos.z * 29303);
}

vec4 worldPos(ivec2 frag, float depth) {
const vec2 fragCoord = ((frag.xy+0.5)*scene.screenResInv)*2.0 - vec2(1.0);
const vec4 scr = vec4(fragCoord.x, fragCoord.y, depth, 1.0);
#if defined(LWC)
return scene.viewProjectLwcInv * scr;
#else
return scene.viewProjectInv * scr;
#endif
}

vec3 shadowPos(float z, ivec2 offset) {
const vec4 wpos = worldPos(ivec2(gl_FragCoord.xy) + offset, z);
#if defined(LWC)
vec4 shPos = scene.viewVirtualShadowLwc * wpos;
#else
vec4 shPos = scene.viewVirtualShadow * wpos;
#endif
shPos.xyz /= shPos.w;
return shPos.xyz;
}

int shadowLod(vec2 dx, vec2 dy) {
float px = dot(dx, dx);
float py = dot(dy, dy);
float maxLod = 0.5 * log2(max(px, py)); // log2(sqrt()) = 0.5*log2()
float minLod = 0.5 * log2(min(px, py));

const float bias = vsmMipBias;
//return max(0, int((minLod + maxLod)*0.5 + bias + 0.5));
return max(0, int(minLod + bias + 0.5));
}

float shadowTexelFetch(vec2 page, int mip) {
return shadowTexelFetch(page, mip, pageTbl, pageData);
}

float shadowTest(vec2 page, int mip, in float refZ, bool isATest) {
const float bias = (isATest ? 8 : -1)/(65535.0);
// const float bias = 2.0/(65535.0); // self-occlusion on trees
refZ += bias;
const float z = shadowTexelFetch(page, mip);
return z<refZ ? 1 : 0;
}

float lambert(vec3 normal) {
return max(0.0, dot(scene.sunDir,normal));
}

void main() {
outColor = vec4(0,0,0, 1);

#if 1
if(drawInt(gl_FragCoord.xy-vec2(100), int(vsm.header.pageCount))>0) {
outColor = vec4(1);
return;
}
#endif

const ivec2 fragCoord = ivec2(gl_FragCoord.xy);
const float z = texelFetch(depth, fragCoord, 0).r;
if(z==1.0)
return;

const vec4 diff = texelFetch (gbufDiffuse, fragCoord, 0);
const vec3 normal = normalFetch(gbufNormal, fragCoord);
if(dot(scene.sunDir,normal)<=0)
return;

vec3 shPos0 = shadowPos(z, ivec2(0,0));
vec2 shPos1 = shadowPos(z, ivec2(1,0)).xy;
vec2 shPos2 = shadowPos(z, ivec2(0,1)).xy;

// expected to have ~9 mips
int mip = shadowLod((shPos1 - shPos0.xy)*VSM_CLIPMAP_SIZE,
(shPos2 - shPos0.xy)*VSM_CLIPMAP_SIZE);
vec2 page = shPos0.xy / (1<<mip);
while(abs(page.x)>=1 || abs(page.y)>=1) {
page /= 2;
mip++;
}
if(any(greaterThan(abs(page), vec2(1))) || mip>=VSM_PAGE_MIPS)
return;

bool isFlat = false;
bool isATest = false;
bool isWater = false;
decodeBits(diff.a, isFlat, isATest, isWater);

const float light = (isFlat ? 0 : lambert(normal));
float shadow = 1;
if(light>0) {
shadow = shadowTest(page, mip, shPos0.z, isATest);
}

const vec3 illuminance = scene.sunColor * light * shadow;
const vec3 linear = textureAlbedo(diff.rgb);
const vec3 luminance = linear * Fd_Lambert * illuminance;

outColor = vec4(luminance * scene.exposure, 1);
#if defined(DEBUG)
const ivec2 pageI = ivec2((page*0.5+0.5)*VSM_PAGE_TBL_SIZE);
// int mip = 0;
// vec3 color = directLight(page, mip, shPos0.z);
vec3 color = debugColors[hash(uvec3(pageI,mip)) % debugColors.length()];
// vec3 color = debugColors[mip % debugColors.length()];
// color *= (1.0 - shadowTexelFetch(page, mip));
color *= (shadowTest(page, mip, shPos0.z, false)*0.9+0.1);
// vec3 color = vec3(shPos0, 0);
// vec3 color = vec3(page, 0);
// vec3 color = vec3(fract(page*VSM_PAGE_TBL_SIZE), 0);
// vec4 color = shadowTexelFetch(page, mip);
outColor = vec4(color.xyz,1);
#endif
}
Loading

0 comments on commit 2e701d9

Please sign in to comment.