Search code examples
glslwebglfragment-shadervertex-shader

shader-school, vertex shaders: varying variables


I am currently in the process of learning a bit of graphics programming / glsl using shader-school, which works great. However I am stuck at the second lesson about vertex shaders.

The triangle asked for the solution seems to display a triangle filled with the differents hues of the YUV color space:
YUV-Wheel

I know that it's possible to calculate the conversion between RGB and YUV, however I am not quite sure about how the coordinate space in the vertex or fragment shader works.

My vertex shader looks like this:

precision highp float;

attribute vec4 position;
attribute vec3 color;

varying vec4 fragPosition;
void main() {
  gl_Position = position;
  fragPosition = position; // send the position to the fragment shader
}

while my fragment shader looks like this:

precision highp float;

varying vec4 fragPosition; // is set by vertex shader

void main() {
  gl_FragColor = fragPosition.rgba;
}

And the rendered triangle looks like this (left part is the problem to solve, right part is my solution so far):

shader-school lesson about vertex shaders #2

fragPosition.a is continuously 1.0; why does the fading look so weird? How exactly does the coordinate space inside the triangle? I can't wrap my head around it and without breakpoints or print statements it's not that easy to figure out. Why is the bottom left corner completely black, and why is there no blue spot?


Solution

  • The default space for opengl is the NDC space. Its a unit cube in range of [-1,1]. Where x=-1 is at the left side of screen, x=1 is at the right side of screen, y=-1 bottom, y=+1 top, z=-1 at the near plane, and z=+1 at the far plane.

    What you are basically doing in your shader right now is displaying the fragment coordinate as a color.

    The top of your triangle is green because the coordinate is something like [0,1,0,1] and when interpreted as a color, that gives it a green color. The right of triangle has the coordinate [1,-1,0,1] which gives it a red color. The bottom is likely to be something like [0,-1,0,1] which is black.

    Btw, I am not sure if fragment.a is actually 1.0, you can check by doing gl_FragColor = fragPosition.aaaa;. If .a is 1.0 then you should only see white, if .a is ~0.5, it should be gray and so on.

    I am guessing here, I think what you are suppose to do in this lesson is to use color inputs instead (attribute vec3 color;) and implement the rgba to yuv conversion in the shader.