{
    "name": "Fire Shader",
    "description": "Prozedurales Feuer mit Rauch",
    "vertex_shader": "attribute vec2 a_position;\nvoid main() {\n    gl_Position = vec4(a_position, 0.0, 1.0);\n}",
    "fragment_shader": "precision mediump float;\nuniform float u_time;\nuniform vec2 u_resolution;\nuniform vec2 u_mouseNorm;\nuniform float u_audioVolume;\n\nfloat hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }\nfloat noise(vec2 p) {\n    vec2 i = floor(p), f = fract(p);\n    f = f*f*(3.0-2.0*f);\n    return mix(mix(hash(i), hash(i+vec2(1.0,0.0)), f.x),\n               mix(hash(i+vec2(0.0,1.0)), hash(i+vec2(1.0,1.0)), f.x), f.y);\n}\n\nvoid main() {\n    vec2 uv = gl_FragCoord.xy \/ u_resolution.xy;\n    float t = u_time;\n    vec2 p = uv * vec2(3.0, 4.0);\n    p.y += t * 0.8;\n    float n = noise(p) + noise(p * 2.0) * 0.5 + noise(p * 4.0) * 0.25;\n    float fire = smoothstep(0.4, 0.8, n) * (1.0 - uv.y);\n    fire += u_audioVolume * 0.2 * (1.0 - uv.y);\n    vec3 col = vec3(0.0);\n    col = mix(col, vec3(0.8, 0.1, 0.0), smoothstep(0.0, 0.3, fire));\n    col = mix(col, vec3(1.0, 0.5, 0.0), smoothstep(0.3, 0.6, fire));\n    col = mix(col, vec3(1.0, 0.9, 0.3), smoothstep(0.6, 1.0, fire));\n    float smoke = smoothstep(0.3, 0.7, n) * uv.y * 0.3;\n    col += vec3(0.1, 0.1, 0.15) * smoke;\n    float mouseDist = length(uv - u_mouseNorm);\n    col += vec3(1.0, 0.5, 0.0) * smoothstep(0.2, 0.0, mouseDist) * 0.5;\n    gl_FragColor = vec4(col, 1.0);\n}"
}