Thursday, April 16, 2026

Synopsis

The following discusses different topics in Modern OpenGL Tutorials.
The source code and compiled binaries can be accessed from Github.
______________________________________________________________________________________________________________________________________________________________________
Introduction
OpenGL is a graphics specification that can be used to render interactive 2D and 3D graphics applications.OpenGL has wide range of applications.This tutorials attempts to teach basic to advanced concepts one at a time. The goal is to create an advanced , multifunctional library from scratch. The tutorials will be a set of C++ header (.h) files.This tutorial is primarily targeted for windows OS. Visual Studio development environment is used for writing, compiling and debugging the code.
______________________________________________________________________________________________________________________________________________________________________
Implementation - Initializing OpenGL Context
As discussed earlier, OpenGL is a drawing specification that requires a context contained in a hosting window to draw upon. 
Creating OpenGL context in windows OS is not a trivial task. It's mainly because opengl.dll and  opengl.lib supplied by Windows only supports OpenGL specification 1.1. 
The display card providers such as Nvidia or Intel or AMD actually implement the latest and greatest OpenGL specification, including additional functionality as extensions and supply it as OpenGL Installable Client Driver or ICD. For example, nvogl.dll, atiogl.dll, or iglicd.dll etc.
These ICDs are registered and their locations are stored in the windows registry.
The OpenGL.dll supplied with windows acts as a wrapper and forwards any OpenGL API calls made by the client to the ICD.
This post discusses creating Hosting Window, initializing OpenGL context and handling Keyboard/Mouse events.
______________________________________________________________________________________________________________________________________________________________________
Lesson01 : Initializing OpenGL Context
This lesson discusses  implementing the basic operations of creating a hosting window, Initializing it with OpenGL context, rendering it and handle mouse/keyboard inputs.
______________________________________________________________________________________________________________________________________________________________________
Primer: Vector
Vectors are widely used  in 3D calculations. A 3D vector is represented as [Vx, Vy,  Vz] where  Vx, Vy and Vz represent numbers in 3D cartesian space.
______________________________________________________________________________________________________________________________________________________________________
Primer: Matrices and Affine transformations
OpenGL uses matrix operations for a lot of purposes. For example, translations, scaling, rotations. Also computing of projection matrices, view matrices etc. The following discusses it in detail.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Mouse and Keyboard Input Support, Camera and Camera Data
Camera is used for projections and animations. It holds camera data which is used for storing mouse and keyboard input information. Further, it stores computed transformation information such as pitch, yaw and roll angles, translation, scaleby as well as Model, View and Projection matrix information of the 3D object. 
______________________________________________________________________________________________________________________________________________________________________
Primer: Graphics Pipeline
A scene consists of  a set of  3D objects. Transformations such as translation, scaling and rotation as a result of Camera movement, mouse and keyboard input brings them into life. 
For example  the following diagram shows a multi color cube with  50 degrees pitch and 20 degrees yaw.
______________________________________________________________________________________________________________________________________________________________________
Implementation:Vertex Buffer
In this post we shall deep dive and understand mechanics behind sending vertex data to the GPU. Vertex data is obtained from mesh objects such as cubemesh which will be discussed later. The vertex data consists of Position, Color, Normal, and Texture Coordinate of each vertex. They are basically stored into VBO, EBO buffers. Later they are packaged into VAO objects.
______________________________________________________________________________________________________________________________________________________________________
Implementation: 3D Mesh
In this post we shall deep dive and understand implementing a mesh.
______________________________________________________________________________________________________________________________________________________________________
Implementation:Shader programs
The following provide an overview of shader programs and their implementation in this tutorial.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Pipeline
In this post we shall deep dive and understand mechanics behind rendering 3D objects on the screen.
So far we discussed  FrameBuffers,Vertex Array Object containing VBO and EBO buffers and  Program Object containing Vertex Shader and Fragment Shaders.
______________________________________________________________________________________________________________________________________________________________________
Implementation: CubeMesh and SingleColoredCube
In this post we shall deep dive and understand implementing a mesh and geometric object for cube shape. We will try to draw a single colored cube as shown above and rotate it along the three axes. The cube looks elongated because aspect ratio is not applied. 
______________________________________________________________________________________________________________________________________________________________________
Lesson02: Single Colored cube
In the previous posts the graphics pipeline and vertex processing were explained. Also, the implementation of the CubeMesh and SingleColoredCube were covered. 
In this post we will try to draw a single colored cube as shown above. The cube looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Multi Colored Cube

