struct VertexInput { @location(0) position: vec3, @location(1) normal: vec3, @location(2) uv: vec2, @location(3) block: vec3, @location(4) material: f32, }; struct VertexOutput { @builtin(position) position: vec4, @location(0) tint: vec3, @location(1) uv: vec2, @location(2) visibility: f32, @location(3) material: f32, }; struct Uniforms { proj: mat4x4, view: mat4x4, skyColor: vec3, cameraPos: vec3, raycast: vec3, renderDistance: f32, }; @group(0) @binding(0) var uniforms: Uniforms; @group(1) @binding(0) var tran: mat4x4; @vertex fn vs_main(input: VertexInput) -> VertexOutput { var output: VertexOutput; var worldPosition = tran * vec4(input.position, 1.0); output.position = uniforms.proj * uniforms.view * worldPosition; output.tint = vec3(dot(abs(input.normal), vec3(0.8, 0.9, 0.75))); output.uv = input.uv; output.material = input.material; var dist = distance(uniforms.cameraPos.xz, worldPosition.xz); var visibility = 1.0; var fogDepth = 16.0; if (dist / fogDepth > uniforms.renderDistance - 2) { visibility = 1 - (dist - (fogDepth * (uniforms.renderDistance - 2))) / fogDepth; } output.visibility = clamp(visibility, 0.0, 1.0); if (all(uniforms.raycast == input.block)) { output.tint = vec3(1.2); } return output; } @group(0) @binding(1) var texSampler: sampler; @group(0) @binding(2) var texture: texture_2d_array; @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4 { var color = vec4(input.tint, 1.0) * textureSample(texture, texSampler, input.uv, i32(input.material)); var skyColor = vec4(uniforms.skyColor, 1.0); return mix(skyColor, color, input.visibility); }