Vertex Shader and Fragment Shader

1.0 Introduction

As beginners continue to make progress with OpenGL, they should pick up more new tools to advance their learning. One of the recommended tools is Shader. In this blog, I will discuss the advantages of using vertex and fragment Shaders and some basic OpenGL Shading Language.

2.0 Advantage of Shader over Fixed-Function OpenGL pipeline

With Shader, users can put and run codes in the GPU, this can significantly improve performance of the product as GPU can simultaneously excuse multiple data streams and fragments. Display rate can increase to hundreds of frames per second [1]. In addition, Shader provide flexibility and quality for graphic design. Per-fragment lighting and per-fragment animation, for example, could produce effective and attractive visual effects for users.

2.1 Roles of Vertex shader and fragment shader in the OpenGL pipeline

Studying the figure 1 can help users understand the roles of vertex Shader and fragment Shader in the OpenGL pipeline compared to the fixed-functions. Vertex Shader will replace the sequential steps of model transform, view transform, per – vertex lighting, and projection transformation with some built-in variables such as gl_Vertex, gl_Color, gl_Normal, gl_ModelViewMatrix, gl_ProjectionMatrix, gl_ModelViewProjectionMatrix. Vertex Shader use in variables and uniform variables. The gl_Position and out variable created from vertex Shader undergo the rasterization process to create a fragment for every pixel.  Fragment Shader is used in variable, uniform variable, and local variables to perform fragment processing, texturing, and per-fragment lighting. gl_FragColor produced from fragment Shader then get into the framebuffer. 

Figure 1: The Shader-style in the OpenGL pileline.

2.2 Basic knowledge of OpenGL Shading Language (GLSL)

There is no pointer, string, or enum in GLSL. Also, GLSP does not support mixed data types; thus, users need to cast data. For vectors, vector components include x, y, z, w (for geometric data) or r, g, b, a (for color data) or s, t, p, q (for texture data). Swizzle notation can help create new vectors based on other defined vectors. Common vectors are Boolean vectors (bvec2, bvec3, and bvec4), Integer vector (ivec2, ivec3, and ivec4), and float point vector(vec2, vec3, and vec4). Studying the below examples [3] can be a good way to understand how vectors work in GLSP. 

Figure 2: Basic variables in GLSL.

In GLSP, users need to declare functions before calling them. If-else statement, while loop, and for loop can also be utilized. For calculation, some command functions are exp(), log(), sqrt(), mod(), fract(), ceil(), floor(), abs(), min(), max(), fract(), clamp(), sin(), cos(), etc. Math functions can be used to animate, to distort shape, and blend values.  

GLSL is used to write vertex and fragment shaders, but there are some similarities and differences between those two shaders. Both vertex and fragment shaders have a main function, built-in functions, variables, and expressions. Uniform is a read-only variable that both vertex shader and fragment shader can read from. 

2.2.1 Vertex Shader

However, some specific built-in functions are used for vertex Shader only. The out variables are  from vertex Shaders. Attribute variables can only be read from the vertex Shader. The gl_Vertex and gl_Normal are the two important built-in variables in vertex Shader. In Shader, without vec4 gl_Vertex, one can not draw any geometry; without vec3 gl_Normal, one cannot light the object. The vertex position and normal vector for each vertex can be defined in OpenGL and is accessed in vertex Shader file and fragment Shader file using the built-in gl_Vertex and gl_Normal respectively. Interestingly, users can set the rgb color for an object by using the untransformed gl_Vertex or the transformed gl_Vertex. The final color effect is very different. While the untransformed one has a fixed color position, the transformed one allows color to change based on position. 

Figure 3: Untransformed vs. transformed gl_Vertex in setting rgb.
Source: [2]

2.2.2 Fragment Shader

Fragment Shaders help build  per-fragment lighting. As users might notice, the fixed-function OpenGL can only allow per-vertex and per-face  lighting. In per-vertex lighting might be fast, but the quality seems different from the per-fragment lighting. In per-vertex light, tessellation of the surface impacts the lighting quality [4]. 

Figure 4: per-vertex vs. per-fragment lighting effect.
Source: [4]

3.0 Conclusion:

We have learned some basic background for vertex Shader and fragment Shader. Hopefully, this could add some more understanding for some beginners who start programming with those Shaders. With Shader, users make a huge difference in the quality and performance of of graphic design.  


[1] L3Harris Geospatial. (2020). How Shaders Enhance Performance. [Online]. Available: Accessed Oct 19th, 2021.

[2] Mike Bailey.(2021). Introduction to using the OpenGL Shading Language (GLSL). Oregon state university. [Online]. Available:

[3] Learn WebGL.(2016). GLSL Data types and Variables.[Online]. Available: Accessed: Oct 19th, 2021.

[4] Steve Burke. (2016). GPU Rendering & Game Graphics Pipeline Explained with nVidia. Gamer Nexus. [Online]. Available: Oct 19th, 2021.

Print Friendly, PDF & Email

Leave a comment

Your email address will not be published.