lab_all
lab_all
Lab – 01
2D Object Creation and Applying Transformations
(Basic OpenGL Programming)
Version-1.0
glColor3f(...)
Type of Arguments
Gl library
Root Command
Number of Arguments
OpenGL APIs
Primitive functions
glBegin(type);
glVertex(…);
glVertex(…);
…
glVertex(…);
glEnd();
Attribute functions
glColor3f(…);
Transformation functions
glRotate(…); glTranslate(…);
Viewing functions
gluLookAt(…);
Input functions
glutKeyboardFunc(…);
Control functions
Inquiry functions
Primitives
Primitives: Points, Lines & Polygons
Each object is specified by a set of Vertices
Primitive Types
Follow the GLUT setup file for details information about creating
an open GL project in CodeBlocks IDE.
After creating a project, there will be a default program. Run the
project and you will see some graphics objects in yout output. Don’t
need to analyze the program. Simply delete all the code from
main.cpp file.
Now let’s try to develop our first openGL simple program. What you
needs to do first is to add the following header files in the top of your
main.cpp file.
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
Here you already know about last three header files. First three are
the required header file for GL, GLU and GLUT library functions.
}
Here we create triangle polygon in its own object space like below
(0, 0) (2, 0)
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(-3, 3, -3, 3);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
triangle();
glFlush();
glutSwapBuffers();
}
Let’s introduce with the above library functions.
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) -
consists of the bitwise OR of all the buffers to be cleared. Color
buffer stores the color of each pixel of the projected scene. And depth
buffer stores the depth information of each pixel for multiple
overlapping objects. Both needs to cleared before creating new scene.
600
(400, 300)
glViewport
(400,0,400,300)
Here we can see that, if we want we can create more than one
viewport in one window, will be demonstrated later. But for now we
create a viewport equal to the original window size.
GL_MODELVIEW Matrix operations affect the modelview matrix stack. (Used to move objects
around the scene.)
GL_PROJECTION Matrix operations affect the projection matrix stack. (Used to define clipping
volume.)
GL_TEXTURE Matrix operations affect the texture matrix stack. (Manipulates texture
coordinates.)
The projection matrix stack is used store the clipping volume defined
by gluOrtho2D(-3, 3, -3, 3) function. Therefore
glMatrixMode()function selects the required matrix stack and then
glLoadIdentity()function replaces the current transformation
matrix with the identity matrix of the stack.
glutInitWindowPosition(100,100);
glutInitWindowSize(windowWidth,
windowHeight);
glutCreateWindow("Traingle-Demo");
glShadeModel( GL_SMOOTH );
glEnable( GL_DEPTH_TEST );
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Now let’s know about the new functions used here:
glutInit(&argc, argv) - This initializes the GLUT library,
passing command line parameters (this has an effect mostly on
Linux/Unix).
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB |
GLUT_DEPTH) - Initial parameters for the display. In this case, we
are specifying a RGB display (GLUT_RGB) along with double-
Till now, we are able to draw and display a particular object. Next
task is to apply some transformations on that object to place the
object in the world space in an appropriate fashion. In openGL, there
are three basic transformation functions;
1. glTranslatef(Xval,Yval,Zval) – this function forms a
translation matrix that translate (simply adds) the current
object’s x, y, z coordinate values by Xval, Yval, Zval
respectively. This matrix is multiplied with modelview matrix
stored in modelview matrix stack.
2. glScalef(Xval,Yval,Zval) – this function forms a scale
matrix that scale (simply multiply) the current object’s x, y, z
coordinate values by Xval, Yval, Zval respectively. This matrix
is multiplied with modelview matrix stored in modelview
matrix stack.
3. glRotatef(theta,Xval,Yval,Zval) – this function forms
a rotation matrix that rotate the current object’s x, y, z
coordinate values by theta degree in anti-clockwise direction
with respect to vector formed by Xval, Yval, Zval and centered
at origin. This matrix is multiplied with modelview matrix
stored in modelview matrix stack.
Now, we want to display the same triangle twice. Very simple, call
the triangle() function again just after the first one. But in output
you will see only one triangle (same as previous output). Why?
Actually the second triangle is also drawn along with first one and
they completely overlapped. But why they overlap? We did not apply
any transformations for the second triangle.
Remember, all the transformations defined before the object will
affect the object (mentioned above).
But, we don’t want to apply the transformations on the second
triangle. What could be the solution? You can push the
transformation matrices along with first triangle in the modelview
matrix stack and pop the matrix when to display using
glPushMatrix() and glPopMatrix()
like below:
glPushMatrix();
glTranslatef(1,-1,0);
glRotatef(45,0,0,1);
triangle();
glPopMatrix();
glPushMatrix();
triangle();
glPopMatrix();
Now see the output. There will be two triangles in different shape.
That is second triangle is now out of the effect of the transformations.
Here
glPushMatrix() - pushes the current matrix onto the current
matrix stack. This function is most often used to save the current
transformation matrix so that it can be restored later with a call to
glPopMatrix().
glPopMatrix() - Pops the current matrix off the matrix stack.
Now try some different transformations for the second triangle and
you will see that affects only the second one.
Now we will introduce with glut keyboard and idle functions. First,
the purpose of keyboard function is to listen a key press and perform
an action with respect to that key press. It needs to define a user
Finally, the last function for this tutorial is to apply an idle function in
your program (optional). Suppose you want to apply some
transformation continuously until you stop it. Say, we want to scale
the second triangle continuously until key press. For this we need to
add some codes in our keyboard function and define a function called
animate() like below:
case 'S':
flagScale=true;
break;
case 's':
flagScale=false;
break;
add the above codes into the switch case.
Now you need to call your animate function from the main()
function using function glutIdleFunc(animate) which is
particularly useful for continuous animation or other background
processing.
At this stage, let’s play with more than one viewports. Modify you
display function with the following code segments below:
glPushMatrix();
glViewport(400, 300 ,400 ,300);
glTranslatef(Txval,Tyval,0);
glRotatef(45,0,0,1);
triangle();
glPopMatrix();
glPushMatrix();
glViewport(0, 0 ,400,300);
glScalef(sval, sval,1);
triangle();
glPopMatrix();
Here we add specific viewport for each matrix stack omitting
the single general viewport function. In this way you can create
more than one viewport in your output window and display
specific objects in that viewport.
Y (1, 4, 1)
Index=4
(0, 0, 2)
(2, 0, 2)
Index=1
Index=2
Fig: pyramid
Today, we create our desired pyramid in little different way than we
did in 2D object creation. Here we see that the pyramid is a
combination of four triangular plane and one rectangular plane.
Creating four triangle and one rectangle requires 16 points. But here
we see that we need only five points and we will reuse that points to
create four triangular and one rectangular plane.
Therefore, at first we store our all required points (coordinate values
of point) in an array. We also store the color for the points in another
array defined in global section of our program like below:
static GLfloat v_pyramid[5][3] = {
{0.0, 0.0, 0.0}, //point index 0
{0.0, 0.0, 2.0}, //point index 1
{2.0, 0.0, 2.0}, //point index 2
{2.0, 0.0, 0.0}, //point index 3
{1.0, 4.0, 1.0} //point index 4
};
Ux = x2-x1;
Uy = y2-y1;
Uz = z2-z1;
Vx = x3-x1;
Vy = y3-y1;
Vz = z3-z1;
Nx = Uy*Vz - Uz*Vy;
Ny = Uz*Vx - Ux*Vz;
Nz = Ux*Vy - Uy*Vx;
glNormal3f(Nx,Ny,Nz);
}
void drawpyramid()
{
glBegin(GL_TRIANGLES);
for (GLint i = 0; i <4; i++) {
getNormal3p(v_pyramid[p_Indices[i][0]][0],
v_pyramid[p_Indices[i][0]][1], v_pyramid[p_Indices[i][0]][2],
v_pyramid[p_Indices[i][1]][0], v_pyramid[p_Indices[i][1]][1],
v_pyramid[p_Indices[i][1]][2], v_pyramid[p_Indices[i][2]][0],
v_pyramid[p_Indices[i][2]][1], v_pyramid[p_Indices[i][2]][2]);
glVertex3fv(&v_pyramid[p_Indices[i][0]][0]);
glVertex3fv(&v_pyramid[p_Indices[i][1]][0]);
glVertex3fv(&v_pyramid[p_Indices[i][2]][0]);
}
glBegin(GL_QUADS);
for (GLint i = 0; i <1; i++) {
getNormal3p(v_pyramid[quadIndices[i][0]][0],
v_pyramid[quadIndices[i][0]][1], v_pyramid[quadIndices[i][0]][2],
v_pyramid[quadIndices[i][1]][0], v_pyramid[quadIndices[i][1]][1],
v_pyramid[quadIndices[i][1]][2], v_pyramid[quadIndices[i][2]][0],
v_pyramid[quadIndices[i][2]][1], v_pyramid[quadIndices[i][2]][2]);
glVertex3fv(&v_pyramid[quadIndices[i][0]][0]);
glVertex3fv(&v_pyramid[quadIndices[i][1]][0]);
glVertex3fv(&v_pyramid[quadIndices[i][2]][0]);
glVertex3fv(&v_pyramid[quadIndices[i][3]][0]);
}
glEnd();
}
Here getNormal3p function is used to create normal of each plane and
normalize the created normals using glEnable(GL_NORMALIZE) in
main() function which will check and if necessary renormalize all
your surface normal. glVertex3fv is a vector function which accepts
vector as parameter shown above. Use a common color for the
pyramid by using glColor3f(1,0,0) in the display() function.
Remember, you must have to use all the other functions used in
display() and main() function in last tutorial.
glMatrixMode(GL_MODELVIEW);
glMultMatrixf(m);
}
Here, the translation matrix is stored in a one dimensional array and
each sequential 4 indices represent the corresponding columns of the
matrix. glMultMatrixf(m) function is used to multiply the translation
matrix with the modelview matrix.
Now try this ownTranslatef() function to translate your object(s).
In the OpenGL model, the light sources have an effect only when
there are surfaces that absorb and reflect light. Each surface is
assumed to be composed of a material with various properties. A
material might emit its own light (like headlights on an automobile),
it might scatter some incoming light in all directions, and it might
reflect some portion of the incoming light in a preferential direction
like a mirror or other shiny surface.
The diffuse component is the light that comes from one direction, so
it's brighter if it comes squarely down on a surface than if it barely
glances off the surface. Once it hits a surface, however, it's scattered
equally in all directions, so it appears equally bright, no matter where
the eye is located. Any light coming from a particular position or
direction probably has a diffuse component.
Now let’s try to apply material properties and light on the scene. First
we will apply material properties to our created pyramid. Lets see the
following code segment:
At this stage we need to add one or more light source in the scene.
We can add at most 8 lights simultaneously in our scene. The code
segment below adds one light in the scene.
glEnable( GL_LIGHT0);
glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv( GL_LIGHT0, GL_POSITION, light_position);
Here, first we define the four color component for light No. 0 (zero).
Then define the light position using x,y,z values and the fourth
parameter of light position, if 1.0, specifies that the light is at this
position. Otherwise, the light source is directional and all rays
are parallel. Then enable light 0 by glEnable( GL_LIGHT0) function.
Finally apply these color component on light 0 using glLightfv()
function. It also has three parameters like glMaterialfv() function, but
the first parameter is the light number to which we apply the color
component. Now use this code segment globally (in main function) in
your program. Now run the program. You will see a bright red
pyramid.
We can also add spot lights in our scene. This is very simple. We just
need to add some more properties in the light to make it a spot light.
Here, first we need to define the direction of the spot light like below.
You must have to set the direction of the spot light properly to
focus your desired object.
• In Figure 7.12, the patch determined by the corners (smin, tmin) and
(smax, tmax) corresponds to the surface patch with corners (umin,
vmin) and (umax, vmax), then the mapping is
Cube Mapping
• “Unwrap” cube and map texture over the cube.
Cylinder Mapping
• Wrap texture along outside of cylinder, not top and bottom
• This stops texture from being distorted
Cylinder Mapping
• in Figure 7.13. Points on the cylinder are given by the parametric
equations
• x = r cos(2πu)u),
• y = r sin(2πu)u),
• z = v/h,
• as u and v vary over (0,1). Hence, we can use the mapping
• s = u,
• t = v.
Two-part Mapping
• To simplify the problem of mapping from an image to an arbitrary
model, use an object we already have a map for as an intermediary!
• Texture -> Intermediate object -> Final model
• Common intermediate objects:
• Cylinder
• Cube
• Sphere
Intermediate Object to Model
• This step can be done in many ways:
• Normal from intermediate surface
• Normal from object surface
• Use center of object
Difficulties in Texture Mapping
• First, we must determine the map from texture coordinates to object
coordinates. A two-dimensional texture usually is defined over a
rectangular region in texture space. The mapping from this rectangle
to an arbitrary region in three-dimensional space may be a complex
function or may have undesirable properties. For example, if we wish
to map a rectangle to a sphere, we cannot do so without distortion of
shapes and distances.
• Second, owing to the nature of the rendering process, which works on
a pixel-by-pixel basis, we are more interested in the inverse map from
screen coordinates to texture coordinates.
Difficulties in Texture Mapping
• Third, because each pixel corresponds to a small rectangle on the
display, we are interested in mapping not points to points, but rather
areas to areas. Here again is a potential aliasing problem that we must
treat carefully if we are to avoid artifacts, such as wavy sinusoidal or
moire’ patterns.
What is aliasing?
• An on-screen pixel does not always map neatly to a texel. Particularly
severe problems in regular textures.
Aliasing
Moire Pattern
Anti-Aliasing
• Pre-calculate how the texture should look at various distances, then
use the appropriate texture at each distance. This is called
mipmapping.
Texture magnification
• a pixel in texture image ('texel') maps to an area larger than one pixel
in image
Texture minification
• a pixel in texture image('texel') maps to an area smaller than a pixel in
image:
Mipmapping
Anti-Aliasing
• Another approach: Filtering-
1. Bi Linear Filtering
2. Tri Linear Filtering
3. Anisotropic Filtering
Aliasing and Anti-aliasing
OpenGL Texture Mapping
• OpenGL’s texture maps rely on its pipeline architecture. We have seen
that there are actually two parallel pipelines: the geometric pipeline
and the pixel pipeline. For texture mapping, the pixel pipeline merges
with fragment processing after rasterization, as shown in Figure 7.16.
This architecture determines the type of texture mapping that is
supported. In particular, texture mapping is done as part of fragment
processing. Each fragment that is generated is then tested for visibility
with the z-buffer. We can think of texture mapping as a part of the
shading process, but a part that is done on a fragment-by-fragment
basis.
Texture Mapping Pipeline
OpenGL Texture Mapping
• Texture mapping requires interaction among the application program,
the vertex shader, and the fragment shader. There are three basic
steps. First, we must form a texture image and place it in texture
memory on the GPU. Second, we must assign texture coordinates to
each fragment. Finally, we must apply the texture to each fragment.
glBindTexture
• glBindTexture(GL_TEXTURE_2D,textureName);
• GL_TEXTURE_2D: Specify that it is a 2D texture
• textureName: Name of the texture
glTexImage2D
• glTexImage2D(GL_TEXTURE_2D, level, components, width, height,
border, format, type, tarray)
• GL_TEXTURE_2D: Specify that it is a 2D texture
• Level: Used for specifying levels of detail for mipmapping
• Components: Generally is 0 which means GL_RGB, Represents
components and resolution of components
• Width, Height: The size of the texture must be powers of 2
• Border Format: Specify what the data is (GL_RGB, GL_RGBA, …)
• Type: Specify data type (GL_UNSIGNED_BYTE, GL_BYTE, …)
glTexParameteri
• glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
• This function sets several texture mapping parameters. These parameters are
bound to the current texture state that can be made current with glBindTexture.
• parameters:
• P1: GLenum: The texture target for which this parameter applies. Must be one of
GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, or GL_TEXTURE_CUBE_MAP.
• P2: GLenum: The texturing parameter to set. GL_TEXTURE_MAG_FILTER Returns
the texture magnification filter value
• P3: GLfloat or GLfloat* or GLint or GLint*: Value of the parameter specified by
pname.
GL_REPEAT Instead of GL_LINEAR
GL_CLAMP
GL_NEAREST
GL_LINEAR
glTexGen
• void glTexGeni( GLenum coord, GLenum pname, GLint param);
• glTexGen selects a texture-coordinate generation function or supplies
coefficients for one of the functions. coord names one of the (s, t, r, q)
texture coordinates; it must be one of the symbols GL_S, GL_T, GL_R,
or GL_Q.
• Coord: Specifies a texture coordinate. Must be one of GL_S, GL_T,
GL_R, or GL_Q.
• Pname: Specifies the symbolic name of the texture-coordinate
generation function or function parameters. Must be
GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE, or GL_EYE_PLANE.
glTexGen
• Params: Specifies a pointer to an array of texture generation
parameters. If pname is GL_TEXTURE_GEN_MODE, then the array
must contain a single symbolic constant, one of GL_OBJECT_LINEAR,
GL_EYE_LINEAR, GL_SPHERE_MAP, GL_NORMAL_MAP, or
GL_REFLECTION_MAP. Otherwise, params holds the coefficients for
the texture-coordinate generation function specified by pname.