Skip to content

Commit

Permalink
vsm: better lod; camera fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Try committed Sep 10, 2024
1 parent 00ae46b commit c8c7ddc
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 95 deletions.
104 changes: 23 additions & 81 deletions game/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ Matrix4x4 Camera::projective() const {
Matrix4x4 Camera::viewShadowLwc(const Tempest::Vec3& lightDir, size_t layer) const {
auto vp = viewProjLwc();
float rotation = (180+src.spin.y-rotOffset.y);
//if(layer==0)
// return viewShadowVsm(cameraPos-origin,rotation,vp,lightDir);
// if(layer==0)
// return viewShadowVsm(cameraPos-origin,rotation,vp,lightDir);
return mkViewShadow(cameraPos-origin,rotation,vp,lightDir,layer);
}

Expand All @@ -277,100 +277,42 @@ Matrix4x4 Camera::viewShadowVsm(const Tempest::Vec3& lightDir) const {
return viewShadowVsm(cameraPos,rotation,vp,lightDir);
}

Matrix4x4 Camera::viewShadowVsm(const Vec3& cameraPos, float rotation, const Tempest::Matrix4x4& viewProj, const Vec3& lightDir) const {
Vec3 ldir = lightDir;
float eps = 0.005f;

if(std::abs(ldir.y)<eps) {
float k = (1.f-eps*eps)/std::sqrt(ldir.x*ldir.x + ldir.z*ldir.z);
ldir.y = (ldir.y<0) ? -eps : eps;
ldir.x *= k;
ldir.z *= k;
}

Vec3 center = cameraPos;
auto vp = viewProj;
vp.project(center);

vp.inverse();
Vec3 l = {-1,center.y,center.z}, r = {1,center.y,center.z};
vp.project(l);
vp.project(r);

Matrix4x4 Camera::viewShadowVsm(const Vec3& cameraPos, float rotation, const Tempest::Matrix4x4& viewProj, const Vec3& ldir) const {
float smWidth = 1024; // ~4 pixels per santimeter
float smDepth = 5120;
float smDepth = 10*5120;
(void)rotation;

float smWidthInv = 1.f/smWidth;
float zScale = 1.f/smDepth;

rotation = 0;
auto up = std::abs(ldir.z)<0.999 ? Vec3(0,0,1) : Vec3(1,0,0);
auto z = ldir;
auto x = Vec3::normalize(Vec3::crossProduct(z, up));
auto y = Vec3::crossProduct(x, z);

auto view = Matrix4x4 {
-1, 0, 0, 0,
0, 0, -1, 0,
0, +1, 0, 0,
0, 0, 0, 1
};
view.rotateOY(rotation);
view.scale(smWidthInv, zScale, smWidthInv);
view.translate(-cameraPos);

x.x, y.x, z.x, 0,
x.y, y.y, z.y, 0,
x.z, y.z, z.z, 0,
0, 0, 0, 1
};
view.transpose();
{
auto up = std::abs(ldir.z)<0.999 ? Vec3(0,0,1) : Vec3(1,0,0);
auto z = ldir;
auto x = Vec3::normalize(Vec3::crossProduct(z, up));
auto y = Vec3::crossProduct(x, z);

auto view2 = Matrix4x4 {
x.x, y.x, z.x, 0,
x.y, y.y, z.y, 0,
x.z, y.z, z.z, 0,
0, 0, 0, 1
};
view2.transpose();
//view2.rotate(rotation, 0, 1, 0);
view2.scale(smWidthInv, zScale, smWidthInv);
view2.translate(-cameraPos);

static bool rel = true;
if(rel)
view = view2;
Matrix4x4 scale;
scale.identity();
scale.scale(smWidthInv, smWidthInv, zScale);
scale.mul(view);
view = scale;
}
view.translate(-cameraPos);

// sun direction
if(false && ldir.y!=0.f) {
float lx = ldir.x/std::abs(ldir.y);
float lz = ldir.z/std::abs(ldir.y);

const float ang = -rotation*float(M_PI)/180.f;
const float c = std::cos(ang), s = std::sin(ang);

float dx = lx*c-lz*s;
float dz = lx*s+lz*c;

view.set(1,0, dx*smWidthInv);
view.set(1,1, dz*smWidthInv);
}

auto inv = view;
inv.inverse();
Vec3 mid = {};
inv.project(mid);
view.translate(mid-cameraPos);

if(false) {
Matrix4x4 proj;
proj.identity();
proj.translate(0.f, 0.8f, 0.5f);
proj.mul(view);
view = proj;
} else {
{
Matrix4x4 proj;
proj.identity();
proj.translate(0.f, 0.f, 0.5f);
proj.mul(view);
view = proj;
}
}

return view;
}
Expand Down
5 changes: 3 additions & 2 deletions game/graphics/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,8 @@ void Renderer::dbgDraw(Tempest::Painter& p) {
//tex.push_back(&textureCast(hiz.smProj));
//tex.push_back(&textureCast(hiz.hiZSm1));
//tex.push_back(&textureCast(shadowMap[1]));
//tex.push_back(&textureCast(shadowMap[0]));
tex.push_back(&textureCast<const Texture2d&>(vsm.pageDataZ));
tex.push_back(&textureCast<const Texture2d&>(shadowMap[0]));
//tex.push_back(&textureCast<const Texture2d&>(vsm.pageDataZ));

static int size = 400;
int left = 10;
Expand Down Expand Up @@ -851,6 +851,7 @@ void Renderer::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t fI
cmd.setUniforms(*vsm.pagesListPso, vsm.uboList);
cmd.dispatchThreads(size_t(vsm.pageTbl.w()), size_t(vsm.pageTbl.h()), size_t(vsm.pageTbl.d()));
// sort for debug purpose only
cmd.setDebugMarker("VSM-sort(debug)");
cmd.setUniforms(Shaders::inst().vsmSortPages, vsm.uboList);
cmd.dispatch(1);

Expand Down
8 changes: 4 additions & 4 deletions shader/virtual_shadow/vsm_cluster_task.comp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ bool projectSphere(const vec4 sphere, out vec4 aabb, out float depthMin) {
const vec3 c = (scene.viewProject * vec4(sphere.xyz, 1)).xyz;
const float R = sphere.w;

const float smWidthInv = 1.0/1024.0; // NOTE: from camera.cpp
const float zScale = 1.0/5120.0;
const float smWidthInv = 1.0/(1024.0); // NOTE: from camera.cpp
const float zScale = 1.0/(10*5120.0);

float Rz = R * zScale;
if(c.z - Rz > 1 || c.z + Rz < 0)
Expand Down Expand Up @@ -107,8 +107,8 @@ void runCluster(const uint clusterId) {
if(cluster.sphere.w<=0.f)
return; // disabled or deleted

if(!frustrumTest(cluster.sphere))
return;
//if(!frustrumTest(cluster.sphere))
// return;

vec4 aabb = vec4(0);
float depthMin = 1;
Expand Down
24 changes: 16 additions & 8 deletions shader/virtual_shadow/vsm_mark_pages.comp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,28 @@ float shadowTexelFetch(vec2 page, int mip) {
}

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

void markPage(ivec2 pageI, int mip){
void markPage(ivec2 pageI, int mip) {
#if defined(MARK_PAGES)
//imageAtomicAdd(pageTbl, ivec3(pageI, mip), 1u);
imageStore(pageTbl, ivec3(pageI, mip), uvec4(1u));
#endif
}

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 = -1;
return int((minLod + maxLod)*0.5 + bias + 0.5);
}

void main() {
#if defined(DEBUG)
outColor = vec4(0,0,0, 1);
Expand All @@ -117,11 +128,8 @@ void main() {
vec2 shPos1 = shadowPos(z, ivec2(1,0)).xy;
vec2 shPos2 = shadowPos(z, ivec2(0,1)).xy;

float dX = length(shPos1 - shPos0.xy)*VSM_CLIPMAP_SIZE;
float dY = length(shPos2 - shPos0.xy)*VSM_CLIPMAP_SIZE;
float dXY = (dX + dY)*0.5;

int mip = int(clamp(log2(dXY), 0, 32)); // ~7 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;
Expand All @@ -140,7 +148,7 @@ void main() {
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);
color *= (shadowTest(page, mip, shPos0.z)*0.9+0.1);
// vec3 color = vec3(shPos0, 0);
// vec3 color = vec3(page, 0);
// vec3 color = vec3(fract(page*VSM_PAGE_TBL_SIZE), 0);
Expand Down

0 comments on commit c8c7ddc

Please sign in to comment.