In SingleColoredCube we saw that VBOs were used to draw the single colored cube using Position data. In this post we  will discuss how to draw a Multi Colored cube using VBOs with Position and Color data having unique color on each face. It looks as shown at the bottom. It looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Lesson03: Multi-Colored Cube
In the previous posts the graphics pipeline and vertex processing were explained. Also, the implementation of the MultiColoredCube were covered. 
In this post we will try to draw a multi colored cube as shown above. The cube looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Implementation:Indexed Cube with interpolated colors
 In this post we  will discuss how to draw an IndexedCube using VBOs and EBO with interpolated colors. It looks as shown above. It looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Lesson04:Indexed Cube with interpolated colors
In the previous posts the graphics pipeline and vertex processing were explained. Also, the implementation of the CubeMesh and IndexedCube were covered. 
In this post we will try to draw a cube with interpolated colors as shown above. The cube looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Textured Cube
In the previous discussions, we covered sending vertex data - Position and color. In this post we will try to send texture vertex data. It's implemented in TexturedCube class.
______________________________________________________________________________________________________________________________________________________________________
Lesson05: Apply Texture to a Cube Interactively
In the previous posts the graphics pipeline and vertex processing were explained. Also, the implementation of the TextureUtil and TexturedCube were covered. 
In this post we will try to draw a cube with brick texture as shown above. The cube looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Primer:Lighting
Lighting is an important factor to consider while rendering realistic 3D shapes.  The following discusses adapting lighting conditions while rendering 3D images.
______________________________________________________________________________________________________________________________________________________________________
Implementation: LightedTexCube

In previous examples, we saw that Position, Color, Texture data were sent to draw cubes. In this post we  will discuss how to implement  Phong lighting models and other lights such as Directional, Point and Spot Lights. For this surface normals needs to be sent as VBO data.
______________________________________________________________________________________________________________________________________________________________________
Lesson06: Lighting a Textured Cube interactively
In the previous posts drawing a textured cube were explained. Also, the implementation of the LightingUtil and LightedTexCube were covered. 
In this post we will try to draw a textured cube with lighting interactively. The cube looks as shown above. The cube looks elongated because aspect ratio is not applied.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Drawing Text and Images
Modern OpenGL does not support drawing text or Images so it needs to be handled independently. There many popular libraries available such as freetype to render text in a scene.
______________________________________________________________________________________________________________________________________________________________________
Lesson07: Drawing Text and Images interactively.
As discussed in the  previous article, we saw how Text can be drawn in multiple fonts, sizes and colors and images can be placed side by side.
Also, the implementation of the TextMesh , TextureUtil  and TextImageSketcher were covered. 
In this post we will try to draw  text and image interactively.
______________________________________________________________________________________________________________________________________________________________________
Lesson08: Understanding Affine Transformation interactively.
In this post we shall understand affine transformations interactively the three kinds of affine 
transformations: Scale, Translate and Rotation on X, Y and  Z axes as discussed in the previous post.
The rotation has been already demonstrated in the earlier examples. In this post we will deep dive into Translation and Scaling.
______________________________________________________________________________________________________________________________________________________________________
Primer: Understanding View space, Perspective and Orthographic Projections
So far our camera was in a fixed position and transformations happened in object space.  In this post we will  look at the larger picture.
______________________________________________________________________________________________________________________________________________________________________
Implementation: DualProjectionCamera Camera
In the previous post, we understood how view matrix, perspective matrix and orthographic matrix. Two new cameras are used to provide perspective and orthographic views.
______________________________________________________________________________________________________________________________________________________________________
Lesson09: Roll Camera and Action Interactively
 In this post understand cameras space and Perspective and Orthographic  projections interactively.
