bvle-voxels/shaders/voxelCommon.hlsli

130 lines
6.6 KiB
HLSL
Raw Permalink Normal View History

// BVLE Voxels - Shared shader definitions
// Root signature, common structures, and constant buffers for voxel shaders.
#ifndef VOXEL_COMMON_HLSLI
#define VOXEL_COMMON_HLSLI
// Wicked Engine DX12 root signature (HLSL 6.6+ bindless model)
// b999: push constants (12 x uint32 = 48 bytes)
// b0-b2: root CBV descriptors
// t0-t15, u0-u15: SRV/UAV descriptor table
// s0-s7: dynamic samplers
// s100+: static samplers
#define VOXEL_ROOTSIG \
"RootFlags(CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED | SAMPLER_HEAP_DIRECTLY_INDEXED), " \
"RootConstants(num32BitConstants=12, b999), " \
"CBV(b0), " \
"CBV(b1), " \
"CBV(b2), " \
"DescriptorTable( " \
"CBV(b3, numDescriptors = 11, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE)," \
"SRV(t0, numDescriptors = 16, flags = DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE)," \
"UAV(u0, numDescriptors = 16, flags = DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE)" \
")," \
"DescriptorTable( " \
"Sampler(s0, offset = 0, numDescriptors = 8, flags = DESCRIPTORS_VOLATILE)" \
")," \
"StaticSampler(s100, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_LINEAR)," \
"StaticSampler(s101, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_MIN_MAG_MIP_LINEAR)," \
"StaticSampler(s102, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_MIN_MAG_MIP_LINEAR)," \
"StaticSampler(s103, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_POINT)," \
"StaticSampler(s104, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_MIN_MAG_MIP_POINT)," \
"StaticSampler(s105, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_MIN_MAG_MIP_POINT)," \
"StaticSampler(s106, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \
"StaticSampler(s107, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \
"StaticSampler(s108, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \
"StaticSampler(s109, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, comparisonFunc = COMPARISON_GREATER_EQUAL),"
// ── Per-frame constant buffer (b0) ──────────────────────────────
cbuffer VoxelCB : register(b0) {
float4x4 viewProjection;
float4x4 inverseViewProjection; // for depth-to-world reconstruction (RT shadows)
float4x4 prevViewProjection; // previous frame's VP for temporal reprojection (RT AO)
float4 cameraPosition;
float4 sunDirection;
float4 sunColor;
float chunkSize;
float textureTiling;
float blendEnabled;
float debugBlend; // >0.5 = show blend zones as debug colors
// Frustum culling data (used by cull compute shader)
float4 frustumPlanes[6]; // ax+by+cz+d=0, xyz=normal, w=distance
uint chunkCount;
uint bleedMask; // bit N set = material N can bleed onto neighbors
uint resistBleedMask; // bit N set = material N resists bleed from neighbors
2026-03-26 18:58:19 +01:00
float windTime; // elapsed time for wind animation (seconds)
// ── Stylized lighting (Phase 7) ──
float4 skyAmbient; // hemisphere ambient: sky (top) color
float4 groundAmbient; // hemisphere ambient: ground (bottom) color
float4 shadowTint; // colored shadow tint (blue-violet)
float4 fogColor; // atmospheric fog color
float4 fogParams; // x=density, y=unused, z=unused, w=unused
float4 rimColor; // rim/fresnel light color
float4 rimParams; // x=exponent, y=intensity, z=unused, w=unused
float4 toneMapParams; // x=saturation boost, y=exposure, z=unused, w=unused
};
// ── Indirect draw args (must match C++ IndirectDrawArgs, 20 bytes) ──
// Wicked Engine's DrawInstancedIndirectCount command signature includes a push
// constant (1 × uint32 at b999[0]) BEFORE each D3D12_DRAW_ARGUMENTS.
// Total stride = 4 + 16 = 20 bytes per draw entry.
struct IndirectDrawArgsInstanced {
uint pushConstant; // written to b999[0] by ExecuteIndirect
uint vertexCountPerInstance;
uint instanceCount;
uint startVertexLocation;
uint startInstanceLocation;
};
// ── GPU chunk info (must match C++ GPUChunkInfo, 112 bytes) ─────
// NOTE: No arrays — scalar-only to guarantee C-style packing in StructuredBuffer.
struct GPUChunkInfo {
float4 worldPos; // xyz = chunk origin in world space, w = debug flag
uint quadOffset; // offset into mega quad buffer (in quads)
uint quadCount; // number of quads for this chunk
uint _pad0;
uint _pad1;
// Per-face data (6 faces: +X -X +Y -Y +Z -Z)
uint faceOff0, faceOff1, faceOff2, faceOff3, faceOff4, faceOff5;
uint faceCnt0, faceCnt1, faceCnt2, faceCnt3, faceCnt4, faceCnt5;
// Face neighbor chunk indices (0xFFFFFFFF = no neighbor)
uint neighbor0, neighbor1, neighbor2, neighbor3, neighbor4, neighbor5; // +X,-X,+Y,-Y,+Z,-Z
uint _pad2, _pad3;
};
// Helper functions to access scalar face fields by index
uint getFaceOffset(GPUChunkInfo info, uint f) {
switch (f) {
case 0: return info.faceOff0;
case 1: return info.faceOff1;
case 2: return info.faceOff2;
case 3: return info.faceOff3;
case 4: return info.faceOff4;
default: return info.faceOff5;
}
}
uint getFaceCount(GPUChunkInfo info, uint f) {
switch (f) {
case 0: return info.faceCnt0;
case 1: return info.faceCnt1;
case 2: return info.faceCnt2;
case 3: return info.faceCnt3;
case 4: return info.faceCnt4;
default: return info.faceCnt5;
}
}
uint getNeighborIdx(GPUChunkInfo info, uint f) {
switch (f) {
case 0: return info.neighbor0; // +X
case 1: return info.neighbor1; // -X
case 2: return info.neighbor2; // +Y
case 3: return info.neighbor3; // -Y
case 4: return info.neighbor4; // +Z
default: return info.neighbor5; // -Z
}
}
#endif // VOXEL_COMMON_HLSLI