Making fire

Does anyone have anything (shader or code) to make fire? I mean with animation. I’m also talking about very simple fire, like the one on this rocket right here. Thanks in advance.
https://goo.gl/images/n9Bzfa

The most simple solution would be to draw the flames 2x (1x yellow, 1x red) both with an offset from the rocket, just like in the picture. Then at random time blend out both or just the furthest one. This will create a blinking burn effect. Combined wirh some sound that makes for a beleaveable illusion.

Another solution would be to animate the flame in asesprite or photoshop and use the resulting spritesheet to play the whole animation in a loop. To make an animation from a spritesheet you can use one of the scripts from this discussion: https://codea.io/talk/discussion/5673/confused-about-sprite-animation-in-codea

The third solution involves making your own particle engine. John did a generic one here: https://codea.io/talk/discussion/634/particle-system-example

Here’s one I made that offloads all the heavy lifting into a shader:

https://codea.io/talk/discussion/2516/particle-effect-in-a-shader

@spacemonkey I have a lot of different particle engines, I don’t know how to make them look good for what I am aiming for

@se24vad I was gonna approach it the same way you did, except I can’t find any good images and I can get vertices to work on my mesh, can anybody share som code, it would really be appreciated. Thanks!

I found this, i cannot remember who wrote it…

--# Main
function setup()
    --screen = image(WIDTH,HEIGHT)
    parameter.integer("size",5,100)

    cap = image(100,100)
    setContext(cap)
        pushStyle()
            local mp = 255/100
            for i=1,400 do
            fill(255,31,0,80)
            ellipse(50,50,i/4)
            end
        popStyle()
    setContext()

    m = mesh()
    m.texture = cap
    part = {}
    i=0
    parameter.color("colour",color(255,60,0,80),function() m:setColors(colour) end)
    m:setColors(colour)
    emitpos = vec2(WIDTH/2,HEIGHT/2-200)
end


function draw()
    if i <= 400 then 
        i = i + 1
        part[i] = {}
        part[i].pos = vec2(WIDTH/2,HEIGHT/2)
        part[i].vel = vec2(math.random(-2,2)*2,math.random(-2,2))
        part[i].time = 0.5
        part[i].size = math.random(20,40)+size
        part[i].r = m:addRect(WIDTH/2,HEIGHT/2,1,1)
        m:setColors(colour)
    end
    background(77, 70, 70, 255)
    for i=1,#part do
        local p = part[i].pos
        part[i].pos = p+part[i].vel
        p = part[i].pos
        part[i].vel = part[i].vel+vec2((emitpos.x-p.x)/300-part[i].vel.x/15,0.005*part[i].size)
        part[i].time = part[i].time-0.01
        local t = part[i].time
        m:setRect(part[i].r,p.x,p.y,part[i].size*t*2,part[i].size*t*2)
        if t<=0 then
            part[i].pos = vec2(WIDTH/2,HEIGHT/2)
            part[i].vel = vec2(math.random(-2,2),math.random(-2,2))
            part[i].time = 0.5
            part[i].size = math.random(20,40)+size
        end
    end
    blendMode(ADDITIVE)
    m:draw()
end

function touched(t)
    emitpos = emitpos + vec2(t.deltaX,t.deltaY)
end -- cartoon fire

If you try to go route (2) I described, you can use my Procreate-To-Codea-Animation-Tool mentioned here: https://codea.io/talk/discussion/7267/procreate-animation-player

And here are two tweets showing the process…
As you can tell, it doesn’t matter if you can draw or not, you just need at least two frames of animation for it to work. (I did three)
https://twitter.com/supacowa/status/842070073162510336
https://twitter.com/supacowa/status/842070701397946375

@se24vad that looks really good, but also really difficult.

@piinthesky i think I might use that one, I have made one of my own, now I have to decide which one is better.

Thank you both!