______________________________________________________________________________________________________________________________________________________________________
Primer: Importing WaveFront OBJ Models
Thus far we have worked with the cube geometric object to understand the concepts. In real world, more complex and detailed geometric objects or models are used. They are generated by sophisticated softwares such as blender that can be exported to plethora image formats.
Wavefront OBJ is one such image format.
______________________________________________________________________________________________________________________________________________________________________
Implementation: Importing WaveFront OBJ Models
As discussed before, WaveFront OBJ and MTL files needs to be parsed to get geometry, Material information. A new mesh class and new geometry object are required for this. A new utility class  GenericObjParser is defined for loading OBJ and MTL files and generating VertexData, Material and texture information.
______________________________________________________________________________________________________________________________________________________________________
Lesson 10: Importing WaveFront OBJ Models using WFObjParser
As discussed in the  previous article, we saw how geometric objects can be imported from obj and mtl files. Also, the implementation of the GenericObjMesh, GenericObj and WFObjParser were covered. 
In this post we will try to render a model from "dolphin.obj" file.
______________________________________________________________________________________________________________________________________________________________________
Lesson 10a: Importing WaveFront OBJ Models using AssetImpParser
As discussed in the  previous article, we saw how geometric objects can be imported from obj and mtl files. Also, the implementation of the GenericObjMesh, GenericObj and and AssetImpParser were covered. 
In this post we will try to render a model from "adiyogi.obj" files.
______________________________________________________________________________________________________________________________________________________________________
Implementation: First Person and Orbit Cameras
An OpenGL application uses specialized cameras navigate a terrain in 3D scenes or wade thru sections of a complex structure. Some of such implementations are First Person Shooter (FPS) Camera or Orbit Camera or ARC ball Camera.
______________________________________________________________________________________________________________________________________________________________________
Lesson11: Traversing with First Person Camera in a Gallery
In this post we will discuss implementation of First Person Camera. In this post we shall understand its functionality.
______________________________________________________________________________________________________________________________________________________________________
Lesson12: Traversing with Orbit Camera in the Solar System
In this post we will discuss implementation of Orbit Camera. In this post we shall understand its functionality.














Sunday, August 28, 2022

Lesson12: Traversing the Solar System with an Orbit Camera

Overview 
As discussed in the previous article, we saw how Orbit Camera is implemented. 

Details
The purpose of Lesson12 is to demonstrate using Orbit Camera.

System  class diagram
The scene class overrides camera with an instance of OrbitCamera. 
Implementation
Scene
The functionality is implemented in the Scene class derived from BaseScene class. 
It creates an instance of WFObjParser which parses the "Solar system" OBJ files and generates instances of  MeshInfo objects, MaterialInfo objects, TextureInfo Objects. 
Each MeshInfo is associated with a MaterialInfo and 1 TextureInfo Object along with Vertex data. Each MeshInfo  is represented by an instance of GenericObj instance.
The three methods Init, DrawScene and Cleanup are overridden as below:
The Init method creates an instance of OrbitCamera and populates 3D objects of the Solar system
The DrawScene method draws a string and image. 

The message handler for IDOK is called when Apply button is pressed after updates are made in the input dialog. It refreshes the display.

The message handler for IDCANCEL is called when in Cancel button is pressed the input dialog. It calls 
OnCloseWindow to destroy window.

Finally, the WM_CLOSE  event is handled in OnCloseWindow function, and the window is destroyed and application is shutdown when the window is closed or Escape key is pressed. 

Application
Scene class is hosted main.cpp. which creates the scene object and displays it. Message pump is added to process windows messages.

Output
The output looks as shown in the top. 
The binaries can be accessed from here.


Saturday, August 6, 2022

Lesson11: Traversing a Gallery with a First Person Camera

Overview 
As discussed in the  previous article, we saw how First Person Camera is implemented. 

Details
The purpose of  Lesson11 is to demonstrate using First Person Camera.

System  class diagram
The scene class overrides camera with an instance of FPSCamera. 
Implementation
QuadMesh
A new mesh class  QuadMesh is defined for loading vertex data of 3D objects such as walls, floor, ceilings etc. It's used by another new class  QuadObj object for loading vertex data to vertex shader and texture data to the vertex and fragment shaders. 
This class derives from IGeometryMesh class. It contains information about Geometry information and Texture information. 

