// BVLE Voxels - Smooth Surface Nets Pixel Shader (Phase 5.1) // Triplanar texture sampling + material blending + same lighting as voxel PS. #include "voxelCommon.hlsli" Texture2DArray materialTextures : register(t1); SamplerState texSampler : register(s0); struct PSInput { float4 position : SV_POSITION; float3 worldPos : WORLDPOS; float3 normal : NORMAL; nointerpolation uint matPacked : MATERIALID; }; // Sample triplanar texture for a given material index float3 sampleTriplanar(float3 worldPos, float3 blend, float tiling, uint matIdx) { uint texIdx = clamp(matIdx - 1u, 0u, 5u); float4 xS = materialTextures.Sample(texSampler, float3(worldPos.yz * tiling, (float)texIdx)); float4 yS = materialTextures.Sample(texSampler, float3(worldPos.xz * tiling, (float)texIdx)); float4 zS = materialTextures.Sample(texSampler, float3(worldPos.xy * tiling, (float)texIdx)); return xS.rgb * blend.x + yS.rgb * blend.y + zS.rgb * blend.z; } [RootSignature(VOXEL_ROOTSIG)] float4 main(PSInput input) : SV_TARGET0 { float3 N = normalize(input.normal); float tiling = textureTiling; // Unpack materials: materialID(8) | secondaryMat(8) | blendWeight(8) | pad(8) uint primaryMat = input.matPacked & 0xFF; uint secondaryMat = (input.matPacked >> 8) & 0xFF; float blendWeight = ((input.matPacked >> 16) & 0xFF) / 255.0; // Triplanar blend weights float3 blend = abs(N); blend = blend / (blend.x + blend.y + blend.z + 0.001); // Sample primary and secondary materials float3 primaryColor = sampleTriplanar(input.worldPos, blend, tiling, primaryMat); float3 texColor; if (blendWeight > 0.01 && secondaryMat != primaryMat) { float3 secondaryColor = sampleTriplanar(input.worldPos, blend, tiling, secondaryMat); texColor = lerp(primaryColor, secondaryColor, blendWeight); } else { texColor = primaryColor; } // Lighting (same model as voxel PS) float3 L = normalize(-sunDirection.xyz); float NdotL = max(dot(N, L), 0.0); float3 ambient = float3(0.15, 0.18, 0.25); float3 lit = texColor * (sunColor.rgb * NdotL + ambient); return float4(lit, 1.0); }