Mega-buffer architecture replacing per-chunk GPU buffers: - Single StructuredBuffer<PackedQuad> for all chunks (2M quads, 16 MB) - StructuredBuffer<GPUChunkInfo> with per-chunk metadata (position, quad offsets, face groups) - VS reads chunk info via push constants (b999) for driver-safe chunk indexing - CPU frustum culling with wi::primitive::Frustum + AABB per chunk - Quads sorted by face direction in greedy mesher (faceOffsets/faceCounts) - GPU frustum + backface cull compute shader (voxelCullCS.hlsl) - GPU binary mesher compute shader baseline (voxelMeshCS.hlsl) - Indirect draw buffers and timestamp query infrastructure - README with build instructions and project architecture
83 lines
2.8 KiB
HLSL
83 lines
2.8 KiB
HLSL
// BVLE Voxels - Pixel Shader (Triplanar textured with simple lighting)
|
|
|
|
#include "voxelCommon.hlsli"
|
|
|
|
Texture2DArray materialTextures : register(t1);
|
|
SamplerState materialSampler : register(s0);
|
|
|
|
struct PSInput {
|
|
float4 position : SV_POSITION;
|
|
float3 worldPos : WORLDPOS;
|
|
float3 normal : NORMAL;
|
|
float2 uv : TEXCOORD0;
|
|
nointerpolation uint materialID : MATERIALID;
|
|
nointerpolation uint faceID : FACEID;
|
|
nointerpolation float debugFlag : DEBUGFLAG;
|
|
float ao : AO;
|
|
};
|
|
|
|
// Triplanar blend weights
|
|
float3 triplanarWeights(float3 normal, float sharpness) {
|
|
float3 w = abs(normal);
|
|
w = pow(w, (float3)sharpness);
|
|
return w / (w.x + w.y + w.z + 0.0001);
|
|
}
|
|
|
|
float3 sampleTriplanar(float3 worldPos, float3 normal, uint texIndex, float tiling) {
|
|
float3 w = triplanarWeights(normal, 4.0);
|
|
|
|
float3 colX = materialTextures.Sample(materialSampler, float3(worldPos.yz * tiling, (float)texIndex)).rgb;
|
|
float3 colY = materialTextures.Sample(materialSampler, float3(worldPos.xz * tiling, (float)texIndex)).rgb;
|
|
float3 colZ = materialTextures.Sample(materialSampler, float3(worldPos.xy * tiling, (float)texIndex)).rgb;
|
|
|
|
return colX * w.x + colY * w.y + colZ * w.z;
|
|
}
|
|
|
|
// Debug face colors
|
|
static const float3 faceDebugColors[6] = {
|
|
float3(1.0, 0.2, 0.2), // 0: +X = RED
|
|
float3(0.5, 0.0, 0.0), // 1: -X = DARK RED
|
|
float3(0.2, 1.0, 0.2), // 2: +Y = GREEN
|
|
float3(0.0, 0.5, 0.0), // 3: -Y = DARK GREEN
|
|
float3(0.2, 0.2, 1.0), // 4: +Z = BLUE
|
|
float3(0.0, 0.0, 0.5), // 5: -Z = DARK BLUE
|
|
};
|
|
|
|
[RootSignature(VOXEL_ROOTSIG)]
|
|
float4 main(PSInput input) : SV_TARGET0
|
|
{
|
|
// ── DEBUG MODE: face direction colors ──
|
|
if (input.debugFlag > 0.5)
|
|
{
|
|
uint fid = min(input.faceID, 5u);
|
|
float3 faceColor = faceDebugColors[fid];
|
|
float2 checker = floor(input.worldPos.xz * 0.5);
|
|
float check = frac((checker.x + checker.y) * 0.5) * 2.0;
|
|
faceColor *= (0.85 + 0.15 * check);
|
|
return float4(faceColor, 1.0);
|
|
}
|
|
|
|
// ── NORMAL MODE: triplanar textured ──
|
|
float3 N = normalize(input.normal);
|
|
float3 L = normalize(-sunDirection.xyz);
|
|
float NdotL = max(dot(N, L), 0.0);
|
|
|
|
float3 baseColor = N * 0.5 + 0.5;
|
|
|
|
uint texIndex = clamp(input.materialID - 1u, 0u, 4u);
|
|
float tiling = textureTiling;
|
|
float3 texColor = sampleTriplanar(input.worldPos, N, texIndex, tiling);
|
|
|
|
float3 albedo = (input.materialID > 0u) ? texColor : baseColor;
|
|
|
|
float3 ambient = float3(0.15, 0.18, 0.25);
|
|
float3 diffuse = sunColor.rgb * NdotL;
|
|
float3 color = albedo * (ambient + diffuse) * input.ao;
|
|
|
|
float dist = length(input.worldPos - cameraPosition.xyz);
|
|
float fog = 1.0 - exp(-dist * 0.003);
|
|
float3 fogColor = float3(0.55, 0.70, 0.90);
|
|
color = lerp(color, fogColor, saturate(fog));
|
|
|
|
return float4(color, 1.0);
|
|
}
|