Quad
QuadObj derives from BaseGeometry class. It renders 3D objects such as walls, floor, ceilings etc. 
Scene
The functionality is implemented in the Scene class derived from BaseScene class.
The three methods Init, DrawScene and Cleanup are overridden as below:
The Init method creates an instance of FPSCamera and populates 3D objects such as walls, floor, cielings etc.
The DrawScene method draws a string and image. 
The message handler for IDOK is called when Apply button is pressed after updates are made in the input dialog. It refreshes the display.

The message handler for IDCANCEL is called when in Cancel button is pressed the input dialog. It calls 
OnCloseWindow to destroy window.

Finally the WM_CLOSE  event is  handled in OnCloseWindow function and the window is destroyed and  application is shutdown when the window is closed or Escape key is pressed. 

Application
Scene class is hosted main.cpp. which creates the scene object and displays it. Message pump is added to process windows messages.

Output
The output looks as shown in the top. 

The Source Code can be accessed from Lesson11: Traversing a Gallery with a First Person Camera
The binaries can be accessed from here.

Friday, August 5, 2022

Implementation: First Person and Orbit Cameras

Overview 
An OpenGL application uses specialized cameras navigate a terrain in 3D scenes or wade thru sections of a complex structure. Some of such implementations are First Person Shooter (FPS) Camera or Orbit Camera or ARC ball Camera.

Details
System  class diagram
New Camera classes derived from DualProjectionCamera are defined. They are FPSCamera and OrbitCamera,

A new mesh class  QuadMesh is defined for loading vertexdata of 3D objects such as walls, ceilings etc in a scene. It's used by another  Quad object for loading vertex data to vertex shader and texture data to the vertex and fragment shaders. 

FPSCamera
FPSCamera class is derived from DualProjectionCamera class. This camera captures objects from the viewpoint of a viewer. Some aspects have to be considered, like the characteristics of the camera (orbiting with the mouse and translation with keyboard keys).
The camera has the following characteristics:
Orbit: The character can look left, right, up, and down; however, if we imagine the character’s head, it can’t be tilted.
Translation: The character can move in four directions: forward, backward, left, and right, up and down. 
It process mouse and keyboard inputs and calculates forward, backward, left, and right, up and down movements. They are updated into MatrixData  objects.

Constructor
Initializes hwnd with the Window handle of the hosting window. Internally calls DualProjectionCamera constructor.

Members
Name  Description
camera_frontcontains front of the camera which gets updated when the viewer moves forward or backward or sideways.
camera_poscontains current position based on the movements of the viewer.
camera_upcontains front of the camera which gets updated when the viewer moves up or down.
mouse_sensitivitySensitivity of the mouse to calculate finer movements of the viewer.
velocitySpeed to calculate finer movements of the viewer.

Methods
NameDescription
OnKeyThis method handles keyboard input events and updates camera_pos as below:
W,S : Viewer Move forward or backward
A,D:Viewer Move Left  or right
R,F:Viewer Move Up or Down
OnMouseMoveUpdates camera_pos based on the mouse movements.
setSenseivitySets mouse_sensitivity and velocity values
updateViewMatrixSets starting values of camera_pos, camera_front and camera_up values.

OrbitCamera
OrbitCamera class is derived from DualProjectionCamera class. 
An orbit camera moves in a circle around a central object. The camera always looks at the center of the object. The viewer moves around the object in a circular path while keeping the focus fixed on that center point.  To calculate polar coordinates and spherical coordinates are used.
A polar coordinate represents a point in a 2D space as radius and angle. The point lies on the circumference where the radius is computed from the center point and the angle between the point and  the polar axis.
As shown below, the blue line represents polar axis. r represents the radius.

A spherical coordinate system specifies a given point in three-dimensional space by using a distance and two angles as its three coordinates. 
These are radius r,  the polar angle, θ, and the azimuthal angle, φ, which is the angle of rotation of the radial line around the polar axis.
The three coordinates (r, θ, φ), provide a coordinate system on a sphere, typically called the spherical polar coordinates. 


