introduction
2 - Introduction to shaders
An introduction to GLSL shaders with a very basic example
The Canvas, The Colors, The Code
Welcome back, art-code aficionados! It's Walter Vikrus, your resident shader shaman, ready to guide you through the mystical realms of GLSL. In our last work, we set the stage for our shader art adventure. Today, we're getting our hands dirty with some actual code, focusing entirely on the fragment shaderβthe heart and soul of our artistic expression.
First, let's talk canvas. In the world of shader art, our canvas isn't a rectangle of fabric; it's a 2D plane in normalized device coordinates (NDC). This means our canvas stretches from (-1, -1) in the bottom-left to (1, 1) in the top-right. Every pixel on your screen maps to a point in this space. It's like graphing in math class π, but instead of plotting points, we're painting dreams! π
Now, let's dive straight into our fragment shader, where all the magic happens:
precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 v = gl_FragCoord.xy/u_resolution.xy;
v.x *= u_resolution.x/u_resolution.y;
v = v * 2.0 - 1.0; // Map to NDC
vec3 color = vec3(0.0);
gl_FragColor = vec4(color, 1.0);
}
Don't worry if this looks like alien language now; we'll decipher it together:
-
precision mediump float;
-
We're telling the GPU, "Hey, we don't need super high precision for our floats." It's like saying we're painting with acrylics, not doing brain surgery π¨π§ .
-
uniform vec2 u_resolution;
-
This is our canvas size. The GPU tells us how many pixels wide and tall our masterpiece will be π.
-
uniform float u_time;
-
An ever-increasing value. Great for animation! Think of it as our artistic heartbeat π.
-
vec2 v = gl_FragCoord.xy/u_resolution.xy;
-
This normalizes our pixel's position to [0, 1]. Like saying "this pixel is 30% from the left and 70% from the bottom." π
-
v = v * 2.0 - 1.0;
-
We're mapping our space to NDC (-1 to 1). Our true artist's canvas! π¨
-
v.x *= u_resolution.x/u_resolution.y;
-
Finally, we adjust for aspect ratio. No squished art here! πΌοΈβοΈ
-
vec3 color = vec3(0.0);
-
Our color, in RGB.
(0.0, 0.0, 0.0)
is black. We'll spice this up soon! β¬ -
gl_FragColor = vec4(color, 1.0);
-
We're setting our pixel's color. The
1.0
is alpha (opacity) π’.
That's it! This compact block of code is your complete fragment shader. In GLSL, the fragment shader runs once for every pixel, deciding its color. It's like having millions of tiny artists π¨βπ¨π©βπ¨π¨βπ¨π©βπ¨π¨βπ¨, each responsible for painting a single dot of your masterpiece, all working in perfect synchronization.
Black Canvas
Right now, our shader is the digital equivalent of a black canvas. Groundbreaking, I know. πΆοΈ But fear not! This minimalist start is intentional. We're setting up our artistic workspace, ensuring our canvas is correctly scaled and oriented. It's like preparing a pristine black canvas, stretching it just right, before we unleash our creativity.
In our next post, we'll breathe life into this monochrome canvas with the vibrant pulse of shader artistry: color manipulation. We'll learn to mix, blend, and transition colorsβcreating sunsets π , ocean depths π, and aurora skies πβall using simple mathematical functions. We're not just coding; we're becoming digital colorists, each line of code a squeeze from our infinite paint tubes. π¨π’β¨
And for those who love math as much as I do (there are dozens of us! DOZENS! π€), we'll delve into the enchanting world of gradients and alpha blending. These aren't just color ramps and transparency values; they're the very equations of light's journeyβits birth in vibrant hues π, its travel through mediums π, and its gentle fading into shadow π. We'll turn oscillations into rainbows, distances into soft fades. Get ready to see math not just calculate color, but caress it. ποΈπβ¨
And if you can't wait, homework time! π Play with our basic shader by yourself:
-
Change
vec3(0.0)
tovec3(1.0, 0.0, 0.0)
. What happens? π΄ -
Try
vec3(v.x, 0.0, 0.0)
orvec3(v.x, v.y, 0.0)
. Notice anything cool? π -
Add
u_time
to the mix:vec3(sin(u_time), v.x, v.y)
. Groovy, right? πΊ
Each change you make to color
transforms your entire canvas. That's the power of shaders: with a single line of code, you command millions of pixels. It's pointillism at the speed of light! π¨β‘
Remember, in the realm of shader art, every line of code is a brushstroke, every function a technique. We're not just programmers or artists; we're digital alchemists, transforming raw mathematics into visual gold. Our fragment shader is our philosopher's stone, turning the lead of coordinate pairs into the gold of vivid imagery. π§ββοΈβ¨
Next time: Shapes, Distance, and the Space Between. Get ready to see your code come alive with geometric poetry! We'll use our fragment shader to sculpt forms from pure math, painting not with strokes, but with equations. Until then, keep your vectors normalized and your gradients smooth. π¨π»β¨
If you enjoyed this virtual work, please consider dropping me a line or making a donation to support my work. Your feedback and support mean a lot and help keep this project going. Thank you!
Reach out Donate back