mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 11:26:00 +03:00
184 lines
5.9 KiB
GLSL
184 lines
5.9 KiB
GLSL
#version 460
|
|
|
|
#include "common_shader.glsl"
|
|
|
|
layout (set = 0, binding = 0) uniform UniformFrameData { PerFrameData frameData; };
|
|
|
|
// Ready lod node for terrain, .xy is position of 2d, .z is lod level.
|
|
layout (set = 0, binding = 1) buffer SSBOLODReadyNodeList { uvec3 data[]; } ssboReadyLodNodeList;
|
|
layout (set = 0, binding = 2) buffer SSBOLODReadyNodeListCount { uint counter; } ssboReadyLodNodeListCounter;
|
|
|
|
// Counter for current lod level which need continue sperate. (size = frameData.landscape.lodCount - 2)
|
|
layout (set = 0, binding = 3) buffer SSBOLODRenderCount { uint counter[]; } ssboLODContinueCounters;
|
|
|
|
// Store temporal buffer of current lod.
|
|
layout (set = 0, binding = 4) buffer SSBOLODContinueBufferRead { uvec2 data[]; } ssboLODContinueBufferRead;
|
|
layout (set = 0, binding = 5) buffer SSBOLODContinueBufferWrite { uvec2 data[]; } ssboLODContinueBufferWrite;
|
|
|
|
|
|
struct DispatchIndirectCommand
|
|
{
|
|
uint x;
|
|
uint y;
|
|
uint z;
|
|
uint pad;
|
|
};
|
|
|
|
layout (set = 0, binding = 6) buffer lodDispatchCmdSSBO
|
|
{
|
|
DispatchIndirectCommand args;
|
|
} lodDispatchCmd;
|
|
|
|
layout (set = 0, binding = 7) buffer patchDispatchCmdSSBO
|
|
{
|
|
DispatchIndirectCommand args;
|
|
} patchDispatchCmd;
|
|
|
|
layout (set = 0, binding = 8) uniform texture2D imageHeightFieldMipmap;
|
|
|
|
layout (set = 0, binding = 9) buffer lodNodeContinueSSBO
|
|
{
|
|
uint data[];
|
|
} lodNodeContinue;
|
|
|
|
layout(push_constant) uniform PushConsts
|
|
{
|
|
uint lodIndex; // from (frameData.landscape.lodCount - 1) to 1.
|
|
float coefficientLodContinue;
|
|
uint maxLodMipmap;
|
|
} terrainPush;
|
|
|
|
#ifdef LOD_PATH_PASS
|
|
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
|
void main()
|
|
{
|
|
uint nodeCount = ssboReadyLodNodeListCounter.counter;
|
|
|
|
patchDispatchCmd.args.x = nodeCount;
|
|
patchDispatchCmd.args.y = 1;
|
|
patchDispatchCmd.args.z = 1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef LOD_ARGS_PASS
|
|
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
|
void main()
|
|
{
|
|
uint level = frameData.landscape.lodCount - terrainPush.lodIndex - 1;
|
|
uint nodeCount = ssboLODContinueCounters.counter[level - 1];
|
|
|
|
lodDispatchCmd.args.x = (nodeCount + 63) / 64;
|
|
lodDispatchCmd.args.y = 1;
|
|
lodDispatchCmd.args.z = 1;
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef LOD_PREPARE_PASS
|
|
|
|
bool shouldContinueCurrentLOD(uvec2 lodNodePos, uint level)
|
|
{
|
|
float tileDim = getTerrainLODSizeFromLOD(terrainPush.lodIndex);
|
|
vec2 pos2D = vec2(lodNodePos + 0.5) * tileDim + vec2(frameData.landscape.offsetX, frameData.landscape.offsetY);
|
|
|
|
vec3 worldPos = vec3(pos2D.x, 0.0f, pos2D.y);
|
|
|
|
vec2 localSampleUv = vec2(worldPos.x - frameData.landscape.offsetX, worldPos.z - frameData.landscape.offsetY) / frameData.landscape.terrainDimension;
|
|
localSampleUv = saturate(localSampleUv);
|
|
|
|
//
|
|
int workLevel = max(0, int(terrainPush.maxLodMipmap) - 2 - int(level));
|
|
ivec2 levelSize = textureSize(imageHeightFieldMipmap, workLevel);
|
|
ivec2 localPos = ivec2(levelSize * localSampleUv + 0.5);
|
|
|
|
vec2 minMax = texelFetch(imageHeightFieldMipmap, localPos, workLevel).xy;
|
|
|
|
|
|
// Evaluate 3 mode to get best lod quality.
|
|
float cH = mix(frameData.landscape.minHeight, frameData.landscape.maxHeight, (minMax.x + minMax.y) * 0.5);
|
|
float lH = mix(frameData.landscape.minHeight, frameData.landscape.maxHeight, minMax.x);
|
|
float tH = mix(frameData.landscape.minHeight, frameData.landscape.maxHeight, minMax.y);
|
|
|
|
worldPos.y = cH;
|
|
float dist = distance(frameData.camWorldPos.xyz, worldPos);
|
|
|
|
worldPos.y = lH;
|
|
dist = min(dist, distance(frameData.camWorldPos.xyz, worldPos));
|
|
|
|
worldPos.y = tH;
|
|
dist = min(dist, distance(frameData.camWorldPos.xyz, worldPos));
|
|
|
|
|
|
float factor = dist / (tileDim * terrainPush.coefficientLodContinue);
|
|
return factor < 1.0f;
|
|
}
|
|
|
|
layout (local_size_x = 64) in;
|
|
void main()
|
|
{
|
|
uint idx = gl_GlobalInvocationID.x;
|
|
uint level = frameData.landscape.lodCount - terrainPush.lodIndex - 1;
|
|
|
|
const bool bLoopPass = (level > 0);
|
|
|
|
// Default from 0, which need evaluate all node.
|
|
uint nodeCount = kTerrainCoarseNodeDim * kTerrainCoarseNodeDim;
|
|
if (bLoopPass)
|
|
{
|
|
// Evaluate from counter.
|
|
nodeCount = ssboLODContinueCounters.counter[level - 1];
|
|
}
|
|
|
|
// Pre-return.
|
|
if (idx >= nodeCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uvec2 lodNodePos = uvec2(idx % kTerrainCoarseNodeDim, idx / kTerrainCoarseNodeDim);
|
|
if (bLoopPass)
|
|
{
|
|
lodNodePos = ssboLODContinueBufferRead.data[idx];
|
|
}
|
|
|
|
|
|
|
|
int lodNodeId = int((16 * (1 - pow(4, int(level)))) / -3) + int(lodNodePos.y * 4 * exp2(level) + lodNodePos.x);
|
|
|
|
if(shouldContinueCurrentLOD(lodNodePos, level))
|
|
{
|
|
if (terrainPush.lodIndex == 1)
|
|
{
|
|
// lod #1, so just add to final
|
|
uint indexId = atomicAdd(ssboReadyLodNodeListCounter.counter, 4);
|
|
|
|
ssboReadyLodNodeList.data[indexId + 0] = uvec3(lodNodePos * 2 + uvec2(0, 0), 0);
|
|
ssboReadyLodNodeList.data[indexId + 1] = uvec3(lodNodePos * 2 + uvec2(0, 1), 0);
|
|
ssboReadyLodNodeList.data[indexId + 2] = uvec3(lodNodePos * 2 + uvec2(1, 0), 0);
|
|
ssboReadyLodNodeList.data[indexId + 3] = uvec3(lodNodePos * 2 + uvec2(1, 1), 0);
|
|
}
|
|
else
|
|
{
|
|
uint indexId = atomicAdd(ssboLODContinueCounters.counter[level], 4);
|
|
|
|
ssboLODContinueBufferWrite.data[indexId + 0] = lodNodePos * 2 + uvec2(0, 0);
|
|
ssboLODContinueBufferWrite.data[indexId + 1] = lodNodePos * 2 + uvec2(0, 1);
|
|
ssboLODContinueBufferWrite.data[indexId + 2] = lodNodePos * 2 + uvec2(1, 0);
|
|
ssboLODContinueBufferWrite.data[indexId + 3] = lodNodePos * 2 + uvec2(1, 1);
|
|
}
|
|
|
|
lodNodeContinue.data[lodNodeId] = 1;
|
|
}
|
|
else
|
|
{
|
|
// Don't need continue, just use current lod.
|
|
uint indexId = atomicAdd(ssboReadyLodNodeListCounter.counter, 1);
|
|
ssboReadyLodNodeList.data[indexId] = uvec3(lodNodePos, terrainPush.lodIndex);
|
|
|
|
|
|
lodNodeContinue.data[lodNodeId] = 0;
|
|
}
|
|
|
|
|
|
}
|
|
#endif |