Showing posts with label Essentials. Show all posts
Showing posts with label Essentials. Show all posts

Monday, July 25, 2022

Primer: Understanding View space, Perspective and Orthographic Projections

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

Details
As shown in the diagram below, a 3D object in a scene starts off from object space. Model transformation places it in the world space using a model matrix.  Based on the camera position the entire world is transformed into Camera space or view space. This is called view transform. This is done using viewing matrix. It is later moved to screen space using Projection matrix.


So far in our examples, camera is located at the origin and view and projection matrixes are not computed; instead identity matrix is used.  Next we will try to move around the camera and understand different type of projections.

Model Matrix
Model Matrix is responsible for moving 3D objects  from object space to world space. The affine transformation discussed in Lesson 08 are applied.

View Matrix
When the hypothetical camera position is changed, the whole world is transformed around it using view matrix. The internals is as described below (courtesy : learnopengl.com).
 


1. Camera position
The camera position or eye at (0,0,2) is a vector in world space.

2. Camera direction vector
The  Camera direction vector is the direction at which the camera is pointing at. This is computed from the scene's origin or center in this case it's  (0,0,0). Subtracting the camera position vector from the scene's origin vector thus results in the direction vector. This must always point to +Z axis by RHS convention.
Therefore normalize((0,0,2) - (0,0,0)) = (0,0,1)

3. World up vector
The up vector (0,1,0) points to worlds Y axis. This may not be always the case.

4. Right axis vector
The right axis vector represents the positive x-axis of the camera space. This is obtained by doing a cross product on the up vector and the camera direction vector from step 2. 
Therefore cross((0,1,0) -  (0,0,1)) = (1,0,0)

5. Up axis vector
The Up axis vector points to camera's positive y-axis. It's computed by the cross product of the right and direction vector.
Therefore cross((0,0,1) - (1,0,0)) = (0,1,0)

The view matrix is computed as below from glm as below.
mat4 lookAt(vec3 const& eye, vec3 const& center, vec3 const& up)

NameDescription
eyeThe 3D coordinates defining exactly where the camera is located in world space.
centerThe 3D coordinates representing the point in the world that the camera is looking at.
up  A directional hint (usually ([0, 1, 0])) indicating which way is "up" in the world, ensuring the camera doesn't roll or tilt improperly.

Example
In the example below, the camera position or eye vector is placed in front of the cube at (0,0,5). Center is located at (0,0,0) and up vector is (0,1,0).



As mentioned earlier, the World up vector need not be always (0,1,0).
For example,  if  the camera is moved on top of the cube say (0, 5, 0), we will be looking at the  top of the cube.  The eye is (0,5,0), center is (0,0.0) and up is (1, 0, 0) not (0,1,0).



Projections
The final matrix is projection matrix. There are two types of projections
Orthographic and Perspective. The traits are as below.


The following shows another view with the view frustum. A view frustum is a rectangular box that confines the image rendered to be shown on the screen. 


The volume or the frustum is defined by the left, right, top, bottom, near and far plane values. 

perspective
The perspective projection is computed in glm as below. In Perspective projection, the frustum appears as a truncated pyramid. 
perspective(float fovy, float aspect, float zNear, float zFar)

NameDescription
fovy Field of View (FOV) or zoom factor 
aspect Aspect ratio of the viewport. i.e., width/height.
ZNear  Distance from the camera to the near plane
ZFar Distance from the camera to the far plane

Example:
perspective(45.0, 1.84, 1.0, 100.0)
The screenshot below shows the perspective projection of the colored cube rotated 20 degree pitch and 20 degree yaw.


ortho
The orthographic projection is computed in glm as below. In orthographic projection, the frustum appears as a cube. 
ortho(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)

NameDescription
xminleft of the view frustum
xmax right of the view frustum
ymintop of the view frustum
ymax bottom of the view frustum
ZMin distance from the camera to the near plane
ZMax distance from the camera to the far plane

Example:
ortho(-1.84, 1.84, -1.0, 1.0, 1.0, 100.0); 
Note that the aspect ratio is 1.84.
The screenshot below shows the orthographic  projection of the colored cube rotated 20 degree pitch and 20 degree yaw.

Unproject
Sometimes it's useful to capture x,y,z coordinates in the object space based on the mouse cursor position. UnProject() accomplishes this.  The X,Y coordinates from the mouse cursor position and Z value from the depth buffer is used to compute the window coordinates. Later this is passed to glm unProject() along with Model, View and Projection Matrix, to get the co ordinates in world space.

wstring Unproject(const mat4& ProjectionMat)

NameDescription
ProjectionMatThe current Projection matrix of the mouse coordinate.

Example:
In the below, the red dot in the cube represents mouse cursor position  
x = 353 y = 168 and depth buffer Z = 0.79


