Shadertoy porting: how to improve frame rate

spin lud's icon

Hi, I have ported this shader from Shadertoy.

It works but with a fullhd resolution 1920x1080 I have a bad fps and a choppy output, while on the Shadertoy website I get smooth output even at full screen (I am using a macbook pro M1 max).

I am looking for ideas to improve the frame rate.

One thing that I have tried is to lower the number of iterations of the marching rays and increase the threshold for hit testing (rows 527-552):

const float smallVal = 0.000625;
// const float smallVal = 0.001; // <-- I TRIED TO INCREASE THIS

const int numIterations = 200;
// const int numIterations = 70; // <-- I TRIED TO DECREASE THIS

// ray marching time
for (int i = ZERO_TRICK; i < numIterations; i++)  // This is the count of the max times the ray actually marches.
{
    // Step along the ray. Switch x, y, and z because I messed up the orientation.
    pos = (camPos + rayVec * t).yzx;
    // This is _the_ function that defines the "distance field".
    // It's really what makes the scene geometry. The idea is that the
    // distance field returns the distance to the closest object, and then
    // we know we are safe to "march" along the ray by that much distance
    // without hitting anything. We repeat this until we get really close
    // and then break because we have effectively hit the object.
    dist = DistanceToObject(pos);
    // This makes the ray trace more precisely in the center so it will not miss the
    // vertical glowy beam.
    dist = min(dist, length(pos.yz));

    t += dist;
    // If we are very close to the object, let's call it a hit and exit this loop.
    if ((t > maxDepth) || (abs(dist) < smallVal)) break;
}
Flux Core 2.zip
zip

This helps but the image quality is worse and still I can't get smooth output at full hd resolution.

Anything else that I can try to improve the frame rate?

Rob Ramirez's icon

is the performance compared to the site closer if you disable fsaa? that basically doubles the number of processing pixels

spin lud's icon

Hi! Disabling fsaa definitely helps to smooth the output. I have added a bit of glsl code to display the fps directly on the final image, the interesting thing is that there isn't much difference between fps reported with fsaa enabled or disabled, but with fsaa enabled the output is definitely much more choppy. Why is that?

// DISPLAY DIGITS FUNCTIONS -----------------
// from: https://www.shadertoy.com/view/lt3GRj

float DigitBin(const in int x)
{
    return x==0?480599.0:x==1?139810.0:x==2?476951.0:x==3?476999.0:x==4?350020.0:x==5?464711.0:x==6?464727.0:x==7?476228.0:x==8?481111.0:x==9?481095.0:0.0;
}

// Multiples of 4x5 work best
vec2 fontSize = vec2(4,5) * vec2(15,9);

vec2 grid(int x, int y) { return fontSize.xx * vec2(1,ceil(fontSize.y/fontSize.x)) * vec2(x,y) + vec2(2); }

// Improved version
//
// Most important change is dropping everything left of the decimal point ASAP 
// when printing the fractional digits. This is done to bring the magnitule down
// for the following division and modulo.
//
// Another change is to replace the logarithm with a power-of-ten value 
// calculation that is needed later anyway.
// This change is optional, either one works.
float PrintValue(vec2 fragCoord, vec2 pixelCoord, vec2 fontSize, float value, float digits, float decimals) {
    vec2 charCoord = (fragCoord - pixelCoord) / fontSize;
    if(charCoord.y < 0.0 || charCoord.y >= 1.0) return 0.0;
    float bits = 0.0;
    float digitIndex1 = digits - floor(charCoord.x)+ 1.0;
    if(- digitIndex1 <= decimals) {
        float pow1 = pow(10.0, digitIndex1);
        float absValue = abs(value);
        float pivot = max(absValue, 1.5) * 10.0;
        if(pivot < pow1) {
            if(value < 0.0 && pivot >= pow1 * 0.1) bits = 1792.0;
        } else if(digitIndex1 == 0.0) {
            if(decimals > 0.0) bits = 2.0;
        } else {
            value = digitIndex1 < 0.0 ? fract(absValue) : absValue * 10.0;
            bits = DigitBin(int (mod(value / pow1, 10.0)));
        }
    }
    return floor(mod(bits / pow(2.0, floor(fract(charCoord.x) * 4.0) + floor(charCoord.y * 5.0) * 4.0), 2.0));
}

// END DISPLAY DIGITS FUNCTIONS ------------------
void main()
{
	vec2 fragCoord = jit_in.texCoord * iResolution.xy;
    // vec2 uv = fragCoord.xy / iResolution.xy;

	#ifdef NON_REALTIME_HQ_RENDER
	    // Optionally render a non-realtime scene with high quality
	    BlockRender(fragCoord);
	#endif	

    // Do a multi-pass render
    vec3 finalColor = vec3(0.0);

	#ifdef NON_REALTIME_HQ_RENDER
	    for (float i = 0.0; i < antialiasingSamples; i++)
	    {
	        const float motionBlurLengthInSeconds = 1.0 / 60.0;
	        // Set this to the time in seconds of the frame to render.
		    localTime = frameToRenderHQ;
	        // This line will motion-blur the renders
	        localTime += Hash11(v21(fragCoord + seed)) * motionBlurLengthInSeconds;
	        // Jitter the pixel position so we get antialiasing when we do multiple passes.
	        vec2 jittered = fragCoord.xy + vec2(
	            Hash21(fragCoord + seed),
	            Hash21(fragCoord*7.234567 + seed)
	            );
	        // don't antialias if only 1 sample.
	        if (antialiasingSamples == 1.0) jittered = fragCoord;
	        // Accumulate one pass of raytracing into our pixel value
		    finalColor += RayTrace(jittered);
	        // Change the random seed for each pass.
		    seed *= 1.01234567;
	    }
	    // Average all accumulated pixel intensities
	    finalColor /= antialiasingSamples;
	#else
	    // Regular real-time rendering
	    localTime = iTime;
	    finalColor = RayTrace(fragCoord);
	#endif


    // ----- FPS Display Code Start -----

    vec3 fpsColor = vec3(1., 1., 0.);
    finalColor = mix( finalColor, fpsColor, PrintValue(fragCoord, grid(1, 1), fontSize, iFrameRate, 2.0, 0.0));

    // ----- FPS Display Code End -----



    fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
}

spin lud's icon

Would it make sense to use lower dimensions on the shader/slab and then upscale the output to full HD using the @dimscale attribute? Something like [jit.gl.slab @file flux-core.jxs @adapt 0 @dim 1536 864 @dimscale 1.25 1.25]