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:
- google for something cool
- copy it into Codea
- poke it randomly till it works