VBAK

Posted on

The Fence Problem from The Book of Shaders

I am working through Patricio Gonzalez Vivo's The Book of Shaders which is turning out to be one of the best (engaging, challenging, fun) technical books I've come across. The Think series by Allen Downey is to Python and Statistical Learning as this book is to computer graphics. At least that's how it feels.

I'm on Chapter 5:

This chapter could be named "Mr. Miyagi's fence lesson."...

...The following code structure is going to be our fence:

``````#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

// Plot a line on Y using a value between 0.0-1.0
float plot(vec2 st, float pct){
return  smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}

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

float y = st.x;

vec3 color = vec3(y);

// Plot a line
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);

gl_FragColor = vec4(color,1.0);
}
``````

I spent the first day staring at and playing around with that code. I didn't get much out of that (immediately).

distraction or my mind digesting information

I took a detour and worked through the wonderfully short and packed tutorials from Toby Schachman's Shadershop which were uh-mazing. If you haven't tried it and are interested in learning about the construction of noise for complex computer graphics you should definitely go through his videos. His pedagogy is built around spatial learning which is a profound concept for learning computer graphics and definitely has influenced my thinking about the field.

back to the fence

I was ready to take on the Fence Code after some Shadershop wins. I realized that I was trying to figure out the Fence Code only in my head, which was why I was hitting a roadblock, or rather, fence. The reason Shadershop was so effective was that it allowed visual learners to use a spatial medium to control the code and view the effects on the resulting graphic. I chose to take that as advice.

I added a few more uniforms to the Fence Code, and used WebGL Fundamentals' boilerplate to set up the WebGL context and sliders to control the shader function uniform variables.

Below is a codepen I created to show the result. Note the change in the (very small) preformatted text when you move the sliders to help you visualize the process better:

I'm itching to jump to some conclusions about the relationships between uniform variable values and the graphical result, but the more I play around with different value combinations, the broader those relationships get. So I'm not quite ready to move on from this chapter.

The biggest takeaway from this experience: the color value and position of the pixels are handled separately. I know, i know, the shader functions themselves are separate so they are handled separately, but I wasn't comfortable with the concept.

So I added a `u_count` uniform variable in the fragment shader's script, which determines how many of the triangles are drawn on the canvas (there are a total of 24 triangles). Changing that count does not affect the color of the canvas. So the fragment shader is generating a color map of sorts which is applied over all pixels of the canvas, not just the ones that are specified in the vertex shader. This led me to two conceptual confusions I couldn't quite visualize before: that animations could be made almost entirely with fragment shaders----varying the color of the pixels over time instead of "moving" (more like changing the visibility of) the pixels over time (as you would do with hand-drawn animations) could give similar or same results, and that shader scripts are run by the GPU which processes in parallel (i.e. all the pixels at the same time).

Thanks for reading!