Showing posts with label VedaLib. Show all posts
Showing posts with label VedaLib. Show all posts

Thursday, July 21, 2022

Implementation: Drawing Text and Images

Overview 
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.

Details
In this post we shall discuss drawing text using GDI+ APIs. The plan is to  draw text and Images onto a memory based bitmap which is later loaded as a texture.
A new mesh class  TextMesh is defined for loading bitmap as texture. It's used by TextImageSketcher object for loading vertex data and texture data to the vertex and fragment shaders.
TextImageSketcher uses GDIPlus to create ARGB in memory bitmap containing text to be drawn. The size of the bitmap should be multiples of 128. i.e.,  128, 256, 512 etc.
First bitmap is filled with black color and then Text is drawn using the font and color. Note the text color needs to be non black. Font can be changed by passing LOGFONT structure, Also text color can be changed by passing COLLOREF of the color.
Fragment shader is modified for blending fragments with the background.
The client needs to first Startup() GDIPlus in the beginning of the application and Shutdown()  at the end.
Instantiate TextImageSketcher object by Init() method supply unique texture id and size.
DrawText() can be called to draw text and supply font details and text color. 
DrawImage() can be called to render images.
The TextImageSketcher object can be translated, rotated etc.  just like any 3D object.

System  class diagram
TextImageSketcher derives from BaseGeometry class. It overrides mesh with an instance of TextMesh to generate 2D geometry. It also uses TextureUtil to render text and images into the texture.


TextMesh
TextMesh derives from IGeometryMesh class. It provides 2D geometry for drawing text and images. It supplies vertices and texture coordinates.





Members
NameDescription
texturemapProvides texture map.
verticesProvides 2D vertices.

Methods
NameDescription
InitThis method generates vertex data for the GPU to render the geometrical shape. This method is called if the data is sent in  non indexed mode.
It generates position and vertex data.

TextureUtil
TextureUtil implements handling textures from image files and bitmaps. It's used by multiple purposes such as rendering 3D objects or text.
Members
NameDescription
textureIDUnique texture handle returned after creating the texture.
texunitUnique texture unit. It's value should be one of the 80 values supported by the system.

Methods
NameDescription
CleanupReleases resources.
InitAssigns unique texture unit to texunit.
LoadTextTextureUsed to render text. It generates texture from GDI bitmap.
LoadTextTextureImageUsed to render text. It wraps 2D image from GDI bitmap.
LoadTextureLoads texture from an image file.
MakeActiveMakes the texture active.

TextImageSketcher
TextImageSketcher derives from BaseGeometry class. It renders text and images. The utility class TextureUtil is used for loading text and images onto the texture.



Members
NameDescription
wd
ht
Specifies the dimensions of the bitmap. 
texutlAn instance of TextureUtil. It helps with loading text and images onto the texture.

Methods
NameDescription
InitThis method overrides the base class Init method to load texture.  Generates the vertices data consisting of surface normals in non indexed mode and later sets them up in VBO buffer.  It also prepares the bitmap for rendering text and images on it. It also initializes the texutl object with texture id for loading textures.
UpdateUniformsThis method overrides the base class UpdateUniforms method. First it updates  "cameraposition" uniform. It also updates "tex" uniform to pass texture object.
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the texture object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the  texture object.
CleanupThis method overrides the base class Cleanup method. It releases the resources used by the host object.
Init()
Shutdown()
These methods are called by the client during start up and shutdown to initialize GDI Plus environment.
ClearCanvasThis method clears the bitmap for fresh renderings of text and images.
DrawtextThis method renders input text string based on the input such as font, color and string formats.
DrawimageThis method reenders the image in the file name and resizesto fir based on the clipping width and height inputs
DrawCanvasThis method loads the bitmap onto the texture.

Output







Saturday, July 16, 2022

Implementation: LightedTexCube

Overview 
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. They look as shown at the bottom. They look elongated because aspect ratio is not applied.