Here is some fire I found on the internet and ported in. Alpha blending doesn’t seem to work so I hard push it down to black, probably just something I’m rusty on.

From here: http://clockworkchilli.com/blog/8_a_fire_shader_in_glsl_for_your_webgl_games

You’ll need this image to load in the setup:
https://s3-us-west-2.amazonaws.com/ccblogdemos/fire/flame.png

-- Fire

-- Use this function to perform your initial setup
function setup()
    flameTexture = readImage("Dropbox:flame")
    fireMesh = mesh()
    fireMesh:addRect(WIDTH/2, HEIGHT/2, 100, 200)
    fireMesh:setRectTex(1 , 0,1,1,-1.0)
    fireMesh.texture = flameTexture
    fireMesh.shader = shader(fireShader.vertexShader, fireShader.fragmentShader)
end

-- This function gets called once every frame
function draw()
    background(0,0,0,255)
    
    fireMesh.shader.time = ElapsedTime
    fireMesh:draw()
    
end

fireShader = {
vertexShader = [[
//
// A basic vertex shader
//

//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;

//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec2 texCoord;

//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    vTexCoord = texCoord;
    
    //Multiply the vertex position by our combined transform
    gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
//
// A basic fragment shader
//

//Default precision qualifier
precision highp float;

//This represents the current texture on the mesh
uniform highp sampler2D texture;
uniform highp float time;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
    //Generate noisy x value
    vec2 n0uv = vec2(vTexCoord.x*1.4 + 0.01, vTexCoord.y + time*0.69);
    vec2 n1uv = vec2(vTexCoord.x*0.5 - 0.033, vTexCoord.y * 2.0 + time*0.12);
    vec2 n2uv = vec2(vTexCoord.x*0.94 + 0.02, vTexCoord.y * 3.0 + time*0.61);
    
    float n0 = (texture2D( texture, n0uv).w-0.5)*2.0;
    float n1 = (texture2D( texture, n1uv).w-0.5)*2.0;
    float n2 = (texture2D( texture, n2uv).w-0.5)*2.0;
    float noiseA = clamp(n0 + n1 + n2, -1.0, 1.0);

    //Generate noisy y value
    vec2 n0uvB = vec2(vTexCoord.x*0.7 - 0.01, vTexCoord.y + time*0.27);
    vec2 n1uvB = vec2(vTexCoord.x*0.45 + 0.033, vTexCoord.y * 1.9 + time*0.61);
    vec2 n2uvB = vec2(vTexCoord.x*0.8 - 0.02, vTexCoord.y * 2.5 + time*0.51);
    float n0B = (texture2D( texture, n0uvB).w-0.5)*2.0;
    float n1B = (texture2D( texture, n1uvB).w-0.5)*2.0;
    float n2B = (texture2D( texture, n2uvB).w-0.5)*2.0;
    float noiseB = clamp(n0B + n1B + n2B, -1.0, 1.0);

    vec2 finalNoise = vec2(noiseA, noiseB);
    float perturb = (1.0 - vTexCoord.y)*0.35 + 0.02;
    finalNoise = (finalNoise * perturb) + vTexCoord - 0.02;
    vec4 color = texture2D(texture, finalNoise);
    color = vec4(color.x*2.0, color.y*0.9, (color.y/color.x)*0.2, 1.0);
    finalNoise = clamp(finalNoise, 0.0, 1.0);
    color.a = texture2D(texture, finalNoise).a * 4.0;
    color.a = color.a*texture2D(texture, vec2(vTexCoord.x, 0.95 - vTexCoord.y)).z * 4.0;

    //for some reason alpha isn't merging so just drop the overall color
    color = color * color.a;

    gl_FragColor = color;
}
]]}

@spacemonkey Wow! This is amazing! You gotta teach me how you make your shaders, they are really great! Thank you so much!

I can’t take credit, my process is:

  1. google for something cool
  2. copy it into Codea
  3. poke it randomly till it works

:wink: