Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,15 @@ float2 GetInterpolatedHeightRW(float2 pxCoord, bool isVertical)
groupshared float2 g_shadowHeight[NTHREADS];

[numthreads(NTHREADS, 1, 1)] void main(const uint gtid : SV_GroupThreadID, const uint gid : SV_GroupID) {
uint2 dims;
TexHeight.GetDimensions(dims.x, dims.y);
// Two independent coordinate spaces are used here: the heightmap sampling
// space (TexHeight) and the shadow-pixel space (RWTexShadowHeights). The
// CPU path may resize the height texture independently of the shadow
// resolution, so sampling and resizing can be done separately for each
// space. LightPxDir and PxSize are expressed in shadow-pixel units.
uint2 heightDims;
TexHeight.GetDimensions(heightDims.x, heightDims.y);
uint2 shadowDims;
RWTexShadowHeights.GetDimensions(shadowDims.x, shadowDims.y);

bool isVertical = abs(LightPxDir.y) > abs(LightPxDir.x);
float2 lightUVDir = LightPxDir * PxSize;
Expand All @@ -77,18 +84,19 @@ groupshared float2 g_shadowHeight[NTHREADS];
bool isValid = isVertical ? isUVinRange.y : isUVinRange.x;

float2 threadUV = rawThreadUV - floor(rawThreadUV); // wraparound
float2 threadPxCoord = threadUV * dims;
float2 heightPxCoord = threadUV * heightDims;
float2 shadowPxCoord = threadUV * shadowDims;

float2 pastHeights = 0.0;
if (isValid) {
pastHeights = RWTexShadowHeights[uint2(threadPxCoord)];
pastHeights = RWTexShadowHeights[uint2(shadowPxCoord)];

// bifilter
float2 heights = GetInterpolatedHeight(threadPxCoord, isVertical).xx;
float2 heights = GetInterpolatedHeight(heightPxCoord, isVertical).xx;

// fetch last dispatch
if (gtid == 0 && all(floor(rawThreadUV - lightUVDir) == floor(rawThreadUV))) {
float2 sampleHeights = GetInterpolatedHeightRW(threadPxCoord - LightPxDir, isVertical) + LightDeltaZ;
float2 sampleHeights = GetInterpolatedHeightRW(shadowPxCoord - LightPxDir, isVertical) + LightDeltaZ;
heights = heights.x > sampleHeights.x ? heights : sampleHeights;
}

Expand All @@ -113,6 +121,6 @@ groupshared float2 g_shadowHeight[NTHREADS];

// save
if (isValid) {
RWTexShadowHeights[uint2(threadPxCoord)] = lerp(pastHeights, g_shadowHeight[gtid], 0.5f);
RWTexShadowHeights[uint2(shadowPxCoord)] = lerp(pastHeights, g_shadowHeight[gtid], 0.5f);
}
}
21 changes: 17 additions & 4 deletions src/Features/TerrainShadows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,17 @@ void TerrainShadows::LoadHeightmap()
std::filesystem::path path{ target_heightmap.dir };
path /= target_heightmap.filename;

DX::ThrowIfFailed(LoadFromDDSFile(path.c_str(), DirectX::DDS_FLAGS_NONE, nullptr, image));
DirectX::ScratchImage rawImage;
DX::ThrowIfFailed(LoadFromDDSFile(path.c_str(), DirectX::DDS_FLAGS_NONE, nullptr, rawImage));

// Downscale heightmap to 1/2 resolution per axis to match the
// shadow texture and speed up full shadow updates by ~4x.
auto& rawMeta = rawImage.GetMetadata();
size_t newWidth = std::max<size_t>(1, rawMeta.width / 2);
size_t newHeight = std::max<size_t>(1, rawMeta.height / 2);
DX::ThrowIfFailed(DirectX::Resize(
rawImage.GetImages(), rawImage.GetImageCount(), rawMeta,
newWidth, newHeight, DirectX::TEX_FILTER_LINEAR, image));
Comment thread
doodlum marked this conversation as resolved.
} catch (const DX::com_exception& e) {
logger::error("{}", e.what());
return;
Expand Down Expand Up @@ -333,8 +343,11 @@ void TerrainShadows::UpdateShadow()
TracyD3D11Zone(globals::state->tracyCtx, "Terrain Occlusion - Update Shadows");

/* ---- UPDATE CB ---- */
uint width = texHeightMap->desc.Width;
uint height = texHeightMap->desc.Height;
// Shadow texture is 1/2 heightmap resolution per axis; ray stepping,
// dispatch and PxSize all operate in shadow-pixel space, while the
// shader still samples the full-res heightmap via UV.
uint width = texShadowHeight->desc.Width;
uint height = texShadowHeight->desc.Height;

// only update direction at the start of each cycle
static uint edgePxCoord;
Expand Down Expand Up @@ -380,7 +393,7 @@ void TerrainShadows::UpdateShadow()
}

shadowUpdateCBData.StartPxCoord = edgePxCoord + signDir * shadowUpdateIdx * updateLength;
shadowUpdateCBData.PxSize = { 1.f / texHeightMap->desc.Width, 1.f / texHeightMap->desc.Height };
shadowUpdateCBData.PxSize = { 1.f / width, 1.f / height };

shadowUpdateCBData.PosRange = { cachedHeightmap->pos0.z, cachedHeightmap->pos1.z };
shadowUpdateCBData.ZRange = cachedHeightmap->zRange;
Expand Down
Loading