58 lines
2.1 KiB
HLSL
58 lines
2.1 KiB
HLSL
|
|
// BVLE Voxels - Smooth Surface Nets Pixel Shader (Phase 5.1)
|
||
|
|
// Triplanar texture sampling + material blending + same lighting as voxel PS.
|
||
|
|
|
||
|
|
#include "voxelCommon.hlsli"
|
||
|
|
|
||
|
|
Texture2DArray<float4> 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);
|
||
|
|
}
|