Details
System  class diagram
LightedTexCube derives from TexturedCube class. It overrides mesh with an instance of CubeMesh to generate geometry. 
LightedTexCube
LightedTexCube is derived from TexturedCube class. It illuminates the textured cube as per settings done in the light parameter. Utility class gLightingUtil is used for lighting related settings.

Members
NameDescription
cameraPositionSpecifies the location of the light source for diffuse and specular illumination. 
lightAn instance of LightingUtil. It contains settings for illumination.

Methods
NameDescription
InitThis method overrides the base class Init method to load texture.  Generates the vertices data consisting of surface normals in non indexed mode and later sets them up in VBO buffer.  It also passes an input to use BlinnPhong or Phong illumination and also type of light source as defined by LightSource enum.
UpdateUniformsThis method overrides the base class UpdateUniforms method. Firs t it updates  "cameraposition" uniform. Next it updates lighting related uniforms by calling Updateshader method on light. Finally it c alls base class UpdateUniforms method to send rest.
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the cube object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the cube object based on light source type.

LightingUtil
It defines illumination properties of the light source and reflection properties of the material in the light and material members.

Members
NameDescription
materialAn instance of Material sub class. It contains settings of the material property for reflection.
lightAn instance of Light sub class. It contains settings for illumination.

Methods
NameDescription
UpdateShaderUpdates the uniforms that contains copies of the information stored in light and material members.

Output
The output looks as shown below.

Thursday, July 14, 2022

Implementation: Textured Cube

Overview 
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.
It looks as shown at the bottom. It looks elongated because aspect ratio is not applied.

Details
A Texture is 2D image that can be wrapped around a 3D object like a gift wrapper. For example, resources\textures\bricks2.jpg is a 2D Texture file. 
Unlike cartesian coordinates, Texture follow UV  System as shown below.

TextureUtil Class is used for loading textures. 

Loading Texture
OpenGL supports up to 80 Textures and each with its own identifier. Loading textures is implemented in LoadTexture method in TextureUtil class.

SOIL_load_OGL_texture(filename.c_str(), SOIL_LOAD_AUTO, 0, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);

MIPMAP
Mipmapping is a technique where a high-resolution texture is downscaled and filtered so that each subsequent mip level is a quarter of the area of the previous level. This means that the texture and all of its generated mips requires no more than 1.5 times the original texture size. An example is shown below.


Inversion of Y Axis
After loading the image needs to be inverted since the V axis of the texture and Y axis of OpenGL  have opposite polarity.

Wrapping
As shown below, determines how the texture is wrapped.

Texture Filtering
Texture filtering is a method that is used to improve the texture quality in a scene. Without texture filtering, artifacts like aliasing generally look worse. Texture filtering makes textures look better and less blocky.

Applying Texture
As discussed previously, Texture coordinates are passed during rendering. The following mapping in relation to the UxV axes is used as texture coordinates for the vertices consecutively.

        //first triangle
		{  0.0,   1.0,   0.0 },
		{ -1.0,   0.0,   0.0 },
		{  0.0,  -1.0,   0.0 },
        //second triangle
		{  1.0,   0.0,   0.0 },
		{  0.0,   0.0,  -1.0 },
		{  0.0,   0.0,   1.0 },

System  class diagram
Every 3D object such as IndexedCube  derives from BaseGeometry class. It overrides mesh with an instance of CubeMesh to generate geometry. It uses a helper class texutl to help render texture.
TextureUtil
TextureUtil implements handling textures from image files and bitmaps. It's used by multiple purposes such as rendering 3D objects or text.
Members
NameDescription
textureIDUnique texture handle returned after creating the texture.
texunitUnique texture unit. It's value should be one of the 80 values supported by the system.

Methods
NameDescription
CleanupReleases resources.
InitAssigns unique texture unit to texunit.
LoadTextTextureUsed to render text. It generates texture from GDI bitmap.
LoadTextTextureImageUsed to render text. It wraps 2D image from GDI bitmap.
LoadTextureLoads texture from an image file.
MakeActiveMakes the texture active.

TexturedCube
TexturedCube is derived from BaseGeometry class. It assembles vertex data generated by mesh in VBO and EBO buffers. Later  sent to GPU using shader programs.
Members
NameDescription
filenameFile name of the image file containing the texture.
texutlTexture utility to aid rendering texture.

