import { Texture, Color, Matrix4, Vector3, Vector4, Mesh, ShaderMaterial } from 'three';

/**
 * Uniforms interface for the fire shader
 */
interface FireShaderUniforms {
    /** Fire texture (grayscale mask) */
    fireTex: {
        value: Texture | null;
    };
    /** Fire color tint */
    color: {
        value: Color;
    };
    /** Current time for animation */
    time: {
        value: number;
    };
    /** Random seed for fire variation */
    seed: {
        value: number;
    };
    /** Inverse model matrix for ray marching */
    invModelMatrix: {
        value: Matrix4;
    };
    /** Scale of the fire object */
    scale: {
        value: Vector3;
    };
    /** Noise scaling parameters [x, y, z, time] */
    noiseScale: {
        value: Vector4;
    };
    /** Fire shape intensity */
    magnitude: {
        value: number;
    };
    /** Noise lacunarity (frequency multiplier) */
    lacunarity: {
        value: number;
    };
    /** Noise gain (amplitude multiplier) */
    gain: {
        value: number;
    };
}
/**
 * Volumetric fire shader using ray marching and simplex noise
 *
 * Based on "Real-Time procedural volumetric fire" by Alfred et al.
 * Uses simplex noise for turbulence and ray marching for volume rendering.
 *
 * @example
 * ```ts
 * const material = new ShaderMaterial({
 *   defines: FireShader.defines,
 *   uniforms: FireShader.uniforms,
 *   vertexShader: FireShader.vertexShader,
 *   fragmentShader: FireShader.fragmentShader,
 *   transparent: true
 * })
 * ```
 */
declare const FireShader: {
    readonly defines: {
        readonly ITERATIONS: "20";
        readonly OCTAVES: "3";
    };
    readonly uniforms: FireShaderUniforms;
    readonly vertexShader: "\n    varying vec3 vWorldPos;\n\n    void main() {\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n      vWorldPos = (modelMatrix * vec4(position, 1.0)).xyz;\n    }\n  ";
    readonly fragmentShader: "\n    uniform vec3 color;\n    uniform float time;\n    uniform float seed;\n    uniform mat4 invModelMatrix;\n    uniform vec3 scale;\n    uniform vec4 noiseScale;\n    uniform float magnitude;\n    uniform float lacunarity;\n    uniform float gain;\n    uniform sampler2D fireTex;\n\n    varying vec3 vWorldPos;\n\n    // GLSL simplex noise function by ashima\n    vec3 mod289(vec3 x) {\n      return x - floor(x * (1.0 / 289.0)) * 289.0;\n    }\n\n    vec4 mod289(vec4 x) {\n      return x - floor(x * (1.0 / 289.0)) * 289.0;\n    }\n\n    vec4 permute(vec4 x) {\n      return mod289(((x * 34.0) + 1.0) * x);\n    }\n\n    vec4 taylorInvSqrt(vec4 r) {\n      return 1.79284291400159 - 0.85373472095314 * r;\n    }\n\n    float snoise(vec3 v) {\n      const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);\n      const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n      vec3 i = floor(v + dot(v, C.yyy));\n      vec3 x0 = v - i + dot(i, C.xxx);\n\n      vec3 g = step(x0.yzx, x0.xyz);\n      vec3 l = 1.0 - g;\n      vec3 i1 = min(g.xyz, l.zxy);\n      vec3 i2 = max(g.xyz, l.zxy);\n\n      vec3 x1 = x0 - i1 + C.xxx;\n      vec3 x2 = x0 - i2 + C.yyy;\n      vec3 x3 = x0 - D.yyy;\n\n      i = mod289(i);\n      vec4 p = permute(permute(permute(\n        i.z + vec4(0.0, i1.z, i2.z, 1.0))\n        + i.y + vec4(0.0, i1.y, i2.y, 1.0))\n        + i.x + vec4(0.0, i1.x, i2.x, 1.0));\n\n      float n_ = 0.142857142857;\n      vec3 ns = n_ * D.wyz - D.xzx;\n\n      vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n\n      vec4 x_ = floor(j * ns.z);\n      vec4 y_ = floor(j - 7.0 * x_);\n\n      vec4 x = x_ * ns.x + ns.yyyy;\n      vec4 y = y_ * ns.x + ns.yyyy;\n      vec4 h = 1.0 - abs(x) - abs(y);\n\n      vec4 b0 = vec4(x.xy, y.xy);\n      vec4 b1 = vec4(x.zw, y.zw);\n\n      vec4 s0 = floor(b0) * 2.0 + 1.0;\n      vec4 s1 = floor(b1) * 2.0 + 1.0;\n      vec4 sh = -step(h, vec4(0.0));\n\n      vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n      vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n\n      vec3 p0 = vec3(a0.xy, h.x);\n      vec3 p1 = vec3(a0.zw, h.y);\n      vec3 p2 = vec3(a1.xy, h.z);\n      vec3 p3 = vec3(a1.zw, h.w);\n\n      vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));\n      p0 *= norm.x;\n      p1 *= norm.y;\n      p2 *= norm.z;\n      p3 *= norm.w;\n\n      vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);\n      m = m * m;\n      return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));\n    }\n\n    float turbulence(vec3 p) {\n      float sum = 0.0;\n      float freq = 1.0;\n      float amp = 1.0;\n\n      for(int i = 0; i < OCTAVES; i++) {\n        sum += abs(snoise(p * freq)) * amp;\n        freq *= lacunarity;\n        amp *= gain;\n      }\n\n      return sum;\n    }\n\n    vec4 samplerFire(vec3 p, vec4 scale) {\n      vec2 st = vec2(sqrt(dot(p.xz, p.xz)), p.y);\n\n      if(st.x <= 0.0 || st.x >= 1.0 || st.y <= 0.0 || st.y >= 1.0) {\n        return vec4(0.0);\n      }\n\n      p.y -= (seed + time) * scale.w;\n      p *= scale.xyz;\n\n      st.y += sqrt(st.y) * magnitude * turbulence(p);\n\n      if(st.y <= 0.0 || st.y >= 1.0) {\n        return vec4(0.0);\n      }\n\n      return texture2D(fireTex, st);\n    }\n\n    vec3 localize(vec3 p) {\n      return (invModelMatrix * vec4(p, 1.0)).xyz;\n    }\n\n    void main() {\n      vec3 rayPos = vWorldPos;\n      vec3 rayDir = normalize(rayPos - cameraPosition);\n      float rayLen = 0.0288 * length(scale.xyz);\n\n      vec4 col = vec4(0.0);\n\n      for(int i = 0; i < ITERATIONS; i++) {\n        rayPos += rayDir * rayLen;\n        vec3 lp = localize(rayPos);\n        lp.y += 0.5;\n        lp.xz *= 2.0;\n        col += samplerFire(lp, noiseScale);\n      }\n\n      // Apply color tint to the fire\n      col.rgb *= color;\n      col.a = col.r;\n      gl_FragColor = col;\n    }\n  ";
};

