diff --git a/game/graphics/drawcommands.cpp b/game/graphics/drawcommands.cpp index 6417003a5..3292a72c6 100644 --- a/game/graphics/drawcommands.cpp +++ b/game/graphics/drawcommands.cpp @@ -337,14 +337,14 @@ void DrawCommands::updateCommandUniforms() { desc[v].set(L_GDepth, *scene.sceneDepth, smp); } - if(v==SceneGlobals::V_Vsm && scene.vsmPageData!=nullptr && !scene.vsmPageData->isEmpty()) { + if(v==SceneGlobals::V_Vsm && scene.vsmPageDataCs->w()>1) { // atomic desc[v].set(L_CmdOffsets, views[v].indirectCmd); desc[v].set(L_VsmPages, *scene.vsmPageList); desc[v].set(L_VsmTbl, *scene.vsmPageTbl); - desc[v].set(L_VsmData, *scene.vsmPageData); + desc[v].set(L_VsmData, *scene.vsmPageDataCs); } - if(v==SceneGlobals::V_Vsm && scene.vsmPageData!=nullptr && scene.vsmPageData->isEmpty()) { + else if(v==SceneGlobals::V_Vsm) { // raster desc[v].set(L_CmdOffsets, views[v].indirectCmd); desc[v].set(L_VsmPages, *scene.vsmPageList); diff --git a/game/graphics/renderer.cpp b/game/graphics/renderer.cpp index 798ea05f2..7577179b6 100644 --- a/game/graphics/renderer.cpp +++ b/game/graphics/renderer.cpp @@ -504,7 +504,7 @@ void Renderer::prepareUniforms() { sh[i] = &textureCast(shadowMap[i]); } wview->setShadowMaps(sh); - wview->setVirtualShadowMap(vsm.pageDataCs, vsm.pageTbl, vsm.pageHiZ, vsm.pageList); + wview->setVirtualShadowMap(vsm.pageData, vsm.pageDataCs, vsm.pageTbl, vsm.pageHiZ, vsm.pageList); wview->setSwRenderingImage(swr.outputImage); wview->setHiZ(textureCast(hiz.hiZ)); diff --git a/game/graphics/sceneglobals.cpp b/game/graphics/sceneglobals.cpp index 1af219f47..811926316 100644 --- a/game/graphics/sceneglobals.cpp +++ b/game/graphics/sceneglobals.cpp @@ -29,6 +29,10 @@ SceneGlobals::SceneGlobals() { for(auto& i:shadowMap) i = &Resources::fallbackBlack(); + vsmPageData = &Resources::fallbackBlack(); + vsmPageTbl = &Resources::fallbackImage3d(); + vsmPageHiZ = &Resources::fallbackImage3d(); + for(uint8_t lay=0; lay(pageData); + vsmPageDataCs = &pageDataCs; + vsmPageTbl = &pageTbl; + vsmPageHiZ = &pageHiZ; + vsmPageList = &pageList; } void SceneGlobals::setSwRenderingImage(const Tempest::StorageImage& mainView) { diff --git a/game/graphics/sceneglobals.h b/game/graphics/sceneglobals.h index deb4384f7..25094cb9f 100644 --- a/game/graphics/sceneglobals.h +++ b/game/graphics/sceneglobals.h @@ -42,7 +42,8 @@ class SceneGlobals final { void setHiZ(const Tempest::Texture2d& hiZ); void setShadowMap(const Tempest::Texture2d* tex[]); - void setVirtualShadowMap(const Tempest::StorageImage& vsmPageData, + void setVirtualShadowMap(const Tempest::ZBuffer& vsmPageData, + const Tempest::StorageImage& vsmPageDataCs, const Tempest::StorageImage& pageTbl, const Tempest::StorageImage& pageHiZ, const Tempest::StorageBuffer& vsmPageList); @@ -76,10 +77,11 @@ class SceneGlobals final { const Tempest::StorageBuffer* lights = nullptr; - const Tempest::StorageImage* vsmPageData = nullptr; - const Tempest::StorageImage* vsmPageTbl = nullptr; - const Tempest::StorageImage* vsmPageHiZ = nullptr; - const Tempest::StorageBuffer* vsmPageList = nullptr; + const Tempest::Texture2d* vsmPageData = nullptr; + const Tempest::StorageImage* vsmPageDataCs = nullptr; + const Tempest::StorageImage* vsmPageTbl = nullptr; + const Tempest::StorageImage* vsmPageHiZ = nullptr; + const Tempest::StorageBuffer* vsmPageList = nullptr; const Tempest::StorageImage* swMainImage = nullptr; diff --git a/game/graphics/shaders.cpp b/game/graphics/shaders.cpp index 08a88fd23..22248bd1c 100644 --- a/game/graphics/shaders.cpp +++ b/game/graphics/shaders.cpp @@ -56,9 +56,10 @@ Shaders::Shaders() { fogViewLut3d = computeShader("fog_view_lut.comp.sprv"); shadowDownsample = computeShader("shadow_downsample.comp.sprv"); fogOcclusion = computeShader("fog3d.comp.sprv"); + if(Gothic::options().doVirtualShadow) + fogOcclusionVsm = computeShader("fog3d_vsm.comp.sprv"); skyExposure = computeShader("sky_exposure.comp.sprv"); - sky = postEffect("sky"); fog = fogShader ("fog"); fog3dHQ = fogShader ("fog3d_hq"); @@ -195,6 +196,7 @@ Shaders::Shaders() { if(Gothic::options().doVirtualShadow) { vsmClusterTask = computeShader("vsm_cluster_task.comp.sprv"); + // vsmClusterTask = computeShader("vsm_cluster_task2.comp.sprv"); vsmClear = computeShader("vsm_clear.comp.sprv"); vsmClearPages = computeShader("vsm_clear_pages.comp.sprv"); vsmMarkPages = computeShader("vsm_mark_pages.comp.sprv"); diff --git a/game/graphics/shaders.h b/game/graphics/shaders.h index bddb5ca56..1f9202a71 100644 --- a/game/graphics/shaders.h +++ b/game/graphics/shaders.h @@ -43,7 +43,7 @@ class Shaders { Tempest::RenderPipeline fog; Tempest::RenderPipeline fog3dHQ; Tempest::RenderPipeline sun; - Tempest::ComputePipeline cloudsLut, fogOcclusion; + Tempest::ComputePipeline cloudsLut, fogOcclusion, fogOcclusionVsm; Tempest::ComputePipeline fogViewLut3d, shadowDownsample; Tempest::ComputePipeline skyExposure; diff --git a/game/graphics/sky/sky.cpp b/game/graphics/sky/sky.cpp index cd07588e4..65dbb8be8 100644 --- a/game/graphics/sky/sky.cpp +++ b/game/graphics/sky/sky.cpp @@ -107,10 +107,21 @@ Sky::~Sky() { } void Sky::setupSettings() { - auto& device = Resources::device(); - bool fog = Gothic::inst().settingsGetI("RENDERER_D3D","zFogRadial")!=0; + auto& device = Resources::device(); + const bool fog = Gothic::inst().settingsGetI("RENDERER_D3D","zFogRadial")!=0; + const bool vsm = false;//Gothic::inst().options().doVirtualShadow; + + auto q = Quality::VolumetricLQ; + if(!fog) { + q = Quality::VolumetricLQ; + } + else if(fog && !vsm) { + q = Quality::VolumetricHQ; + } + else if(fog && vsm) { + q = Quality::VolumetricHQVsm; + } - auto q = fog ? Quality::VolumetricHQ : Quality::VolumetricLQ; if(pathTrace) q = PathTrace; @@ -129,6 +140,7 @@ void Sky::setupSettings() { occlusionLut = StorageImage(); break; case VolumetricHQ: + case VolumetricHQVsm: // fogLut and oclussion are decupled fogLut3D = device.image3d(lutRGBAFormat,128,64,32); shadowDw = StorageImage(); @@ -274,7 +286,7 @@ void Sky::prepareUniforms() { auto smpB = Sampler::bilinear(); smpB.setClamping(ClampMode::ClampToEdge); - if(quality==VolumetricHQ) { + if(quality==VolumetricHQ || quality==VolumetricHQVsm) { occlusionScale = 1; if(uint32_t(scene.zbuffer->h()) > 1080 && device.properties().type!=DeviceType::Discrete) { @@ -340,15 +352,22 @@ void Sky::prepareUniforms() { uboFog.set(2, scene.uboGlobal[SceneGlobals::V_Main]); } - if(quality==VolumetricHQ) { + if(quality==VolumetricHQ || quality==VolumetricHQVsm) { auto smpLut3d = Sampler::bilinear(); smpLut3d.setClamping(ClampMode::ClampToEdge); - uboOcclusion = device.descriptors(Shaders::inst().fogOcclusion); + const bool vsm = (quality==VolumetricHQVsm); + auto& fogOcclusion = vsm ? Shaders::inst().fogOcclusionVsm : Shaders::inst().fogOcclusion; + uboOcclusion = device.descriptors(fogOcclusion); uboOcclusion.set(1, *scene.zbuffer, Sampler::nearest()); uboOcclusion.set(2, scene.uboGlobal[SceneGlobals::V_Main]); uboOcclusion.set(3, occlusionLut); - uboOcclusion.set(4, *scene.shadowMap[1], Resources::shadowSampler()); + if(quality==VolumetricHQVsm) { + uboOcclusion.set(4, *scene.vsmPageTbl); + uboOcclusion.set(5, *scene.vsmPageData); + } else { + uboOcclusion.set(4, *scene.shadowMap[1], Resources::shadowSampler()); + } uboFogViewLut3d = device.descriptors(Shaders::inst().fogViewLut3d); uboFogViewLut3d.set(0, scene.uboGlobal[SceneGlobals::V_Main]); @@ -438,9 +457,13 @@ void Sky::prepareFog(Tempest::Encoder& cmd, uint32_t fra cmd.dispatchThreads(uint32_t(fogLut3D.w()),uint32_t(fogLut3D.h())); break; } - case VolumetricHQ: { + case VolumetricHQ: + case VolumetricHQVsm: { + const bool vsm = (quality==VolumetricHQVsm); + auto& fogOcclusion = vsm ? Shaders::inst().fogOcclusionVsm : Shaders::inst().fogOcclusion; + cmd.setFramebuffer({}); - cmd.setUniforms(Shaders::inst().fogOcclusion, uboOcclusion, &ubo, sizeof(ubo)); + cmd.setUniforms(fogOcclusion, uboOcclusion, &ubo, sizeof(ubo)); cmd.dispatchThreads(occlusionLut.size()); cmd.setUniforms(Shaders::inst().fogViewLut3d, uboFogViewLut3d, &ubo, sizeof(ubo)); @@ -479,6 +502,7 @@ void Sky::drawFog(Tempest::Encoder& cmd, uint32_t fId) { cmd.setUniforms(Shaders::inst().fog, uboFog, &ubo, sizeof(ubo)); break; case VolumetricHQ: + case VolumetricHQVsm: cmd.setUniforms(Shaders::inst().fog3dHQ, uboFog3d, &ubo, sizeof(ubo)); break; case PathTrace: diff --git a/game/graphics/sky/sky.h b/game/graphics/sky/sky.h index 306c40ac5..2372ad999 100644 --- a/game/graphics/sky/sky.h +++ b/game/graphics/sky/sky.h @@ -48,6 +48,7 @@ class Sky final { None, VolumetricLQ, VolumetricHQ, + VolumetricHQVsm, PathTrace, }; diff --git a/game/graphics/worldview.cpp b/game/graphics/worldview.cpp index 9846f4354..58a7367b2 100644 --- a/game/graphics/worldview.cpp +++ b/game/graphics/worldview.cpp @@ -85,11 +85,12 @@ void WorldView::setShadowMaps(const Tempest::Texture2d* sh[]) { sGlobal.setShadowMap(shadow); } -void WorldView::setVirtualShadowMap(const Tempest::StorageImage& pageData, +void WorldView::setVirtualShadowMap(const Tempest::ZBuffer& pageData, + const Tempest::StorageImage& pageDataCs, const Tempest::StorageImage& pageTbl, const Tempest::StorageImage& pageHiZ, const Tempest::StorageBuffer& pageList) { - sGlobal.setVirtualShadowMap(pageData, pageTbl, pageHiZ, pageList); + sGlobal.setVirtualShadowMap(pageData, pageDataCs, pageTbl, pageHiZ, pageList); } void WorldView::setSwRenderingImage(const Tempest::StorageImage& mainView) { diff --git a/game/graphics/worldview.h b/game/graphics/worldview.h index 1909e1c42..90a941010 100644 --- a/game/graphics/worldview.h +++ b/game/graphics/worldview.h @@ -37,7 +37,8 @@ class WorldView { void setGbuffer(const Tempest::Texture2d& diffuse, const Tempest::Texture2d& norm); void setShadowMaps (const Tempest::Texture2d* shadow[]); - void setVirtualShadowMap(const Tempest::StorageImage& pageData, + void setVirtualShadowMap(const Tempest::ZBuffer& pageData, + const Tempest::StorageImage& pageDataCs, const Tempest::StorageImage& pageTbl, const Tempest::StorageImage& pageHiZ, const Tempest::StorageBuffer& pageList); diff --git a/game/resources.cpp b/game/resources.cpp index 15ace9623..edeb4dffb 100644 --- a/game/resources.cpp +++ b/game/resources.cpp @@ -91,6 +91,9 @@ Resources::Resources(Tempest::Device &device) fbZero = device.texture(pm); } + fbImg = device.image2d(TextureFormat::R32U,1,1); + fbImg3d = device.image3d(TextureFormat::R32U,1,1,1); + // Set up the DirectMusic loader DmResult rv = DmLoader_create(&dmLoader, DmLoader_DOWNLOAD); if(rv != DmResult_SUCCESS) { @@ -283,6 +286,14 @@ const Texture2d &Resources::fallbackBlack() { return inst->fbZero; } +const Tempest::StorageImage& Resources::fallbackImage() { + return inst->fbImg; + } + +const Tempest::StorageImage& Resources::fallbackImage3d() { + return inst->fbImg3d; + } + const zenkit::Vfs& Resources::vdfsIndex() { return inst->gothicAssets; } diff --git a/game/resources.h b/game/resources.h index 36e704d08..f07d3f644 100644 --- a/game/resources.h +++ b/game/resources.h @@ -94,6 +94,8 @@ class Resources final { static const Tempest::Texture2d& fallbackTexture(); static const Tempest::Texture2d& fallbackBlack(); + static auto fallbackImage() -> const Tempest::StorageImage&; + static auto fallbackImage3d() -> const Tempest::StorageImage&; static const Tempest::Texture2d* loadTexture(std::string_view name); static const Tempest::Texture2d* loadTexture(Tempest::Color color); static const Tempest::Texture2d* loadTexture(std::string_view name, int32_t v, int32_t c); @@ -190,6 +192,7 @@ class Resources final { Tempest::VertexBuffer sphere(int passCount, float R); Tempest::Texture2d fallback, fbZero; + Tempest::StorageImage fbImg, fbImg3d; using BindK = std::tuple; using FontK = std::pair; diff --git a/shader/CMakeLists.txt b/shader/CMakeLists.txt index 32107d67f..96e2cb339 100644 --- a/shader/CMakeLists.txt +++ b/shader/CMakeLists.txt @@ -236,8 +236,9 @@ add_shader(clouds_lut.comp sky/clouds_lut.comp) add_shader(fog_view_lut.comp sky/fog_view_lut.comp -DCOMPUTE) -add_shader(fog3d_hq.frag sky/fog.frag -S frag -DVOLUMETRIC_HQ) -add_shader(fog3d.comp sky/fog.frag -S comp -DVOLUMETRIC_HQ -DCOMPUTE) +add_shader(fog3d_hq.frag sky/fog.frag -S frag -DVOLUMETRIC) +add_shader(fog3d.comp sky/fog.frag -S comp -DVOLUMETRIC -DCOMPUTE) +add_shader(fog3d_vsm.comp sky/fog.frag -S comp -DVOLUMETRIC -DCOMPUTE -DVIRTUAL_SHADOW) add_shader(fog.frag sky/fog.frag) add_shader(sky.frag sky/sky.frag) @@ -307,6 +308,7 @@ add_shader(vsm_alloc_pages.comp virtual_shadow/vsm_alloc_pages.comp) add_shader(vsm_pack_draws0.comp virtual_shadow/vsm_pack_draws.comp -DPASS0) add_shader(vsm_pack_draws1.comp virtual_shadow/vsm_pack_draws.comp -DPASS1) add_shader(vsm_cluster_task.comp virtual_shadow/vsm_cluster_task.comp -DVIRTUAL_SHADOW) +add_shader(vsm_list_pages.comp virtual_shadow/vsm_list_pages.comp) add_shader(vsm_rendering.comp virtual_shadow/vsm_rendering.comp) diff --git a/shader/sky/fog.frag b/shader/sky/fog.frag index de759514a..e776aff43 100644 --- a/shader/sky/fog.frag +++ b/shader/sky/fog.frag @@ -3,13 +3,13 @@ #extension GL_GOOGLE_include_directive : enable #extension GL_EXT_control_flow_attributes : enable +#if defined(VIRTUAL_SHADOW) +#include "virtual_shadow/vsm_common.glsl" +#endif + #include "sky_common.glsl" #include "scene.glsl" -#if defined(VOLUMETRIC_HQ) -#define VOLUMETRIC -#endif - #if defined(COMPUTE) layout(local_size_x = 1*8, local_size_y = 2*8) in; vec2 inPos; @@ -30,16 +30,21 @@ layout(binding = 2, std140) uniform UboScene { SceneDesc scene; }; -#if defined(VOLUMETRIC_HQ) && defined(COMPUTE) +#if defined(VOLUMETRIC) && defined(COMPUTE) layout(binding = 3, r32ui) uniform writeonly restrict uimage2D occlusionLut; -#elif defined(VOLUMETRIC_HQ) +#elif defined(VOLUMETRIC) layout(binding = 3, r32ui) uniform readonly restrict uimage2D occlusionLut; #endif -#if defined(VOLUMETRIC_HQ) && defined(COMPUTE) +#if defined(VOLUMETRIC) && !defined(VIRTUAL_SHADOW)&& defined(COMPUTE) layout(binding = 4) uniform sampler2D textureSm1; #endif +#if defined(VOLUMETRIC) && defined(VIRTUAL_SHADOW) && defined(COMPUTE) +layout(binding = 4) uniform utexture3D pageTbl; +layout(binding = 5) uniform texture2D pageData; +#endif + #if defined(COMPUTE) uvec2 invocationID = gl_GlobalInvocationID.xy; #endif @@ -52,7 +57,23 @@ float interleavedGradientNoise() { #endif } -#if defined(VOLUMETRIC_HQ) && defined(COMPUTE) +#if defined(VOLUMETRIC) && defined(VIRTUAL_SHADOW) && defined(COMPUTE) +bool shadowFactor(vec4 shPos) { + vec3 shPos0 = shPos.xyz/shPos.w; + + int mip = VSM_PAGE_MIPS-1; + vec2 page = shPos0.xy / (1<=VSM_PAGE_MIPS) + // return true; + if(any(greaterThan(abs(page), vec2(1)))) + return true; + //return false; + + float v = shadowTexelFetch(page, mip, pageTbl, pageData); + return v < shPos.z; + //return true; + } +#elif defined(VOLUMETRIC) && defined(COMPUTE) float shadowSample(in sampler2D shadowMap, vec2 shPos) { shPos.xy = shPos.xy*vec2(0.5)+vec2(0.5); return textureLod(shadowMap,shPos,0).r; @@ -79,18 +100,24 @@ vec3 project(mat4 m, vec3 pos) { return p.xyz/p.w; } -#if defined(VOLUMETRIC_HQ) +#if defined(VOLUMETRIC) vec4 fog(vec2 uv, float z) { const int steps = 32; const float noise = interleavedGradientNoise()/steps; const float dMin = 0; const float dMax = 0.9999; - const vec3 pos0 = project(scene.viewProjectInv, vec3(inPos,dMin)); - const vec3 pos1 = project(scene.viewProjectInv, vec3(inPos,dMax)); - const vec3 posz = project(scene.viewProjectInv, vec3(inPos,z)); - const vec4 shPos0 = scene.viewShadow[1]*vec4(pos0, 1); - const vec4 shPos1 = scene.viewShadow[1]*vec4(posz, 1); + const vec3 pos0 = project(scene.viewProjectLwcInv, vec3(inPos,dMin)); + const vec3 pos1 = project(scene.viewProjectLwcInv, vec3(inPos,dMax)); + const vec3 posz = project(scene.viewProjectLwcInv, vec3(inPos,z)); + +#if defined(VIRTUAL_SHADOW) + const vec4 shPos0 = scene.viewVirtualShadowLwc*vec4(pos0, 1); + const vec4 shPos1 = scene.viewVirtualShadowLwc*vec4(posz, 1); +#else + const vec4 shPos0 = scene.viewShadowLwc[1]*vec4(pos0, 1); + const vec4 shPos1 = scene.viewShadowLwc[1]*vec4(posz, 1); +#endif const vec3 ray = pos1.xyz - pos0.xyz; const float dist = length(ray)*0.01; // meters diff --git a/shader/virtual_shadow/vsm_alloc_pages.comp b/shader/virtual_shadow/vsm_alloc_pages.comp index ee5f0b79f..34f729d77 100644 --- a/shader/virtual_shadow/vsm_alloc_pages.comp +++ b/shader/virtual_shadow/vsm_alloc_pages.comp @@ -235,7 +235,7 @@ void main() { listPages(); const uint frag = lane4 ? 2 : 3)*2; + const int mergeQ = 5; //(at.z>4 ? 2 : 3)*2; uint a = unpackSamples(data[at.x+0][at.y+0]); uint b = unpackSamples(data[at.x+2][at.y+0]); uint c = unpackSamples(data[at.x+2][at.y+2]); uint d = unpackSamples(data[at.x+0][at.y+2]); uint s = (a+b+c+d); - if(a+b+c+d >= mergeQ) { + + bool denie = (a==0 && b==0) || (c==0 && d==0); // horizontal-only patterns + if(!denie && s >= mergeQ) { data[at.x+0][at.y+0] = packPage(s, 4); data[at.x+2][at.y+0] = packPage(0, 0); data[at.x+0][at.y+2] = packPage(0, 0); @@ -148,12 +150,15 @@ void main() { // demote unfilled quads to 1x1 pages if(true && quad) { - uint s = unpackSize (data[at.x][at.y]); + uint q = unpackSize (data[at.x][at.y]); uint a = unpackPrimeBit(data[at.x+0][at.y+0]); uint b = unpackPrimeBit(data[at.x+1][at.y+0]); uint c = unpackPrimeBit(data[at.x+1][at.y+1]); uint d = unpackPrimeBit(data[at.x+0][at.y+1]); - if(s==2 && a+b+c+d <= 2) { + uint s = (a+b+c+d); + + bool denie = (a==0 && b==0) || (c==0 && d==0); // horizontal-only patterns + if(q==2 && (denie || s<2)) { data[at.x+0][at.y+0] = packPage(1, a, a); data[at.x+1][at.y+0] = packPage(1, b, b); data[at.x+1][at.y+1] = packPage(1, c, c); diff --git a/shader/virtual_shadow/vsm_common.glsl b/shader/virtual_shadow/vsm_common.glsl index c55685a72..caaaf0393 100644 --- a/shader/virtual_shadow/vsm_common.glsl +++ b/shader/virtual_shadow/vsm_common.glsl @@ -1,6 +1,8 @@ #ifndef VSM_COMMON_GLSL #define VSM_COMMON_GLSL +#extension GL_EXT_samplerless_texture_functions : enable + // #define VSM_ATOMIC 1 const int VSM_PAGE_SIZE = 128; @@ -60,4 +62,56 @@ bool vsmPageClip(ivec2 fragCoord, const uint page) { return false; } +float vsmTexelFetch(in utexture2D pageData, const ivec2 pixel) { + return uintBitsToFloat(texelFetch(pageData, pixel, 0).x); + } + +float vsmTexelFetch(in texture2D pageData, const ivec2 pixel) { + return texelFetch(pageData, pixel, 0).x; + } + +float shadowTexelFetch(in vec2 page, in int mip, in utexture3D pageTbl, + #if defined(VSM_ATOMIC) + in utexture2D pageData + #else + in texture2D pageData + #endif + ) { +#if 1 + while(mip>=0) { + if(abs(page.x)>=1 || abs(page.y)>=1) + break; + //page-local + const ivec2 pageI = ivec2((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); + const vec2 pageF = fract((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); + const ivec2 at = ivec2(pageF*VSM_PAGE_SIZE); + + //page-global + const uint pageId = texelFetch(pageTbl, ivec3(pageI, mip), 0).x >> 16u; + if(pageId==0xFFFF) { + page *= 2.0; + --mip; + continue; + } + + const ivec2 pageImageAt = unpackVsmPageId(pageId)*VSM_PAGE_SIZE + at; + return vsmTexelFetch(pageData, pageImageAt); + } + return 0; +#else + //page-local + const ivec2 pageI = ivec2((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); + const vec2 pageF = fract((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); + const ivec2 at = ivec2(pageF*VSM_PAGE_SIZE); + + //page-global + const uint pageId = texelFetch(pageTbl, ivec3(pageI, mip), 0).x >> 16u; + if(pageId==0xFFFF) + return 0; + + const ivec2 pageImageAt = unpackVsmPageId(pageId)*VSM_PAGE_SIZE + at; + return vsmTexelFetch(pageData, pageImageAt); +#endif + } + #endif diff --git a/shader/virtual_shadow/vsm_mark_pages.comp b/shader/virtual_shadow/vsm_mark_pages.comp index c1b5cdc2e..b02ed388c 100644 --- a/shader/virtual_shadow/vsm_mark_pages.comp +++ b/shader/virtual_shadow/vsm_mark_pages.comp @@ -38,7 +38,7 @@ layout(binding = 3) uniform texture2D depth; #if defined(MARK_PAGES) layout(binding = 4, r32ui) uniform uimage3D pageTbl; #elif defined(COMPOSE) || defined(DEBUG) -layout(binding = 4, r32ui) uniform readonly uimage3D pageTbl; +layout(binding = 4) uniform utexture3D pageTbl; # if defined(VSM_ATOMIC) layout(binding = 5) uniform utexture2D pageData; # else @@ -124,22 +124,7 @@ int shadowLod(vec2 dx, vec2 dy) { float shadowTexelFetch(vec2 page, int mip) { #if defined(COMPOSE) || defined(DEBUG) - //page-local - const ivec2 pageI = ivec2((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); - const vec2 pageF = fract((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); - const ivec2 at = ivec2(pageF*VSM_PAGE_SIZE); - - //page-global - const uint pageId = imageLoad(pageTbl, ivec3(pageI, mip)).x >> 16u; - if(pageId==0xFFFF) - return 0; - - const ivec2 pageImageAt = unpackVsmPageId(pageId)*VSM_PAGE_SIZE + at; -# if defined(VSM_ATOMIC) - return uintBitsToFloat(texelFetch(pageData, pageImageAt, 0).x); -# else - return texelFetch(pageData, pageImageAt, 0).x; -# endif + return shadowTexelFetch(page, mip, pageTbl, pageData); #else return (0); #endif @@ -200,6 +185,13 @@ void main() { outColor = vec4(0,0,0, 1); #endif +#if defined(COMPOSE) + if(drawInt(gl_FragCoord.xy-vec2(100), int(vsm.header.pageCount))>0) { + outColor = vec4(1); + return; + } +#endif + const ivec2 size = textureSize(depth, 0); #if defined(GL_COMPUTE_SHADER) if(any(greaterThanEqual(pixelPos, size))) @@ -230,7 +222,7 @@ void main() { page /= 2; mip++; } - if(any(greaterThan(abs(page), vec2(1))) || mip>=16) + if(any(greaterThan(abs(page), vec2(1))) || mip>=VSM_PAGE_MIPS) return; ivec2 pageI = ivec2((page*0.5+0.5)*VSM_PAGE_TBL_SIZE); @@ -240,10 +232,6 @@ void main() { outColor = vec4(directLight(page, mip, shPos0.z), 1); #endif -#if defined(COMPOSE) - outColor.rgb += drawInt(gl_FragCoord.xy-vec2(100), int(vsm.header.pageCount)).xxx; -#endif - #if defined(DEBUG) // int mip = 0; // vec3 color = directLight(page, mip, shPos0.z);