Demystifying OpenGL Shaders

What is a shader? a shader is a small program developed by you that lives in the GPU. A shader is written in a special graphics language called OpenGL Shading Language (GLSL). A shader takes the place of two important stages in the OpenGL pipeline: "Per-Vertex Processing" and "Per-Fragment Processing" stage.

Long ago, these stages were provided by OpenGL as static-configurable stages. However, this prevented graphical effects creativity. OpenGL solved this problem by creating the concept of shaders. 

There is one shader for each stage. The shader processed in the "Per-Vertex" stage is called Vertex Shader. The shader processed in the "Per-Fragment" stage is called Fragment Shader. The ultimate goal of the vertex shader is to provide the final transformation of the character’s vertices to the rendering pipeline. The goal of the fragment shader is to provide coloring and texture data to each pixel heading to the framebuffer.

Passing data to Shaders

Data is passed down from your application to the GPU through OpenGL Objects. This data is first received by the Vertex Shader. Inside the vertex shader, this data is defined as an Attribute. Unlike the Vertex Shader, the Fragment Shader can not receive data directly. Any data that is required by the Fragment Shader is passed down from the Vertex Shader and is defined as a Varying data type in both shaders. The only exception, is data defined as Uniform. Uniform data can be received by the vertex shader and fragment shader.

Attributes, Varying and Uniforms

GPU data received by a vertex shader is considered an Attribute, for example, vertex, normal and UV-coordinates. A Uniform is a global variable that can be received by both vertex and fragment shader. Usually, attributes is defined as data that may constantly change. Whereas uniform is defined as data that will rarely change, e.g. a transformation matrix.

Your application must inform OpenGL which data being sent to the GPU should be considered an attribute or a uniform.

A fragment shader can not receive data from the GPU directly. Thus, attributes can not defined in fragment shader. If a fragment shader requires the data of an attribute, a new variable of type Varying is defined in the vertex shader. The attribute data is copied onto the varying variable. The Varying variable is then sent from the vertex shader to the fragment shader for further processing.

Shaders Output

Although shaders allows you to be creative in their implementation, shaders require data for two output built-in variables: gl_Position and gl_FragColor.

gl_Position

The gl_Position is used by the vertex shader to hand over the transformed vertices to the rendering pipeline.

gl_FragColor

The gl_FragColor is used by the fragment shader to provide coloring and texture data to each pixel heading to the framebuffer.

Harold Serrano

Computer Graphics Enthusiast. Currently developing a 3D Game Engine.