Home / 2012 / December

Flaming Flowers Preview with Javascript / WebGL

UPDATE 01/07 :

I finally find out the problem with the problem of same shader but different result in processing and webgl, it’s because i didn’t set the blend function right, once i got it right the result is identical, you can check the link above. Besides, i use video as a texture instead of image of sequence, the mask which was done with global composite operation is now replace by another fragment shader, therefore reduce a lot of loadings.

Screen-Shot-2013-01-07-at-13.01.48

Just playing with mask on top of a video, surprisingly the effect is really beautiful, so I went back on to add more details to it. I started with javascript with simple mask using the “globalCompositeOperation” skill, then i switched to Processing to add more effects using GLSL Shaders, and then i went back to javascript trying to add the same effects in WebGL. It’s an interesting experiment and i learn a lot from it. I’m still working on the processing version to make it more complete, will have another post coming soon once i finished it. However i want to blog about the javascript version first and give a little preview 😛

 

Global Composite Operation

the first problem I have is how to mask a video, I find some articles but they are not working for me, the main reason is the graphics of the flower are from images, and they have alpha gradient inside. It is very important for me to keep these alpha gradients, it looks much better on the visual side. So at the end i use image sequence instead of video, and using context2d.globalCompositeOperation to mask it.

this.ctx.clearRect(0, 0, W, H);
this.ctx.globalCompositeOperation = "source-over";

//  Draw Flowers and Particles
this.ctx.globalCompositeOperation = "source-in";
this.ctx.drawImage(this.bgs[this.currentFrame], 0, 0, W, H);  // Draw the image sequence of the background video

In fact it’s very easy to create this effect, the only thing to be careful is don’t forget to reset the globalCompositeOperation every time you render :

this.ctx.globalCompositeOperation = "source-over";

or it will keep rendering in “source-in” then you won’t be able to see anything.

 

Drawing Images with different transparency on the same canvas

When trying to create the particles effect i encounter this problem : each of my particles have its own transparency, and I’m using image for my particles. The way to draw image with transparency on a canvas is using globalAlpha, but this will change the alpha of the canvas, not just one single particle. Luckily i found the solution : context2d.save() / context2s.restore(); I am very surprised when i realise this, i thought these 2 methods are for transformations, but apparently they are doing more then that :

var pp = this.particles[i];
this.ctx.save();
this.ctx.globalAlpha = pp.alpha;
this.ctx.drawImage(flamming.imgParticle, pp.position.x, pp.position.y, pp.scale, pp.scale);
this.ctx.restore();

so before you setting the globalAlpha, call the context.save(), and call context.restore() after you done drawing, simple as that !

 

GLTexture / GLTextureFilter

When i was building this in Processing, i am using the GLGraphic library, it’s very easy to use. These are the 2 classes inside, the GLTextureFilter take a source from a GLSL fragment shader, all you need to do is write your fragment shader , then call :

filter.apply(inputTextures, outputTexture);

and you have the result in the outputTexture, very easy to use, especially for compositing, you won’t lost track in swapping the textures and shader programs, and also both the texture and programs are reusable. So when i went back to javascript, the first thing i did is try to build something similar to this, which will save me a lot of time on trying fragment shaders and different compositing. I want to create an effect that it’s only clear in the center, and it gets blurry when moving away the center, here is the workflow :

1. render the flowers ( the original render)

2. using the original render and apply a vertical blur to get the first blur version

3. using this first blur version and apply a horizontal blur to get the full blur version

4. combine the original render and this full blur version, mix it with each pixel’s distance to the center.

So i need to create 3 different Filter : Vertical Blur Filter, Horizontal Blur Filter and the last one Mix Filter, in the code it’s like this :

//	Init
this.glTexture = new GLTexture(this.gl, this.canvas);
this.outputHBlur = new GLTexture(this.gl, null, 1024, 1024);
this.outputBlur = new GLTexture(this.gl, null, 1024, 1024);
this.outputEdgeBlur = new GLTexture(this.gl, null, 1024, 1024);

this.glFilterHBlur = new GLTextureFilter(this.gl, "shader-vs", "shader-fs-hblur");
this.glFilterHBlur.setParameter("h", "float", 1/1024);
this.glFilterVBlur = new GLTextureFilter(this.gl, "shader-vs", "shader-fs-vblur");
this.glFilterVBlur.setParameter("v", "float", 1/1024);
this.glFilterEdgeBlur = new GLTextureFilter(this.gl, "shader-vs", "shader-fs-edgeblur");

//	Render
this.glTexture.updateTexture(this.canvas);
this.glFilterHBlur.apply([this.glTexture], this.outputHBlur);
this.glFilterVBlur.apply([this.outputHBlur], this.outputBlur);
this.glFilterEdgeBlur.apply([this.outputBlur, this.glTexture], this.outputEdgeBlur);
renderImage(this.gl, this.outputEdgeBlur);

It’s really simple and easy, however these 2 classes are not done yet, still some work to do, i’ll put them on my github when i finish these tasks, and will keep on working for more features.

Another thing I love with WebGL is that it’s using the GLSL for shaders, and it’s the same with GLGraphics, this means i can basically use the same shader program for both, it’s amazing! Compare to AGAL of flash, AGAL more difficult to program and can be only used in flash, that’s pity.

 

Same Shader, Different result

Although i am using the same fragment shader for both processing and javascript version, the result is so different :blurCompare

as you can see on the left is the result in Processing/GLGraphics, which is much like the idea of blur, on the left is the result in javascript, it’s blurred yes, but i lose a lot on the alpha as well, still wondering why and try to find the answer.

 

Anyway that’s about it for right now, hope you enjoy it and stay tuned for the bigger version on Processing !