Methods
NameDescription
InitThis method overrides the base class Init method. It creates the mesh object. Generates the vertices and texture data in non indexed mode and later sets them up in VBO buffers of the GPU. It later loads the texture from the image file.
UpdateUniformsThis method overrides the base class UpdateUniforms method. The base class method updates the "transform" matrix uniform by calling GetTransformationMatrix method. It updates the uniform "tex" containing the texture coordinates from to the loaded texture.
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the cube object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the cube object.
CleanupReleases resources. Calls base class method and the texutl.

Output





Wednesday, July 13, 2022

Implementation: Indexed Cube with interpolated colors

Overview 
In SingleColoredCube we saw that VBOs were used to draw the single colored cube. In this post we  will discuss how to draw an IndexedCube using VBOs and EBO with interpolated colors. It looks as shown at the bottom. It looks elongated because aspect ratio is not applied.

Details
Drawing a cube with VBO requires binding VBO of 12 vertices containing position and optionally normal vector, color, Texture coordinate data. Whereas an Indexed draw requires binding VBO of 8 vertices containing position, normal vector, color, Texture coordinate data and bind an EBO containing 12 indices.

To draw a VBO cube glDrawArrays API is used where as for EBO or Indexed, glDrawElements is used. Here the EBO contains indices data.

Color interpolation means a triangle's fragment's color is computed by interpolating colors of the vertices.

System  class diagram
Every 3D object such as IndexedCube  derives from BaseGeometry class. It overrides mesh with an instance of CubeMesh to generate geometry.


IndexedCube
IndexedCube is derived from BaseGeometry class. It assembles vertex data generated by mesh in VBO and EBO buffers. Later  sent to GPU using shader programs.

Methods
NameDescription
InitThis method overrides the base class Init method. It creates the mesh object. Generates the vertices data consisting of Position and color in indexed mode. and later sets them up in VBO buffers. It also sets up Indices data in EBO buffer. Both are sent to the GPU.
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the cube object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the cube object.

Output

Tuesday, July 12, 2022

Implementation: Multi Colored Cube

Overview 
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.

Details

System  class diagram
Every 3D object such as MutiColoredCube derives from BaseGeometry class. It overrides mesh with an instance of CubeMesh to generate geometry.
MultiColoredCube
MutiColoredCube is derived from BaseGeometry class. It assembles vertex data generated by mesh in VBO buffers. Later  sent to GPU using shader programs.
Methods
NameDescription
InitThis method overrides the base class Init method. It creates the mesh object. Generates the vertices data consisting of Position and color in non indexed mode. and later sets them up in VBO buffers. 
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the cube object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the cube object.

Output


Monday, July 11, 2022

Implementation: CubeMesh and SingleColoredCube

Overview 
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 at the bottom and rotate it along the three axes. The cube looks elongated because aspect ratio is not applied. 

Details
System  class diagram
Every 3D object such as SingleCoredCube derives from BaseGeometry class. It overrides mesh with an instance of CubeMesh to generate geometry.


Cube Geometry
A cube has 8 vertices (0,1,2,3,4,5,6,7) and 6 faces (top, bottom, right, left, back, front), with each face made up of 2 triangles. Its center of the origin is at (0,0,0).
 

CubeMesh
CubeMesh class generates geometry for the cube shape. As we learnt previously, GPU expects data in the form of vertices of the triangles. Hence the cube is divided into 12 triangles. The geometry consists of geometry data for each of the three vertices of the triangle. In other words, the geometry data consists of 36 vertices.
The geometry data for each vertex consists of
  1. X, Y, Z coordinate (mandatory)
  2. Color (optional)
  3. Normal vector (optional)
  4. Texture coordinates (optional)
How this data is packaged depends on if data is sent as indexed or non indexed format.
In non indexed format, all the 4 pieces of data is packaged and sent for all the 36 vertices.
In indexed format, all the 4 pieces of data is packaged and sent for only the 8 vertices.
In addition, an array consisting of indices of the 36 vertices are also sent.
This will be more clear in the discussion below.

