Random stuff I'm working on, in chronological order.

Based on code by Paulo Falcao which is available on ShaderToy. It's licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

1280x720 resolution. The original code gives 35 fps. Replacing the atan() calls increases this to 47 fps. Then it's the usual steps of quality reductions and some unrolling to edge it above 60 fps. Gonna do a writeup about atan() one of these days. The NVidia implementation is ok, but the code is just inlined, not reordered.

Some changes to make all the Xmas demo effects run in 60 fps:

Shader files, the ones changed since the video was released in bold:

- galdance.glsl - based on code by Sinuousity
- glowcity.glsl - based on code by mhnewman
- noise3d.glsl - based on code by revers
- colorful.glsl - based on code by ollj
**seascape.glsl**- based on code by TDM- trans.glsl - based on code by Shane
**twofield.glsl**- based on code by w23**torus.glsl**- based on code by bal-khan- tracer.glsl - based on code by Nils L. Corneliusen
- quat.glsl - based on code by Keenan Crane

It's running in 60 fps except during the transition, so let's save a bit more. The routine is already chopping off the left and right sides of the screen. But more can be removed, just not all the way down. Either mask out the areas using high-level GL or just quickly hack it into the shader:

void main( void ) { float xedge = 256.0f/1920.0f; float yedge2 = 208.0f/1080.0f; float xedge2 = 416.0f/1920.0f; if( (vt.x < xedge || vt.x > 1.0f - xedge) || ((vt.x < xedge2 || vt.x > 1.0f - xedge2) && vt.y > yedge2 && vt.y < 1.0f - yedge2 ) ) { outColor = vec4( 0.0f, 0.0f, 0.0f, colscale ); return; } (...)

Also a trivial reduction in lightball() that the compiler doesn't do:

vec3 lightball( vec3 lpos, vec3 lcolor, vec3 O, vec3 D, float L ) { vec3 ldir = lpos - O; if( dot( ldir, ldir ) > L*L ) return vec3( 0.0f ); float lv = 2.07f - ( ( ( lpos.z / 10.0f + 1.0f ) / 2.0f ) + 1.0f ); float pw = pow( max( 0.0f, dot( normalize( ldir ), D ) ), 20000.0f * lv ); return ( normalize( lcolor ) + 1.0f ) * pw; }

Move ang, orig, m calculation to the CPU. Untangle heightMapTracing(). Discover that one of the two initial map() calls resolves to static value for all iterations: map( ori ). But just using a base value of 1.0f is more than precise enough. So main() becomes simpler:

(...) float hx = map( ori.xyz + dir * 1000.0f ); if( hx > 0.0f ) { outColor = vec4( getSkyColor(dir), colscale ); return; } vec3 p = heightMapTracing(ori.xyz,dir, hx ); (...)

And heightMapTracing() is changed to:

vec3 heightMapTracing( vec3 ori, vec3 dir, out float hx ) { vec3 p; float tm = 0.0; float tx = 1000.0; // float hm = map(ori); float hm = 1.0f; // ori fixed per frame, so close enough float tmid = 0.0; for( int i = 0; i < NUM_STEPS; i++ ) { tmid = mix( tm, tx, hm / (hm-hx) ); p = ori + dir * tmid; float hmid = map( p ); if( hmid < 0.0 ) { tx = tmid; hx = hmid; } else { tm = tmid; hm = hmid; } } return p; }

D'oh of the week: I_MAX is 100. Sounds rather arbitrary, it never gets to 100 iterations anyway. Reduce until framerate is above 60 all the way. A good value of I_MAX seems to be 52. Visual artifacts minimal.