Hi folks
The book Texturing and Modeling, A Procedural Approach contains code for a noise-based procedural flame shader. This code is written in the Stanford shading language (RTSL).
float abs(float x) {
return(select(x < 0, -x, x));
}
float fastspline(float x) {
float t0 = x*2;
float r0 = 0.8 + t0*(-0.45 + t0*(-0.8 + t0*(0.55)));
float t1 = (x-0.5)*2;
float r1 = 0.1 + t1*(-0.4 + t1*(0.55 + t1*(-0.25)));
float r = select(x < 0.5, r0, r1);
return r;
}
float3 rotate30scale2(float3 x) {
return {x[0]*2.0*0.866, x[1]*2.0*(-0.5), 0.0} + {x[0]*2.0*0.5, x[1]*2.0*(-0.866), 0.0};
}
float noise3D(float3 T, texref noisetex,
float3 L1offset, float L1weight,
float3 L2offset, float L2weight) {
float L1 = texture(noisetex, T+L1offset)[0];
float L2 = texture(noisetex, T+L2offset)[0];
float N = L2*L2weight + L1*L1weight; // Range of N is [0,1]
return abs(N-0.5);
}
float lookup_olddepth(texref depthtex) {
float4 dtex = texture(depthtex, rgb(xyz_xcreen())/1024);
return dtex[0] + dtex[1]/256 + dtex[2]/(256*256);
}
surface shader float4
flame (float4 uv, primitive group float time, texref permutetex, texref noisetex, texref depthtex) {
fragment float u = uv[0];
fragment float v = uv[1];
float framediff = time*0.2;
float3 T = {u, v+framediff, 0}
constant float freqscale = 16;
T = T * ({freqscale, freqscale/2, 0} * {1/64.0, 1/64.0, 0});
constant float changerate = 6.0;
float timeval = time*changerate;
float timerem = timeval - floor(timeval);
float timebase = floor(timeval);
float L1weight = 1.0 - timerem;
float L2weight = timerem;
float ocoord1 = timebase/64.0 + 1.0/128.0;
float ocoord2 = ocoord1 + 1.0/64.0;
float3 L1offset = rgb(texture(permutetex, {ocoord1, 1.0/128.0, 0.0}));
float3 L2offset = rgb(texture(permutetex, {ocoord2, 1.0/128.0, 0.0}));
float turb;
turb = noise3D(T, noisetex, L1offset, L1weight, L2offset, L2weight);
T = rotate30scale2(T);
turb = turb + 0.5 * noise3D(T, noisetex, L1offset, L1weight, L2offset, L2weight);
T = rotate30scale2(T);
turb = turb + 0.25 * noise3D(T, noisetex, L1offset, L1weight, L2offset, L2weight);
T = rotate30scale2(T);
turb = turb + 0.125 * noise3D(T, noisetex, L1offset, L1weight, L2offset, L2weight);
float turbscale = 0.5 + 0.7*(1-v);
float x = (1.0/sqrt(v)) * (abs(2.0*u-1.0) + turbscale*turb);
float edgedensity = 12.5 * fastspline(clamp(x, 0, 1));
float FlameTemperature = 0.6;
float3 FlameColor = {1.0, FlameTemperature, FlameTemperature-0.2};
float3 edgecolor = FlameColor * edgedensity;
float indensity = (2.85*turb+0.55) + v*0.35;
float incolor = FlameColor * indensity;
float3 flamecolor = select(edgedensity > indensity, incolor, edgecolor);
float density = select(edgedensity > indensity, indensity, edgedensity);
flamecolor = clamp(flamecolor, 0, 1);
density = clamp(density, 0, 1);
constant float depthscale = 0.002;
constant float flamethickness = depthscale;
constant float depthperturb = 1.75 * depthscale;
constant float edgeperturb = 3.5 * depthscale;
float olddepth = lookup_olddepth(depthtex);
float depth = xyz_screen()[2];
depth = depth + depthperturb*turb + edgeperturb*abs(u-0.5);
float atten = (olddepth - depth) / flamethickness;
return {flamecolor, density*min(atten, 1.0)};
} // flame
Code ©2001 NVIDIA
How can I use this shader. There are some commands like “select”, which is not defined in e.g. FXComposer. I’m a rookie in such things, but probably it’s possible to re-write this code to another language?
Thanks for helping me.