The CubeMesh class derives from IGeometryMeshIndexed interface.

 It overrides GenerateVerticesData() method to generate 36 vertices for the 12 triangles, 2 from each of the 6 faces as discussed above. Only Position attribute of the vertex containing X,Y, Z coordinates is stored internally as a vector. 

Members
NameDescription
clrs
Contains individual colors for the six faces. Each color is represented as RGB format with values varying from 0 to 1.
faces
Contains vertices. 3 vertices for each triangle. 2 triangles for each face.  6 faces for entire cube.
normals
Contains individual normal for the six faces. Each normal has X,Y,Z format with values varying from -1 to 1.
texturemap
Contains individual texture coordinate for the six faces. Each texture coordinate  has X,Y format with values varying from 0 to 1.
vertices
Contains 8 vertices of the cube.  Each vertex has X,Y,Z format with values varying from -1 to 1.

Methods
NameDescription
GenerateVerticesDataThis method generates vertex data for the GPU to render the geometrical shape. This method is called if the data is sent in  non indexed mode.
The parameter att specifies the 4 attributes in the form of their enums ORed together. The enums are defined in BaseGeometry class. The data is stored in the parameter vaoutil by invoking its corresponding method  to update the data. For example, for the enum POS,  AddPosition() method is called etc.
GenerateVerticesDataIndexedSame as GenerateVerticesData() except this method is called if the data is sent in indexed mode.
GenerateIndicesDataThis method is called if the data is sent in indexed mode. It sends  an array consisting of indices of the 36 vertices.
updateColorsUpdates the clrs with the array in the parameter clrs.
updateNormalsUpdates the normals with the array in the parameter normals.
updateTextureMapUpdates the texturemap with the array in the parameter texturemap.

SingleColoredCube
SingleColoredCube is derived from BaseGeometry class. It assembles vertex data generated by mesh in VBO and EBO buffers. Later  sent to GPU using shader programs.

Members
NameDescription
color
Contains the color of the cube

Methods

NameDescription
InitThis method overrides the base class Init method. It creates the mesh object. Generates the vertices data in non indexed mode and later sets them up in VBO buffers of the GPU.
UpdateUniformsThis method overrides the base class UpdateUniforms method. The base class method updates the "transform" matrix uniform by calling GetTransformationMatrix method. It updates the uniform "color" containing the value from color to the shader.
vertexShaderSourceThis method overrides the base class vertexShaderSource method. It returns the vertex shader code to render the cube object.
fragmentShaderSourceThis method overrides the base class fragmentShaderSource method. It returns the fragment shader code to render the cube object.

Output





Implementation: Pipeline

Overview
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.

The following diagram combines all the above and represents it,
Details
 Every 3D object such as cube derives from BaseGeometry class. The following describes this in details.


BaseGeometry
BaseGeometry class implements base class for all the 3D objects. All the 3D objects such as cube must derive from this class.  

Members
NameDescription
bindexed
Indexed if the data is VBO or EBO. True if EBO.
kount
Number of elements in VBO or EBO. It's populated by derived classes.
mesh
Geometry provider. Supplies the vertices and other data.
ProjectionMatrix
Contains project matrix computed based on mouse and keyboard inputs.
MM
Contains 3D angles and other info based on keyboard/Mouse inputs.
ViewMatrix
Contains view matrix computed based on mouse and keyboard inputs.
shader
Contains instances of vertex shader and fragment shaders.
vaoutil
Contains vertex data containing VBO and EBO

Methods
NameDescription
Cleanup Releases resources associated with VAO, EBO, shader programs and others. This is overridden by derived classes.
DrawCalls  OpenGL APIs such as glDrawArrays or glDrawElements are used to draw the 3D objects from VAO buffers using shaders.
InitLoads and attach shaders to program object.  This is overridden by derived classes. This is shown in the diagram below.
UpdateUniformsUpdates uniform transform containing Transformation Matrix  This is overridden by derived classes,
GetTransformationMatrixReturns transformation matrix after combining with view and model matrix.
vertexShaderSourceReturns vertex shader string. This is overridden by derived classes.
fragmentShaderSourceReturns fragment shader string. This is overridden  by derived classes.


