View Full Version : How to use Stanford RTSL shader?!

 m@Xist10 October 2006, 12:06 AMHi 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 (c)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.
dlanier
10 October 2006, 06:14 AM
Hi,

The select command seems to me like the C macro :

//select(x < 0.5, r0, r1);
float var = (x< 0.5)?r0:r1;
So it's equivalent but faster tp
if (x < 0.5)
var = r0;
else
var = r1;

This is faster on 3D chips than a real "if" instruction.

And yes it can be translated into Cg, HLSL, GLSL, but you 'll probably need to have a noise function, as far as I remember the noise function is part of shaders 3.0...
See for example in GLSL this web site for oise function : http://www.davidcornette.com/glsl/download.html
Or there must have some in the source code of your book.

Regards,

m@Xist
10 October 2006, 08:23 PM
Thanks dlanier

this section helps, but then theres coming up another problem:

FXComposer doesn't understand
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};

Actually, it's just returning a vector, but it seems to have problems with the join operator "{}", which assembles scalars into vectors. In this case makes a 3-vector from scalars x, y, and z.

HalfVector
10 October 2006, 02:30 AM
Try this:

return float3(x[0]*2.0*0.866, x[1]*2.0*(-0.5), 0.0) + float3(x[0]*2.0*0.5, x[1]*2.0*(-0.866), 0.0);

m@Xist
10 October 2006, 12:50 PM
Thanks, but errors keep going on with "texref", which is specified in RTSL. In other shading languages it's equivalent to "string" I guess.

Well, the thing is, I have to understand what the code does in order to use it in other shading languages.

I'm not quite sure, what it does in detail, but first of all I guess it builds the shape of the fire via the spline function. Next there are overlayed different noise maps, and finally colors are added.

Can anyone tell my what's happenin in detail? Thanks!

darktding
10 October 2006, 02:27 PM
isnt ther standford shading code you are showing here similiar to the nvidia's CG code?
http://developer.nvidia.com/object/gpu_programming_guide.html
I think tex must be tex3f or something alternate and must be all specified in that manual, it depends if you are writing shaders for CG and not something else...

CGTalk Moderation
10 October 2006, 02:27 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.

1