Using  Model, View, and Perspective Projection matrices, the world space coordinate is calculated as
0.22, 0.12, 0.43.


Saturday, July 23, 2022

Primer: Importing WaveFront OBJ Models

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

Details
Wavefront OBJ file is an ASCII text based image format that can be parsed to obtain geometry information such as vertices, texture coordinates and normals along with triangles for rendering. Also, material properties such as ambient, diffuse and specular colors along with texture files can also be extracted.
The usually comes with a pair files. .obj  files contain geometry information and .mtl. contain material properties. Texture files are separate.

The following lists an example.
crate.obj
# Blender v3.0.0 OBJ File: ''
# www.blender.org
mtllib crate.mtl
o crate
v 0.467223 -0.137344 -0.716128
v -0.334052 -0.667593 -0.439009
v -0.818424 0.179215 -0.219235
v -0.017149 0.709464 -0.496354
v 0.818424 -0.179215 0.219235
v 0.017149 -0.709464 0.496354
v 0.334052 0.667593 0.439009
v -0.467223 0.137344 0.716128
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.5395 -0.1586 -0.8269
vn -0.3857 -0.7709 -0.5069
vn -0.9450 0.2069 -0.2532
vn -0.0198 0.8192 -0.5731
vn 0.9450 -0.2069 0.2532
vn 0.0198 -0.8192 0.5731
vn 0.3857 0.7709 0.5069
vn -0.5395 0.1586 0.8269
usemtl _Crate1Material
s 1
f 1/1/1 2/2/2 3/3/3
f 3/3/3 4/4/4 1/1/1
f 5/5/5 6/6/6 2/7/2
f 2/7/2 1/8/1 5/5/5
f 7/9/7 8/10/8 6/11/6
f 6/11/6 5/12/5 7/9/7
f 4/13/4 3/14/3 8/15/8
f 8/15/8 7/16/7 4/13/4
f 2/17/2 6/6/6 8/15/8
f 8/15/8 3/18/3 2/17/2
f 5/5/5 1/19/1 4/20/4
f 4/20/4 7/16/7 5/5/5

The keyword mtllib represents the material library to use.
The keyword v represents x,y,z coordinates of a vertex.
The keyword vt represents u,v coordinates of a texture point.
The keyword vn represents x,y,z coordinates of a normal.
The keyword usemtl represents the material to use as described in the mtl file.
The keyword f represents three vertices of the triangle in the form of vertex/texture/normal.
For example in the above case, f 1/1/1 refers to (0.467223, -0.137344 ,-0.716128)/(1.0, 0.0)/(0.5395, -0.1586, -0.8269).

crate.mtl
# Blender MTL File: 'None'
# Material Count: 1

newmtl _Crate1Material
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2

The keyword newmtl represents a material description.
The keyword Ns represents shininess of the specular color
The keyword Ka represents ambient color

The keyword Kd represents diffuse color
The keyword Ks represents specular color
The keyword Ke represents emissive color
The keyword map_Kd represents diffuse texture file. 



Saturday, July 16, 2022

Primer:Lighting

Overview 
Lighting is an important factor to consider while rendering realistic 3D shapes.  The following discusses adapting lighting conditions while rendering 3D images.

Details
According to physics, visible light is made up of a band of different wavelengths. Each segment has a designated color that human eye can detect.


When light is shone on an object, it absorbs some wavelengths and reflects some giving out the color based on the material property of the object. 
The reflection is different based on its proximity to the light source and the angle between its position and  the light source. Therefore light calculations should factor these.

The calculations primarily considers three kinds of light sources.

Ambient
Ambient light means that light always existed in absence of a light source. Imagine a unlit room next to the street where light is coming in from a street lamp through the window bouncing off the walls onto curtains, furniture etc. It's dark, yet curtains, furnitures etc are visible albeit not clearly.
This pictorially represented as below

To calculate the amount of ambient reflection (I) on a surface,  the formula below is used.
I = Ka  ∑ Ia

Ka  is the ambient reflection coefficient that ranges from 0 to 1. Higher the value stronger is the reflection.

Ia  is global ambient intensity of the individual light source.

Example:
In this example, the Red light falls on Gray object. Here the 3rd image shows ambient lighting of the the back face of the sphere where lighting is same everywhere.


Diffused Light
Diffused light means that directional light that is reflected equally irrespective of user view point. 


The effectiveness of the reflection depends on the angle of incidence and the surface normal. In other words, the cross product of both. The lesser the value, higher is the reflection.
This pictorially represented as below. 



To calculate the amount of diffuse reflection (I) on a surface,  the formula below is used.
I = Kd Id (n.L)