Operations
The following describes the key operations that happens during the lifetime of a scene object.

Init
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.

Next  the shader code is attached and linked. 

DrawScene

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. 
In DrawTriangles function, to draw a VBO cube glDrawArrays API is used where as for EBO or Indexed, glDrawElements is used. Here the EBO contains indices data.



Cleanup
Releases the resources.


In the next post we will draw a single colored cube.


Sunday, July 10, 2022

Implementation: Shader programs

Overview
 
The following provide an overview of shader programs and their implementation in this tutorial.

Shaders
Shaders are small, specialized programs that run in parallel on the multiple GPU cores to calculate rendering effects, transforming input data (vertices) into output images (pixels). Primarily written in languages like GLSL, they dictate lighting, textures, and geometry, enabling real-time 3D graphics.
Shaders provide the code for certain programmable stages of the rendering pipeline.
The OpenGL rendering pipeline defines the following shader stages, with their enumerator name:
Vertex Shaders( GL_VERTEX_SHADER)
Geometry Shaders (GL_GEOMETRY_SHADER)
Fragment Shaders (GL_FRAGMENT_SHADER)

Program Object
A program object can combine multiple shader stages (built from shader objects) into a single, linked whole. A program pipeline object can combine programs that contain individual shader stages into a whole pipeline.

Uniforms
Data such as vectors, matrices can be shared across the C++ application and shaders using a uniform.
A uniform is a global Shader variable declared with the "uniform" storage qualifier. These act as parameters that the user of a shader program can pass to that program. Their values are stored in a program object.
Uniforms are so named because they do not change from one shader invocation to the next within a particular rendering call thus their value is uniform among all invocations. This makes them unlike shader stage inputs and outputs, which are often different for each invocation of a shader stage.

Details
The shader programs are written in a 'C' like GLSL programming language. They support declaring input and output parameters. They also support different data types such as int, float, vectors, matrices etc.
uniforms can be generally considered as global variables that application can send down values to the shaders.

vertex shader 
Vertex shaders are used to send vertex,color, normal and texture coordinates to the GPU. The following example demonstrates sending vertex data.  
#version
indicates GLSL language version depends on the ca[abilities of the hardware. Most new hardware support at least 3.3 or higher. It can be obtained from making the following call:
glGetString(GL_SHADING_LANGUAGE_VERSION)

in,out 
Shader programs can receive inputs in the in parameters from the application and pass values back to another shader or application in out parameters.

core 
indicates legacy features are not available.

layout (location=0) 
indicates where to access vertex data from VBO buffers. In this case the Position data is available

uniform
uniforms are used by application to share data such as transformation matrix, color etc.

main
Entry point of the shader program

gl_Position
Built in variable that stores the position of the vertex to be rendered.

Fragment shader 
Fragment shaders are similar to vertex shader. They are executed after the rasterization process. They are responsible for determining the color of the vertex. 


FragColor
is a built-in output variable. It's assigned the color of the vertex from the input parameter fcolor coming in from the vertex shader.

ShaderUtil 
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 error logs.

Members
NameDescription
program
Unique id generated by OpenGL required for linking vertex shader and fragment shader programs.
shadermap
Contains unique ids generated by OpenGL after compiling shader programs.
attmap
Contains unique ids generated by OpenGL after linking attributes with the program
unimap
Contains unique ids generated by OpenGL after linking uniforms with the program

Methods
NameDescription
Cleanup Destroys the instance of the program
CreateAndLinkProgramCompiles the programs and link it with unique id program
LoadFromFileLoads shader program from a file and compiles it. Generates unique id and stores it in shadermap
LoadFromStringLoads shader program from a string and compiles it. Generates unique id and stores it in shadermap
Use
Uses the program at program to draw.
Release
Unuses the program at program after draw.
GetAttributeLocationAdds or returns unique id for the attribute from attmap
GetUniformLocationAdds or returns unique id for the uniform from unimap