Hey all,

What kind of animation in flash 3d world do you know? You can use such thing as MovieClipTexture3D or VideoTexture3D, but what do you say if I show you example of animation given by texture and vertex color? With one texture and one simple plane.

David Blaine

Yeap. We can do it and our result will be like burning paper in my video.

As you can see, there are four different animations, in various direction of burning.

So, we need to make two things:

1) Create burning effect
2) And make it “directional”

Let’s go create the effect.

To reach it, we need something, that will look like big noise. It can be computed at runtime and in this case we will not need any texture at all, but precomputed effect will be much faster and more controllable.

So, at now it is just Photoshop’s Filter->Render->Clouds.

butningtexture

Look at this texture. The idea is that the burned area is where color is totally black. And if we add black color to the entire texture, the burned area will be increased too:

Burning progress

So this texture is already kind of “animation config”.

Now we are ready to write the code.

use namespace flare;
use namespace flare.transforms;
use namespace flare.filters;
use namespace flare.blendMode;

param float4 mainColor <ui = "color"> = float4( 1, 0, 0, 1 );

sampler2D fractalTexture;
param float burnLevel = 0;
param float burnK = 10;

technique main
{
    output vertex = transform();
    
    float4 texMain = mainColor;
    float4 texFractal = sampler2D( fractalTexture, iUV0 );
    
    float4 texBurned = texFractal;
    
    float current = texBurned.r - burnLevel/burnK;
    kill(-current<0);
    
    float4 tex = texMain;
    
    output fragment = tex;
}

Pretty simple code, the most important thing going on is here:

    float current = texBurned.r - burnLevel/burnK;
    kill(-current<0);

According to main control value (burnLevel) all texels lower than this value will be killed. That’s it.

burning paper 01

Now we need to make paper burnt where our imaginary flame has done with paper. To make this simply multiply our precomputed “noise” to main color.

    float4 tex = multiply(texMain,float4(current));

burning paper 02

Good, but paper shouldn’t be already burnt at the start.

    float4 tex = multiply(texMain,float4(min(current,1)));

burning paper 03

Effect is just around to be done, we are missing glow borders. It is kind of tricky a little. Let’s return to code that determines where paper is already burned and where it is not:

    float current = texBurned.r - burnLevel/burnK;

According to this expression, negative “current” is where paper is totally burned, positive – where paper is still intact, and zero is on the border of these conditions. Right where we need to show flame glowing.

    float4 texGlow = sampler2D( fractalTexture, iUV0*10 );
    texGlow = pow(texGlow,3)*glowColor;
    
    float4 glow = (1-clamp(current,0,0.03)/0.03)*texGlow;
    tex += glow*2;

We are taking the same “noise”, sample it with big tiling and apply it where our positive value is less than 0.03.

burning paper 04

Looks nice.

The only thing left is to make effect “directional” as promised.

The problem is that we need to use the same program for different surfaces. So we need to store some data at the vertexes. The data can be Vertex Color, for example.

In 3ds Max you can set these values via VertexPaint modifier. And trick is that you can draw ANYTHING you want with that. Where color is darker – this will be our start of burning.

3dsmax vertex color

Ask me if you need to pay more attention to additional vertex data and its usage, I’ll make a separate post about it

    input COLOR0 color0;
    interpolated float3 iColor0 = color0;

    float current = texBurned.r + color0.r - burnLevel/burnK;

burning paper 05

Yes! It’s working! Try to draw something by yourself, you can also use any texture, as I showed it in demo video.

The final shader:

use namespace flare;
use namespace flare.transforms;
use namespace flare.filters;
use namespace flare.blendMode;

param float4 mainColor <ui = "color"> = float4( 1, 0, 0, 1 );
param float4 glowColor <ui = "color"> = float4( 1, 0, 0, 1 );

sampler2D fractalTexture;

param float burnLevel = 0;
param float burnK = 10;

input COLOR0 color0;
interpolated float3 iColor0 = color0;

technique main
{
    output vertex = transform();
    
    float4 texMain = mainColor;
    float4 texFractal = sampler2D( fractalTexture, iUV0 );
    
    float4 texBurned = texFractal;
    
    // <0 is gone, >0 still alive, 0
    float current = texBurned.r + color0.r - burnLevel/burnK;
    kill(-current<0);
    
    float4 tex = multiply(texMain,float4(min(current,1)));
    
    float4 texGlow = sampler2D( fractalTexture, iUV0*10 );
    texGlow = pow(texGlow,3)*glowColor;
    
    float4 glow = (1-clamp(current,0,0.03)/0.03)*texGlow;
    tex += glow*2;
    
    output fragment = tex;
}

Join the conversation! 2 Comments

  1. Wow! This is great! Can it be reproduced in AS3 / Starling?

    Reply

Leave a Reply

Category

3D FX

Tags

, ,