3
\$\begingroup\$

I'm learning GLSL shaders on Book of Shaders and I decided to mess around with one of the examples. I wanted to see, whats a more efficient way to calculate to mask out the color?

#ifdef GL_ES
precision mediump float;
#endif

#define TWO_PI 6.28318530718

uniform vec2 u_resolution;
uniform float u_time;

//  Function from Iñigo Quiles
//  https://www.shadertoy.com/view/MsS3Wc
vec3 hsb2rgb( in vec3 c ){
    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0,0.0,1.0);
    rgb = rgb*rgb*(3.0-2.0*rgb);
    return c.z * mix( vec3(1.0), rgb, c.y);
}

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution;
    vec3 color = vec3(0.0);

    // Use polar coordinates instead of cartesian
    vec2 toCenter = vec2(0.5)-st;

    float angle = atan(toCenter.y,toCenter.x);
    float radius = length(toCenter)*2.0;

    angle = angle + u_time;

    float outsideMask = 1.0 - step(distance(st, vec2(0.5)), 0.3);
    float insideMask = 1.0 - step(0.2, distance(st, vec2(0.5)));
    float visibleArea = 1.0 - insideMask - outsideMask;

    // Map the angle (-PI to PI) to the Hue (from 0 to 1)
    // and the Saturation to the radius
    color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius, 1.0));

    gl_FragColor = vec4(color, visibleArea);
}

Here is an image of the end result.

End Result.

The outsideMask, insideMask and visibleArea variables in particular all have that 1.0 minus something, which seems weird to me. Any suggestions would be appreciated!

\$\endgroup\$
3
\$\begingroup\$

Distance

In both your step(...) functions, you are computing distance(st, vec2(0.5)). If you computed this once, and stored this in a local variable, you'd be able to reuse this computed value, which should save time in your shader.

But ... wait a second ...

vec2 toCenter = vec2(0.5)-st;
float radius = length(toCenter)*2.0;

You've already computed this distance (length, actually), and stored it (doubled) in the local variable radius. We can use this value directly, by doubling your step thresholds:

float outsideMask = 1.0 - step(radius, 0.6);
float insideMask = 1.0 - step(0.4, radius);
float visibleArea = 1.0 - insideMask - outsideMask;

Or don't multiply the computed radius by 2.0 for the radius variable, and multiply it by 2 when you use it to compute the colour:

float radius = length(toCenter);

float outsideMask = 1.0 - step(radius, 0.3);
float insideMask = 1.0 - step(0.2, radius);
float visibleArea = 1.0 - insideMask - outsideMask;

color = hsb2rgb(vec3((angle/TWO_PI)+0.5, radius*2.0, 1.0));

visibleArea

  1. outsideMask = 1.0 - step(radius, 0.3)
  2. insideMask = 1.0 - step(0.2, radius)
  3. visibleArea = 1.0 - insideMask - outsideMask

Substituting insideMask into (3):

  1. visibleArea = 1.0 - (1.0 - step(0.2, radius)) - outsideMask
  2. visibleArea = 1.0 - 1.0 + step(0.2, radius) - outsideMask
  3. visibleArea = step(0.2, radius) - outsideMask

From step(A,B) = 1 - step(B,A), we can reworking (1) as:

  1. outsideMask = step(0.3, radius)

And substituting into (6):

  1. visibleArea = step(0.2, radius) - step(0.3, radius)
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.