/**
 * Properties for creating a Fire instance
 */
interface FireProps {
    /** Fire texture (grayscale mask defining fire shape) */
    fireTex: Texture;
    /** Fire color tint (default: 0xeeeeee) */
    color?: Color | string | number;
    /** Ray marching iterations - higher = better quality, lower performance (default: 20) */
    iterations?: number;
    /** Noise octaves for turbulence (default: 3) */
    octaves?: number;
    /** Noise scaling parameters [x, y, z, time] (default: [1, 2, 1, 0.3]) */
    noiseScale?: [number, number, number, number];
    /** Fire shape intensity (default: 1.3) */
    magnitude?: number;
    /** Noise lacunarity - frequency multiplier (default: 2.0) */
    lacunarity?: number;
    /** Noise gain - amplitude multiplier (default: 0.5) */
    gain?: number;
}
/**
 * Volumetric fire effect using ray marching shaders
 *
 * Creates a procedural fire effect that renders as a translucent volume.
 * The fire shape is defined by a grayscale texture, with white areas being
 * the most dense part of the fire.
 *
 * @example
 * ```ts
 * const texture = textureLoader.load('fire.png')
 * const fire = new Fire({
 *   fireTex: texture,
 *   color: 0xff4400,
 *   magnitude: 1.5
 * })
 * scene.add(fire)
 *
 * // In animation loop
 * fire.update(time)
 * ```
 */
declare class Fire extends Mesh {
    material: ShaderMaterial & {
        uniforms: FireShaderUniforms;
    };
    private _time;
    /**
     * Creates a new Fire instance
     *
     * @param props - Configuration options for the fire effect
     */
    constructor({ fireTex, color, iterations, octaves, noiseScale, magnitude, lacunarity, gain, }: FireProps);
    /**
     * Updates the fire animation and matrix uniforms
     *
     * Call this method in your animation loop to animate the fire effect.
     *
     * @param time - Current time in seconds (optional)
     *
     * @example
     * ```ts
     * function animate() {
     *   fire.update(performance.now() / 1000)
     *   renderer.render(scene, camera)
     *   requestAnimationFrame(animate)
     * }
     * ```
     */
    update(time?: number): void;
    /**
     * Current animation time in seconds
     */
    get time(): number;
    set time(value: number);
    /**
     * Fire color tint
     *
     * @example
     * ```ts
     * fire.fireColor = 'orange'
     * fire.fireColor = 0xff4400
     * fire.fireColor = new Color(1, 0.5, 0)
     * ```
     */
    get fireColor(): Color;
    set fireColor(color: Color | string | number);
    /**
     * Fire shape intensity
     *
     * Higher values create more dramatic fire shapes.
     * Range: 0.5 - 3.0, Default: 1.3
     */
    get magnitude(): number;
    set magnitude(value: number);
    /**
     * Noise lacunarity (frequency multiplier)
     *
     * Controls how much the frequency increases for each noise octave.
     * Range: 1.0 - 4.0, Default: 2.0
     */
    get lacunarity(): number;
    set lacunarity(value: number);
    /**
     * Noise gain (amplitude multiplier)
     *
     * Controls how much the amplitude decreases for each noise octave.
     * Range: 0.1 - 1.0, Default: 0.5
     */
    get gain(): number;
    set gain(value: number);
}

export { Fire as FireMesh, FireShader };
export type { FireProps as FireMeshProps, FireShaderUniforms };
