import { GLSL3, RawShaderMaterial } from "three";


// Debug visualisation: shows each voxel's baked OBJECT-space normal as
// RGB. Same world-space-sized camera-facing quad as the unlit V0.
const shader_vx = `
    in vec3 position;
    in vec2 uv;
    in vec3 iPosition;
    in vec3 iNormal;

    out vec2 vUv;
    flat out vec3 vNormal_OS;

    uniform mat4 modelMatrix;
    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;
    uniform float uPointDiameter;

    void main() {
        vUv = uv;
        vNormal_OS = iNormal;

        float model_scale = length(modelMatrix[0].xyz);
        float world_diameter = uPointDiameter * model_scale;
        float radius_OS = uPointDiameter * 0.5;

        // Inward-shift; see VoxelImpostorShaderV0 for rationale.
        vec3 centre_OS = iPosition - iNormal * radius_OS;
        vec4 centre_view = modelViewMatrix * vec4(centre_OS, 1.0);
        vec2 corner = position.xy * world_diameter;
        gl_Position = projectionMatrix * (centre_view + vec4(corner, 0.0, 0.0));
    }
`;

const shader_fg = `
    precision highp float;
    precision highp int;

    in vec2 vUv;
    flat in vec3 vNormal_OS;

    out vec4 color_out;

    uniform bool uDiscMask;

    void main() {
        if (uDiscMask) {
            vec2 c = vUv - 0.5;
            if (dot(c, c) > 0.25) {
                discard;
            }
        }
        color_out = vec4(vNormal_OS * 0.5 + 0.5, 1.0);
    }
`;

export class VoxelImpostorShaderNormalsV0 extends RawShaderMaterial {
    constructor() {
        super({
            vertexShader: shader_vx,
            fragmentShader: shader_fg,
            glslVersion: GLSL3,
            uniforms: {
                uPointDiameter: { value: 0.05 },
                uDiscMask: { value: false }
            }
        });
    }
}
