We are about to switch to a new forum software. Until then we have removed the registration on this forum.
TheCodingTrain channel did two videos recently on water and fire effects. He did them in just processing, I'm doing it in processing with shaders.
For the water, I didn't have any issues converting it (posted in comment below).
For the fire, I'm having issues getting it to perform like expected. It's almost working but not quite.
Edit: I fixed it, here is the working code. The original code from the video ran at 25 fps on my machine, and this shader version does 1000fps easy.
fireShader.pde
PShader fire;
PGraphics buffer1,buffer2, cooling;
int w = 400, h = 400;
float ystart = 0.0;
int speed = 1000;
void setup() {
size(800, 400, P2D);
buffer1 = createGraphics(w, h, P2D);
buffer2 = createGraphics(w, h, P2D);
cooling = createGraphics(w, h, P2D);
cool();
fire = loadShader("fire.glsl");
fire.set("resolution", w*2, h);
fire.set("buffer1", buffer1);
fire.set("buffer2", buffer2);
fire.set("cooling", cooling);
frameRate(100);
}
void cool() {
cooling.loadPixels();
float xoff = 31.1;
float increment = 0.12;
noiseDetail(3, 1.06);
for (int x = 0; x < w; x++) {
xoff += increment;
float yoff = ystart;
for (int y = 0; y < h; y++) {
yoff += increment;
float n = noise(xoff, yoff);
float bright = pow(n, 2) * 22;
cooling.pixels[x+y*w] = color(bright);
}
}
cooling.updatePixels();
ystart += increment;
}
void startFire() {
buffer1.beginDraw();
buffer1.resetShader();
buffer1.noStroke();
buffer1.fill(255);
buffer1.rect(mouseX,mouseY,100,5);
buffer1.rect(0,h-4,w,4);
buffer1.endDraw();
}
void swapBuffers(){
PGraphics temp = buffer1;
buffer1 = buffer2;
buffer2 = temp;
}
void draw() {
fire.set("time", (frameCount % speed)/(float)speed);
startFire();
background(0);
buffer2.beginDraw();
buffer2.shader(fire);
buffer2.rect(0, 0, w, h);
buffer2.stroke(0);
buffer2.endDraw();
swapBuffers();
image(buffer2, 0, 0);
image(cooling, w, 0);
text((int)frameRate,2,10);
}
fire.glsl
#ifdef GL_ES
precision highp float;
#endif
#define PROCESSING_COLOR_SHADER
uniform float time;
uniform vec2 mouse;
uniform float dissipation;
uniform vec2 resolution;
uniform sampler2D buffer1;
uniform sampler2D buffer2;
uniform sampler2D cooling;
float decode(vec4 color) {
return (color.r + color.g + color.b)/3.0;
}
vec4 encode(float r){
int k = int(floor(r*255));
int d = int(round(k % 3));
float up = 1.0/255.0;
if (d==0) return vec4(r,r,r,1.0);
if (d==1) return vec4(r,r,r+up,1.0);
if (d==2) return vec4(r,r+up,r+up,1.0);
}
void main( void ) {
vec2 position = ( gl_FragCoord.xy / resolution.xy );
vec2 pixel = 1./resolution;
float k = -1.;
float sum = 0;
sum += decode(texture2D(buffer1, position + pixel * vec2(1., k)));
sum += decode(texture2D(buffer1, position + pixel * vec2(-1, k)));
sum += decode(texture2D(buffer1, position + pixel * vec2(0., 1+k)));
sum += decode(texture2D(buffer1, position + pixel * vec2(0., -1+k)));
sum *= 0.25;
position.y = 1-position.y;
position.y += time;
if (position.y > 1.0) position.y = (position.y - 1.0);
sum -= decode(texture2D(cooling, position + pixel * vec2(0., k)))/2.0;
gl_FragColor = encode(sum);
}
Answers
Here is my working conversion of the water effect. I expanded it from 255 levels of brightness to 765 by utilizing all 3 rgb channels.
waterShader.pde
water.glsl
Nice! =D> I used a variation of the CPU water a long time ago to make this You've inspired me to have a look at making a GLSL version - it's basically using the ripple map to read from a texture.
Using the ripple map to read from a texture is an interesting idea
Added color, some waviness , some code I thought would help it behave more like fire where it expands more where the fire is high intensity. https://github.com/lmccandless/fireShader