How does this shader code work?

I’ve been going through the book of shaders tutorial and am having trouble understanding the way this shader generates any color at all.

#version 150

uniform vec2 u_screenRes

void main()
{
    vec2 coord = gl_FragCoord.xy/u_screenRes;
    coord *= 10;
    vec2 cF = fract(coord);    
    vec2 tile = cF;
     
    float c = (step(length(tile),0.6) -
              step(length(tile),0.4) ) +
             (step(length(tile-vec2(1.)),0.6) -
              step(length(tile-vec2(1.)),0.4) );
    vec4 color = vec4(c);
    gl_FragColor = vec4(color);
}

It looks like this:

But if tile is always a vector with an x and y each between 0.0 and 1.0, c should never have a value higher than 0. it should always return either 0 or -1. So why does it draw white waves?

Hi @s_e_p
That is because the length function returns a float and then the step function goes to zero if below the threshold (the hard coded number there) or 1 if above. at the end c is actually an integer, because you only added or substracted 1 and 0. last, when you pass a float to vec4( ) it will assign that value to all the values of the vec4, hence you end up with all values 0 or more or equal to 1. Does it make sense?

1 Like

Hey Roy,

No, I don’t get it, because every pair of values I try to work this out for returns either -1 or 0; never 1. I even tried running the equation in c++ and printing the values

int ofApp::step(float edge, float x)
{
	return edge > x ? 1 : 0;
}

float ofApp::length(ofVec2f v)
{
	return std::hypot(v.x, v.y);
}

void ofApp::setup()
{
	for (int i = 0; i < 100; ++i)
	{		
		tile.y = 0.0f;
		for (int j = 0; j < 100; ++j)
		{
			float a = (step(length(tile), 0.6) -
				step(length(tile), 0.4)) +
			(step(length(tile - ofVec2f(1.0f)), 0.6) -
				step(length(tile - ofVec2f(1.0f)), 0.4));
			cout << a << ", ";
		}
		tile.x += 0.01f;
	}
}

and it’s all -1s and 0s only. Is there something wrong with my simulation?

Just checked and your step code is flipped
https://registry.khronos.org/OpenGL-Refpages/gl4/html/step.xhtml
int step(float edge, float x)
{
return x < edge ? 0 : 1;
}

1 Like

What @roymacdonald said and you also need to increment tile.y.

Ahh, that’s it. Thank you!

(@hubris you’re right, but that was a mistake when I was copying and cleaning up the code for here)

I often find it helpful to break shader code into smaller pieces, to see how it works. With the original code, you can see how the step() functions affect the color. It can be a good way to troubleshoot:

    // run each separately in the shader to see what they do
    float c = step(length(tile), 0.6);
//    float c = step(length(tile - vec2(1.0)), 0.6);
//    float c = step(length(tile), 0.6) - step(length(tc), 0.4);
2 Likes