Showing posts with label VOGL Library. Show all posts
Showing posts with label VOGL Library. Show all posts

Monday, July 11, 2022

Modern OpenGL Library Implementation - Part 2

 Every 3D object such as cube derives from BaseGeometry class. The following describes this in details.

CameraData class  holds transformation information such as pitch, yaw and roll angles, translation, scaleby as well as Model, View and Projection matrix information of the 3D object. It's implemented in VOGLLib\Camera \CameraData,h file. CamaraData of a 3D object is modified by BaseCameraInputHandler object the of the scene discussed earlier.

IGeometryMesh structure defines the abstract class that every 3D object must override. It defines methods for generating vertices for the 3D object and populating VBO and EBO buffers of VAOUtil object.  It's declared in VOGLLib\Geometry\GeometryMesh.h file. 

VAOUtil  class defines a  VAO and its associated VBOs and EBO discussed in the previous post. The VertexData class stores VBO and EBO data and manages its lifetime. VaoUtil class and VertexData class are implemented  in VOGLLib\Geometry\VAOUtil.h file.  VAOUtil class defines VertexData class for Position, Color, Normal, Texture Coordinates and Indices.
In a typical usage scenario, a 3D object first loads all the vertex data such as position by calling  GenerateVerticesData method of the mesh. Then it calls SetupVBO method for all the vertex data with location number of the the vertex data. Note that the location number has to match with the location number defined in the vertex shader. First time, this will generate a VAO and bind it. VBO is created, data is loaded for GL_STATIC_DRAW, bound and associated with the location and the location is enabled.
In cases of indices, the indices are loaded by calling  GenerateIndicesData method. Later BindEBO method is called. This will  generate a EBO, data is loaded for GL_STATIC_DRAW, bound.

ShaderUtil class loads shader code such as vertex shader and fragment shader , creates program object, attaches shader code and links them to the program object. In addition shaderUtil also stores attribute locations and uniform locations. Errors in compilation are written to the errorlogs.
In usage, first the shader code is attached and linked. At the time of drawing, uniforms are updated and program is set for use. Draw method is called to draw the 3D object. finally program is reset for use. 
ShaderUtil class is implemented  in VOGLLib\Geometry\ShaderUtil.h file.

BaseGeometry class implements base class for all the 3D objects. All the 3D objects such as cube must derive from this class. BaseGeometry class defines 
Init method that loads and attach shaders to program object. 
Cleanup method that does cleanup. 
UpdateUniform updates Projection matrix uniform.
Draw method calls  OpenGL APIs such as glDrawArrays or glDrawElements are used to draw the 3D objects.
In usage, VertexShaderSource and FragmentShaderSource are overridden to supply shader code. Init, Cleanup, UpdateUniforms methods are overridden based on the customization.

Mouse and Keyboard input support


As discussed earlier, the BaseScene object captures  all the Mouse and Keyboard activities such as key press, mouse button press, move etc.  Later it's processed by BaseCameraInputHandler class. For example, If  key is pressed, it's scan code is stored. similarly,  if mouse left button is pressed and mouse is moved and then released, delta x and delta y are computed. All the data is stored in  CameraData.
Later this data is shared with all the 3D objects in the scene to redraw.

For Example, SimpleCameraInputHandler object implements keyboard and mouse handling as below:
Press X key  => rotate around X axis by 10 degrees.
Press Y key  => rotate around X axis by 10 degrees.
Press Z key  => rotate around Z axis by 10 degrees.
Mouse Left Button Down. Mouse Move, Mouse Left Button Up => Compute Delta X, and Delta Y.
Later this is shared with 3D objects in the scene to draw.


Friday, July 8, 2022

Modern OpenGL Library Implementation - Part 1

Source code of modern OpenGL library is located under VOGLLib folder . It's a set of header files that can be included by the client applications.  The directory structure looks as below.



CompileLink.h
This header files defines locations of the externals.  Note that include file locations and libraries locations are predefined. If your setup is different then this file needs to be edited.
       