Given sphere with center point c and [r, θ, φ], the corresponding [x, y, z] coordinates are:
x = c.x + r * cos(θ) * cos(φ)
y = c.y + r * sin(θ)
z = c.z + r * cos(θ) * sin(φ)
They are updated into MatrixData  objects.

Constructor
Initializes hwnd with the Window handle of the hosting window. Internally calls DualProjectionCamera constructor.

Members
Name  Description
_minRadiusThe minimum value of radius set during zoom operation.
azimuthAngle_contains the value of current azimuth angle.
center_The center defaulted to 0,0,0.
polarAngle_contains the value of current polar angle.
radiusThe current value of the radius.
upVector_The up vector defaulted to 0,1,0.
zoomfactorThe increments of the zoom both ways defaulted to 0.5
mouse_sensitivitySensitivity of the mouse to calculate finer movements of the viewer.

Methods
NameDescription
OnKeyThis method handles keyboard input events and updates radius as below:
Left Arrow : Makes radius bigger
Right Arrow : Makes radius smaller
OnMouseMoveLeft Button: Rotates all the objects
Right Button: Changes Azimuth and Polar angles resulting in circular motion of the objects
Middle Button: Changes center point resulting in panning motion of the objects horizontally and vertically.
geteyeReturns current viewer position
getNormalizedViewVectorReturns normalized value of  (center_ - getEye())
getUpVectorReturns upVector_
getViewPointReturns center_
moveHorizontalPans entire scene horizontally as a result of mouse movement
moveVerticalPans entire scene vertically as a result of mouse movement
rotateAzimuthRotates entire scene horizontally as a result of mouse movement
rotatePolarRotates entire scene vertically as a result of mouse movement
updateViewMatrixSets view matrix data based on current positions of the eye, center_ and upVector_.
zoomSets fov based on keyboard input resuting in zoom out and zoom in actions.

The Source Code can be accessed from FPSCamera, OrbitCamera

Wednesday, August 3, 2022

Lesson 10a: Importing WaveFront OBJ Models using AssetImpParser

Overview 
As discussed in the  previous article, we saw how geometric objects can be imported from obj and mtl files. Also, the implementation of the GenericObjMesh, GenericObj and GenericParser were covered. 
In this post we will try to render a model from "Adiyogi.obj" and "Adiyogi.mtl" files.

Details
The purpose of  Lesson10a is to demonstrate importing an obj and mtl files to extract geometry and material information.

System  class diagram
The scene class overrides camera with an instance of DualProjectionCamera. 
Implementation
Scene
The functionality is implemented in the Scene class derived from BaseScene class. It creates an instance of AssetImpParser which parses the OBJ file and generates 1 more MeshInfo objects, MaterialInfo objects, TextureInfo Objects. 
Each MeshInfo is associated with a MaterialInfo and 0 or 1 TextureInfo Object along with Vertex data. Each MeshInfo  is represented by an instance of GenericObj instance which later becomes 
The three methods Init, DrawScene and Cleanup are overridden as below:
The Init method calls 
  1. BaseScene::Init to create hosting window and OpenGL Context. 
  2. It creates an input dialog to import obj, and mtl files and input texture files.
  3. It calls init function with an instance of  GenericObj object. Internally it creates a GenericObj Mesh object to load geometry and material information from the object files and to populate VBO/EBO buffers and bind them. Also create texture if necessary 
  4. It also compiles and links shader programs.
The DrawScene method draws a string and image. 

The message handler for IDOK is called when Apply button is pressed after updates are made in the input dialog. It refreshes the display.

The message handler for IDCANCEL is called when in Cancel button is pressed the input dialog. It calls 
OnCloseWindow to destroy window.

Finally the WM_CLOSE  event is  handled in OnCloseWindow function and the window is destroyed and  application is shutdown when the window is closed or Escape key is pressed. 

Application
Scene class is hosted main.cpp. which creates the scene object and displays it. Message pump is added to process windows messages.

Input dialog
The input dialog as shown below can be used to change settings and understand drawing text and images.
Output
The output looks as shown in the top. 
The Source Code can be accessed from Lesson 10a: Importing WaveFront OBJ Models using AssetImpParser
The binaries can be accessed from here.