Skip to content
Tags

75. The fragment shader

June 3, 2013

Now we’ll look at the fragment shader in more detail.

If you look at the Fragment tab in your custom shader in the Shader Lab, you should see this code

//
// A basic fragment shader
//

//Default precision qualifier
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;

//The interpolated vertex color for this fragment
varying lowp vec4 vColor;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
    //Sample the texture at the interpolated coordinate
    lowp vec4 col = texture2D( texture, vTexCoord ) ;
    gl_FragColor = col;
}

This doesn’t look too different from the code for the vertex shader, and if you look at the variables above the main function, you’ll see some old friends, vColor, and vTexCoord, and they are defined exactly the same way.

However, they are not exactly the same, because in the vertex shader, they gave the value for a particular vertex, whereas here, they give the (interpolated) values for a pixel. So you might only have 10 vertices that use the vertex shader, but you might have 1000 pixels that use the vertex shader.

There is a new variable, texture, defined as uniform (so it applies to all pixels) and as a sampler2D (ie a 2D image like those in Codea). This is the texture image that will be used to choose the colour for the pixel.

Now, I did explain the code once before, but I’ll do it again.

The first line of code in main defines a new local variable called col, which is a vec4 with low precision (not that we care about that). Note that you don’t need to give OpenGL a reason for it being there (ie attribute, varying or uniform), because it is purely local to the main function.

The texture2D function is like myImage:Get(i,j) in Codea. It gets the color at the position x,y in the texture image, where x and y are 0-1.

The second line simply passes this on to the output variable, gl_FragColor.

This is pretty boring, so let’s try changing it.

Making a colour change

In your Shader Lab example, add a line between the two existing lines, like so

    lowp vec4 col = texture2D( texture, vTexCoord );
    col.g=1.-col.g;   // NEW
    //Set the output color to the texture color
    gl_FragColor = col;

and you should see this
http://instagram.com/p/aAVARQhHeA/

What we have done is flip the green colour, so if it was low, it is now high, or vice versa. You may wonder why we subtracted it from 1, when colour values go up to 255. Well not in OpenGL, they don’t. They are converted to a scale from 0 to 1 (=255), with fractions in between.

This is why, if we have set a colour for the vertices as well as a texture, we can apply it to the pixel by multiplying like so

     gl_FragColor = col * vColor;

The result of col * vColor = vec4(col.r x vColor.r, col.g x vColor.g,…etc).

You can see this with a simple experiment. We’ll make the logo go dark.

Alter the last line to

     gl_FragColor = col * 0.2;   //reduce light to 20% of full value

This works because 0.2 is multiplied by each of the r,g,b,a parts of col.

Now it would be really cool to be able to do this from Codea, ie to make your scene go light or dark.

And there is a way.

Next time.

From → Shaders

3 Comments
  1. degraevesofie permalink

    Question: Why is there no declaration of gl_FragColor? I.e., I would have expected:
    varying lowp vec4 gl_FragColor;
    in the preamble, no?

    • It is declared out of sight. The gl_Position variable in the vertex shader is the same. I guess they didn’t want to clutter up the shader code with stuff that had to be there anyway.

Leave a comment