#define WGL_WGLEXT_PROTOTYPES
#pragma include_alias( "GL/GL.h", "..\..\externals\GLExtensions\GL\GL.h" )
#pragma include_alias( "GL/wglext.h", "..\..\externals\GLExtensions\GL\wglext.h" )
#pragma include_alias( "SOIL2.h", "..\..\externals\SOIL2\src\SOIL2\SOIL2.h" )
#pragma include_alias( "glm/glm.hpp", "..\..\externals\glm\glm\glm.hpp" )
#pragma include_alias( "glm/gtc/matrix_transform.hpp", "..\..\externals\glm\glm\gtc\matrix_transform.hpp" )
#pragma include_alias( "glm/gtc/type_ptr.hpp", "..\..\externals\glm\glm\gtc\type_ptr.hpp" )

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "gdiplus.lib")
#ifdef _DEBUG 
#pragma comment(lib, "..\\..\\externals\\GLExtensions\\lib\\GLExtensions_static_x86_d.lib")
#pragma comment(lib, "..\\..\\externals\\SOIL2\\projects\\VC15\\libs\\SOIL_static_x86_d.lib")
#else
#pragma comment(lib, "..\\externals\\GLExtensions\\lib\\GLExtensions_static_x86.lib")
#pragma comment(lib, "..\\externals\\SOIL2\\projects\\VC15\\libs\\SOIL_static_x86.lib")
#endif

Geometry
This folder defines some base classes responsible for sending vertex data and also rendering  objects such as Text, Cube etc.

Camera
This folder contains classes responsible  for different type of projections of  the scene and mouse and keyboard handling for the same.

Lighting
This folder contains classes responsible lighting the objects in the scene.

Scene
This folder contains classes responsible creating OpenGL context and host window.

Creating OpenGL context
As discussed earlier, OpenGL is a drawing library that requires a context to draw upon. 
Creating OpenGL context in windows OS is not a trivial task. It's mainly because opengl32.lib supplied by windows OS supports OpenGL specification 1.1. 
The display card providers such as NVidia or intel actually implement the latest and greatest OpenGL specification, including additional functionality and supply it as OpenGL Installable Client Driver or ICD.

Following lists the steps of modern OpenGL context  creation
  1. Create a dummy window with CS_OWNDC style.
  2. Create OpenGL context  as per OpenGL 1.1 specification
  3. Load the OpenGL extensions using wglGetProcAddress API. This will setup and forward any future OpenGL API calls to OpenGL ICD from the vendor
  4. Once the extensions are loaded the the OpenGL context and dummy window should be discarded  because the pixel format  of the OpenGL specification 1.1  and 3.3 are different and cannot be changed once set.
  5. Create a new window that will render 3d Graphics with CS_OWNDC style.. 
  6. Create OpenGL context compatible with OpenGL specification 3.3


OGLAppWindow implements creating OpenGL context and the hosting window. It's located in  VOGLLib\Scene\OGLAppWindow.h

BaseScene Implements rendering, resizing, mouse and keyboard events. It's located in VOGLLib\Scene\BaseScene .h. All the scene classes should derive from BaseScene class.

Init
When the scene is created Init method is called. Note that the Init method should be overridden by all scene classes derived from  BaseScene class. Internally it calls basescene's Init method to create the hosting window and the OpenGL context.

Rendering
The scene will be rendered when WM_PAINT  message is received. The OnPaint method captures it and internally calls DrawScene to render the scene using OpenGL APIs. Note that the DrawScene method should be overridden by all scene classes derived from  BaseScene class.

Mouse/Keyboard input support
Keyboard and Mouse inputs are used for various visual operations such as panning, rotation, zoom in/out etc. BaseScene class captures' keyboard and mouse inputs and passes it to the scene's  Keyboard and mouse input handler for further processing when it's assigned. The scene's   Keyboard and mouse input handler is  implemented in BaseCameraInputHandler class. The BaseCameraInputHandler  itself can be overridden for specialization. For example, SimpleCameraInputHandler class

The following table shows Keyboard and mouse input events handled.

BaseScene class

BaseCameraInputHandler  class 

OnKeyDown

OnKey

OnMouseDown

OnMouseBtnDown

OnMouseMove

OnMouseMove

OnMouseWheel

updateFOV


Resizing 
When the window is resized, WM_SIZE event is raised. OnSize method in BaseScene class captures' this event. This method resizes the viewport, passes the input to BaseCameraInputHandler  for aspect ratio  calculations and repaints the scene.

Cleanup
When the scene is destroyed Cleanup method is called. Note that the Cleanup() should be overridden by all scene classes derived from  BaseScene class.

In the next post we will discuss creation of  Creating OpenGL Context, Rendering and Mouse/Keyboard input support.