Kd  is the diffuse reflection coefficient that ranges from 0 to 1. Higher the value stronger is the reflection.

Id  is the diffuse intensity of the light source.

(n.L) is the cross product of the surface normal n and light incident on the surface.

Example:
In this example, the red light falls on Gray object. Here the 3rd image represents the back face of the sphere where lighting is poor because of angle of incidence.
Specular Light
Specular light applies to smooth and polished surfaces that readily reflect light. When light hits the shiny surface it forms bright highlights.Here the reflection is targeted and is perpendicular to the angle of incidence in the opposite direction. A viewer can see only if in exactly the right position, somewhere along the path of the reflection r. 
Specular reflection from a very shiny surface produces very narrow cones of reflected light;
specular highlights on such a material are small and sharp. A duller surface will produce wider
cones of reflected light.


Specular reflection can be calculated as follows.
I = Ks  Imax(0,(v⋅r))ᵖ
Ks is the specular reflection coefficient to determine how strong or weak the specular reflection appears.
I is the brightness of the light source illuminating the surface.
is (2 (l . n) n) - l
(v⋅r) is the cross product between the observer's line of view and the direction of the reflected light.
p is known as the Phong Exponent. As p increases, the light cone becomes narrower (because r⋅e ≤ 1), the highlighted spot becomes smaller.
max(0,(v⋅r))ᵖ controls the size and sharpness of the specular highlight, making it more or less focused depending on the value of p.  The max returns 0 is returned if the v.r is negative.

Example
In this example, the White light source falls on Gray object. The 3rd image shows the specular reflection. 


Emissive Light
Some surfaces such as ovens, TV screens etc may emit light. It's independent and can be directly factored. Emissive lighting represents a self-luminous glow that is additive, meaning it is added on top of the results of ambient, diffuse, and specular lighting.

I = KeIe
Ke is emissive light value.
Ke is emissive light intensity.

The following example shows a sphere with emissive lighting.
Material
As discussed earlier materials absorb some light wavelengths and reflect back remaining. Illumination models should also consider these in the calculations of ambient, diffuse and specular. In other words, three separate material reflection color, one each for ambient, diffuse and specular should be used for realistic renderings.

Phong Lighting Model
This combines all the three models discussed above - Ambient, Diffuse,Specular and attenuation.
The combined formula combines  all the three
I = KaIa  +  KdId(n.L)KsIs(max(0,v⋅r)ᵖ)KeIe

The image below combines ambient,diffuse and specular reflections resulting in highlight and the curvature.

Blinn Phong Lighting Model
This combines all the three models discussed above - Ambient, Diffuse and Specular same as Phong lighting model except specular component is calculated using the halfway vector h.

The combined formula combines  all the three
I = Ka∑Ia + KdId(n.L) + KsIs(max(0,v⋅h)ᵖ)
h is (l+v) / |l+v|   




The image below combines ambient,diffuse and specular reflections resulting in highlight and the curvature.

These are the other light sources used to create realistic rendering.

Directional Light
Directional light refer to light sources such as sun where light reaches the objects irrespective of their location. Here the light source is assumed to be infinitely distant and intensity is same. Also the light rays are parallel to each other and are unidirectional.
In other words, Directional lights have only color and direction, not position. 


The following example displays an directional light such as tubelight.


Point Light
Point light emits light equally in all directions and also they have a position. Point lights have color and position within a scene, but no single direction.
However they suffer from attenuation where light gets waker over the distance. 
Attenuation reduces light intensity based on distance, making objects further from a light source appear dimmer. Attenuation has no impact on ambient light. Attenuation is calculated as below.

d: Distance between the light source and the point on the surface.
Kc: Constant attenuation (usually 1.0) to prevent division by zero or small numbers.
Kl: Linear attenuation (reduces intensity proportionally to distance).
Kq: Quadratic attenuation (reduces intensity proportionally to the square of the distance, simulating physical reality).

The light bulb below illustrates a point light.


Spot Light
A spotlight is a light source that radiates light in a cone shape from a single point in a specific direction, designed to simulate real-world lights like flashlights or stage spotlights. This effect is achieved through a two-cone system that defines the intensity, producing a bright center and a soft, fading edge.
Spotlights have color, position, and direction in which they emit light.


Notice that color is brightest in the center and gradually fades outwards.

In order to calculate the fading, cosine value of the directional vector of the light and the vertex under the cone is used. Naturally as angle increases the cosine value decreases.


The below spot light illustrates it.





Sunday, July 10, 2022

Primer: Graphics Pipeline

Overview
Modern OpenGL supports many different primitives  such as Points(GL_POINTS), Triangle(GL_TRIANGLE)  and Line Strip (GL_LINE_STRIP) etc. as shown below.


A scene consists of one or more 3D objects.  The shapes of these 3D objects are typically described using primitives.  For example, the 3D wire frame of a rabbit below is represented as hundreds of triangles.
These triangles are in turn are defined by their vertices. A vertex is the corner of the triangle where two edges meet, and thus every triangle is composed of three vertices. 

Note that this tutorial focuses only on 3D shapes rendered as  triangles.

Details
In OpenGL, the Graphics pipeline is responsible for rendering 3D objects. The following gives a brief overview without over burdening with the complex  details. As you get familiar, this can be revisited to gain a deeper understanding.

FrameBuffer
The output of graphics pipeline ends up in Framebuffer. Framebuffer is piece of memory within the graphics card that maps to the display. For simplicity, you can assume that it's like a bitmap covering entire viewport. Double framebuffers are used to avoid screen tearing while rendering the scene. For example, after the first frame of a scene is written by the pipeline into framebuffer, it's drawn on the screen while the framebuffer2 is filled with the second frame of the scene. Then it's swapped with the first so that  the screen now displays the second frame while third frame is written in to the framebuffer etc.

OpenGL  Graphics pipeline
OpenGL provides a multi-stage graphics pipeline that is partially programmable using a language called GLSL (OpenGL Shading Language) as shown below. Each of these programmable units are called shaders.


To kick off this chain, the C++ application supplies vertex data consisting of  vertices. 
The vertex data for each vertex maps to the following information:

Position
This is a mandatory input. It represents the X, Y, Z coordinate of the vertex.  As discussed earlier it contains double values.
Each position is represented as a vector of 3 doubles.

Color
This is an optional input. It represents RGBA color of the vertex. RGBA stands of Red Green Blue Alpha. The values are double values. The range goes from 0 to 1. 
To generate different colors such as fuchsia, violet etc, an unique different values are supplied to the RGB components.
However, the Alpha component represents transparency.  A value of 1 makes the vertex completely opaque and replaces background vertex. Similarly, a values 0 makes it completely transparent. Intermediate values makes the vertex blend with background. 
Each color is represented as a vector of 4 doubles. However in practise, only RGB values are sent. The alpha component is hardcoded in the Fragment shader.

Normal
This is an optional input. It represents the normal vector of the vertex. Normals are used in the lighting calculations. 
Just like Position, Normals are represented as X,Y,Z coordinates and hence represented as a vector of 3 doubles.

Texture
This is an optional input. It represents 2D texture coordinates of the vertex. 
Texture coordinates are represented as UV coordinates and hence represented as a vector of 2 doubles.

The vertex data is first fed to the vertex shader.

Vertex Shader
This stage is mandatory. A vertex shader is a graphics processing function used to add special effects to objects in a 3D environment by performing mathematical operations on the  vertex's data. Vertex Shaders don't actually change the type of data; they simply change the values of the data, so that a vertex emerges with a different color, different textures, or a different position in 3D space.

Tessellation Shader
This stage is optional and not available to OpenGL release 3.3.  After the vertex shader has processed each vertex’s associated data, the tessellation shader stage will continue processing those data, if it has been activated. Tessellation uses patches to describe an object’s shape, and allows relatively simple collections of patch geometry to be tessellated to increase the number of geometric primitives providing better-looking models. The tessellation shading stage can potentially use two shaders to manipulate the patch data and generate the final shape.

Geometry Shader
This stage is optional. Allows additional processing of individual geometric primitives, including creating new ones, before rasterization. This shading stage is also optional, but very powerful.

Rasterization
The primitive assembly stage organizes the vertices into their associated geometric primitives in preparation for clipping and rasterization. Clipping removes all pixels outside of the viewport.
After clipping, the updated primitives are sent to the rasterizer for fragment generation. Consider a fragment a candidate pixel, in that pixels have a home in the framebuffer, while a fragment still can be rejected and never update its associated pixel location. Processing of fragments occurs in the next two stages, fragment shading and per-fragment operations.

Fragment Shader
This stage is necessary for the practical reasons. Fragment shader determines the fragment’s final color , and potentially its depth value. Fragment shaders are very powerful as they often employ texture mapping to augment the colors provided by the vertex processing stages. A fragment shader may also terminate processing a fragment if it determines the fragment shouldn’t be drawn; this process is called fragment discard.

Pixel Operations
A fragment’s visibility is determined using depth testing (also commonly known as Z-buffering) and stencil testing. If a fragment successfully makes it through all of the enabled tests, it may
be written directly to the framebuffer, updating the color (and possibly depth value) of its pixel, or if blending is enabled, the fragment’s color will be combined with the pixel’s current color to generate a new color that is written into the framebuffer.

In the next post we will discuss the nitty gritty of rendering a cube.