Upload
nguyenxuyen
View
268
Download
0
Embed Size (px)
Citation preview
CP3830Computer Graphics
OpenGL Topics
2D graphics : modelling and transformations
3D graphics : modelling and transformations
Bezier curves and surfaces
Lighting and Textures
Unity3D TopicsScenes
Game Objects
Prefabs
Lights
Cameras
Materials
Mechanim
Particle Systems
Physics
C# Scripting
Evaluation
Assignments: 60%
Project: 40%
What is OpenGL?OpenGL is Graphics API - Application Programming Interface - set of functions we can call in our programs.
It hides details about OS, Windowing System, display etc.
Fundamental difference between fixed and programmable pipeline.
Fixed Pipeline
CPU GPU
VRAM
FixedFunctionality
RAM
Fixed Pipeline
Model Matrix
Projection Matrix
Scale / Translate / Rotate
Parallel / Perspective
Viewport Matrix
Model
Map 3D objects to 2D screen
View Matrix
Position camera
Fixed PipelineModel: glutWireCube (1.0);
Model transformation: glScalef (1.0, 2.0, 1.0);
View transformation: gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
Projection matrix: glMatrixMode (GL_PROJECTION);
Viewport transformation: glViewport (0, 0, (GLsizei) w, (GLsizei) h);
Programmable Pipeline
CPU GPU
VRAM
ProgrammableFunctionality
RAM
Programmable PipelineVertex
Processor
Fragment Processor
Programmable
OutputMerging
Model
Rasterizer
Programmable
Programmable Pipeline
Introduced in OpenGL 2.0
Advantages: faster, more realistic graphics
Disadvantages: You’ll find our shortly
OpenGL 1.0 HierararchyGL library lowest level: vertices, matrix computations etc. e.g glVertex3f(0.0, 1.0, 0.0);
GLU (Utility) library helper functions for shapes, transformations etc. e.g gluCylinder(q, b, t, h, sl, st);
GLUT (Utility Toolkit) library highest level: window and interface management. e.g. glutInitWindowSize(640, 480);
OpenGL API fixed
Specify the position of a “camera”
Specify geometry and appearance of objects
Specify materials and lights (optional)
Given OpenGL’s API, we need to:
OpenGL will compute and render the resulting image.
OpenGL Function Format
glVertex3f(x,y,z);
belongs toGL library
functionname
number of arguments
type
Xcode and OpenGLStart Xcode, new project, OS X Application, Command LineTool :
In options, name project Hello and set type to C :
Xcode and OpenGL
Select Project, in Build Settings set target to 10.8
Xcode and OpenGL
Select Target, Build Phases, Link Binary with Libraries, and add OpenGL.framework and GLUT.framework.
Our first example will simply present black square on white background.
Xcode and OpenGL
Hello
main() function
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(480, 480); glutInitWindowPosition(100, 100); glutCreateWindow("Hello"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
#include <GLUT/glut.h>
void init(void); void display(void);
init() functionvoid init(void) { glMatrixMode(GL_PROJECTION); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); }
glMatrixMode - specifies which matrix is the current matrix. Matrix representation of a vertex:
OpenGL uses homogeneous coordinates, we’ll talk about it later.
GL_PROJECTION
Computer monitor is 2D surface and we need to transform 3D scene into 2D image.GL_PROJECTION matrix is used for this transformation.
glOrtho functionArguments define coordinates of the clipping plane ( left, right, bottom, top, near, far ).
glOrtho describes a transformation that produces a parallel projection.
display() functionvoid display(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 0.0); glBegin(GL_POLYGON); glVertex2f(0.25, 0.25); glVertex2f(0.75, 0.25); glVertex2f(0.75, 0.75); glVertex2f(0.25, 0.75); glEnd();
glFlush(); }
Compile and Run
On Mac, in Xcode, hit run and you are done.
On Linux you’ll have to install FreeGlut/MESA libraries and write Makefile
On Windows - it’s doable, but how, I have no idea.
Shaders businessThe next example uses OpenGL 3.2, courtesy of Tom Dalling (http://www.tomdalling.com)
Well, for this you’ll need third party libraries GLEW, GLFW and GLM. Why?
Because almost all the API functionality is gone. So, you’ll either have to write your own libraries or find them somewhere?!
GLEWThe OpenGL Extension Wrangler (GLEW) is what we will be using to give us access to the OpenGL 3.2 API functions.
Unfortunately, accessing OpenGL functions isn't as simple as #include <GL/gl.h>.
In modern OpenGL, the API functions are determined at run time, not compile time.
GLFW
GLFW will allow us to create a window, and receive mouse and keyboard input in a cross-platform way.
OpenGL does not handle window creation or input, so this must be done somewhere else.
GLMOpenGL Mathematics (GLM) is a mathematicslibrary that handles vectors and matrices, amongst other things.
Older versions of OpenGL provided functions like glRotate, glTranslate and glScale.
In modern OpenGL, the previously mentioned functions do not exist, and we must do all of the math ourselves.
Shaders
Shaders are “little programs”, made from GLSL code, that run on the GPU instead of the CPU.
They are written in OpenGL Shading Language (GLSL), which looks like C or C++.
Vertex Shader
The Vertex Shader is the programmable Shader stage in the rendering pipeline that handles the processing of individual vertices.
Vertex shaders are fed Vertex Attribute data, as specified from a vertex array object by a drawing command.
Vertex ShaderA
B
C
vertex-shader.txt
#version 150
in vec3 vert;
void main() { gl_Position = vec4(vert, 1); }
Triangle AssemblyA
B
C
RasterizationA
B
C
Fragment Shader
The main purpose of a fragment shader is to calculate the color of each pixel that is drawn.
A “fragment” is basically a pixel, so you can think of fragment shaders as “pixel shaders”.
Fragment ShaderA
B
C
fragment-shader.txt
#version 150
out vec4 finalColor;
void main() {
finalColor = vec4(1.0, 1.0, 1.0, 1.0); }
VBOs and VAOsSince shaders run on the GPU and the rest of the C++ code runs on the CPU, we need a way of sending data from the CPU to the GPU.
This is where we need Vertex Buffer Objects (VBOs) and Vertex Array Objects (VAOs).
VBOs and VAOs are used to take data from yourC++ program and send it through to the shaders for rendering.
Vertex Buffer ObjectVBO is used to move data, in our case three vertices, from RAM to VRAM.
glGenBuffers(1, &gVBO); glBindBuffer(GL_ARRAY_BUFFER, gVBO); GLfloat vertexData[] = { 0.0f, 0.8f, 0.0f, -0.8f,-0.8f, 0.0f, 0.8f,-0.8f, 0.0f, };
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
Vertex Array ObjectVAOs are the link between the VBOs and the shader variables.
VAOs describe what type of data is contained within a VBO, and which shader variables the data should be sent to.glEnableVertexAttribArray(gProgram->attrib("vert"));
glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
AppMain - Initialize GLFW
The glfwSetErrorCallback(OnError) line tells GLFW to call the OnError function whenever an error occurs.
glfwSetErrorCallback(OnError);
if(!glfwInit()) throw std::runtime_error("glfwInit failed");
Create WindowglfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); gWindow = glfwCreateWindow((int)SCREEN_SIZE.x, (int)SCREEN_SIZE.y, "OpenGL Tutorial", NULL, NULL);
if(!gWindow) throw std::runtime_error("glfwCreateWindow failed. Can your hardware handle OpenGL 3.2?”);
glfwMakeContextCurrent(gWindow);
Initialize GLEW
This step is required in order to access OpenGL APIs.
glewExperimental = GL_TRUE; if(glewInit() != GLEW_OK) throw std::runtime_error("glewInit failed");
if(!GLEW_VERSION_3_2) throw std::runtime_error("OpenGL 3.2 API is not available.");
See if OpenGL 3.2 is available.
LoadShaders()
Here we compile and link a vertex shader and a fragment shader using the tdogl::Shader and tdogl::Program classes provided.
std::vector<tdogl::Shader> shaders; shaders.push_back(tdogl::Shader::shaderFromFile( ResourcePath(“vertex-shader.txt"), GL_VERTEX_SHADER));
shaders.push_back(tdogl::Shader::shaderFromFile( ResourcePath(“fragment-shader.txt"), GL_FRAGMENT_SHADER));
gProgram = new tdogl::Program(shaders);
LoadTriangle()
Used to create Vertex Buffer and Vertex Array Objects.
These two variables are global.
GLuint gVAO = 0; GLuint gVBO = 0;
Render()At this point the shaders, VBO, and VAO are ready for use. All we have to do now is draw them inside the Render function.
First we clear the screen so that it is completely black:
glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT);
Render()
Next we tell OpenGL that we want to start using our shaders and our VAO:
glUseProgram(gProgram->object()); glBindVertexArray(gVAO);
Render()At last, we can draw that ever-elusive triangle:
glDrawArrays(GL_TRIANGLES, 0, 3);
This call to glDrawArrays says that we want to draw triangles, starting at vertex zero, and ending after three vertices have been sent to the shader.
The vertices will be pulled out of the VBO and sent to the vertex shader. Each pixel within the triangle will be sent to the fragment shader.
Render()The drawing is finished now, so we unbind the shaders and the VAO just to be safe:
glBindVertexArray(0); glUseProgram(0);
The last thing that needs to be done before we can see the triangle is to swap the frame buffers:
glfwSwapBuffers(gWindow);
Enjoying shaders?
Lots of code for a single triangle. Not counting all the supporting libraries and resources.
For the rest of OpenGL overview, I’ll stick with deprecated functionality to introduce some concepts that we’ll need in Unity.
Transformation
There are three fundamental transformations in OpenGL - Translation, Scaling and Rotation.
Translation
1 2 3 4 5 6 7 8
23456
87
1
Translation is done by vector addition.
Example: Given a triangle with vertex vectors( 2, 2 ), ( 4, 6 ), ( 6, 2 ) and displacement vector T = ( 1, 1 ), the resultant vector set is ( 3, 3 ), ( 5, 7 ) and ( 7, 3 ).
Scaling
1 2 3 4 5 6 7 8
23456
87
1
Scaling is done by vector - scalar multiplication.
Example: Given a triangle with vertex vectors ( 2, 2 ), ( 4, 6 ), ( 6, 2 ) and scalar constant S = 0.5, the resultant vector set is ( 1, 1 ), ( 2, 3 ) and ( 3, 1 ).
Rotation
1 2 3 4 5 6 7 8
23456
87
1
Rotation is accomplished by vector multiplication.
Example: Given a line segment with vertex vectors ( 0, 0 ), ( 4, 0 ), and rotation angle 90 degrees, the resultant vector set is ( 0, 0 ), ( 0, 4 ).
Recall the three types of transformations:
Translation V’ = V + T
Scaling V’ = S・T
Rotation V’ = R・T
How to use matrix multiplication for all transformations?
Homogeneous coordinates
And the answer is: homogenous coordinates
Homogeneous coordinates add an extra coordinate to a point, i.e., point ( x, y ) is represented as( x, y, W )
Two homogeneous coordinates represent the same point if they are multiple of each other. ( 1, 2, 1 ) and ( 2, 4, 2 ) represent the same point.
If we set W to be 1, then the homogenized point would be ( x / W, y / W, 1 )
Homogeneous coordinates
Homogeneous coordinatesNow, translation can be performed with matrix multiplication:
where:
Homogeneous coordinatesTransformations for scaling and rotation remain the same:
Scaling
where:
Homogeneous coordinatesRotation
where:
OpenGL Transformations
glTranslatef(GLfloat x, GLfloat y, GLfloat z);
glScalef(GLfloat x, GLfloat y, GLfloat z);
glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
OpenGL has special functions for modelling transformations:
Order of TransformationsWhen using OpenGL transformation functions, they are applied in reversed order.
For example, if we had: glTranslatef(1.0, 1.0, 0.0); glScalef(0.5, 0.5, 0.0); glRotatef(90.0, 0.0, 0.0, 1.0); square();
Then rotation is applied first to square, than scaling and finally translation.
3D ModellingSo far, we have been using orthogonal projection only. For 3D realistic scenes, first of all, we need perspective.
Perspective
In OpenGL perspective is defined as:gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble znear, GLdouble zfar);
fovy - specifies field of view angle, in degrees, in the y direction
aspect - specifies the aspect ratio that determines the field of view in the x direction ( width / height )
znear - distance from the viewer to the near clipping plane
zfar - distance from the viewer to the far clipping plane
Perspective
CameraSo far, we haven’t explicitly defined the position of the camera. In 3D-modelling we have to do that.
CameraIn OpenGL camera is defined as: gluLookAt(GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble lookatX, GLdouble lookatY, GLdouble lookatZ, GLdouble upX, GLdouble upY, GLdouble upZ,);
Camera
eyeX,eyeY,eyeZ - specify the position of the eye point.
lookatX,lookatY,lookatZ - specify the position of the reference ( “look at” ) point.
upX,upY,upZ - specify the direction of the “up” vector, typically ( 0, 1, 0 ).
3D Objects
The following examples demonstrate built-in 3D primitives such as cube, sphere cone, etc. both wireframe and solid.
Functions main(), init() and display() are identical, except for the actual 3D construct in display, just before flush.
Cube
glutWireCube(GLdouble size);glutSolidCube(GLdouble size);;
Argument is cube side’s length.
Sphere
glutWireSphere( GLdouble radius, GLint nslices, GLint nstacks);
where nslices and nstacks are subdivisions / bands around z-axis ( longitude / latitude ).
ConeglutWireCone( GLdouble base, GLdouble height, GLint nslices, GLint nstacks);
where base is the radius of the base, nslices and nstacks are subdivisions / bands around z-axis.
Teapot
glutWireTeapot( GLdouble size);
where size is the relative size of the teapot.
Torus
glutWireTorus( GLdouble inRadius, GLdouble outRadius, GLint nslices, GLint nstacks);
where in/outRadius are inner / outer radii, nslices and nstacks are subdivisions / bands around z-axis.
Tetrahedron
glutWireTetrahedron();
renders a tetrahedron ( 4-sided ) with a radius of √3.
Dodecahedron
glutWireDodecahedron();
renders a tetrahedron (12-sided) with a radius of √3.
CylinderGLUquadricObj *qobj;qobj = gluNewQuadric();gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder(qobj, GLdouble baseRad, GLdouble topRad, GLdouble height, GLdouble nslices, GLdouble nstacks);
where base/topRad are base / top radii, nslices and nstacks are subdivisions / bands around z-axis.
3D TransformationsAll of the transformations we have seen have similar representations in 3 dimensions: translation, scaling and rotation. Example:
Spheres.c - header
#include <GL/glut.h> #include <unistd.h>
static GLfloat alpha = 0.0;
void init(void); void display(void); void rotate(void);
Spheres.c - mainint main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(640, 320); glutInitWindowPosition(100,100); glutCreateWindow("Spheres"); init(); glutDisplayFunc(display); glutIdleFunc(rotate); glutMainLoop(); return 0; }
glutIdleFunc(*func)- continuously called when events are not received.
Spheres.c - init
void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); gluPerspective(45, 1, 1, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(2.3, 1.3, 2, 0, 0.25, 0, 0, 1, 0); }
Spheres.c - displayvoid display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3d(1, 0, 0); glBegin(GL_LINE_STRIP); glVertex3i(0, 0, 0); glVertex3i(1, 0, 0); glEnd(); glBegin(GL_LINE_STRIP); glVertex3i(0, 0, 0); glVertex3i(0, 1, 0); glEnd(); glBegin(GL_LINE_STRIP); glVertex3i(0, 0, 0); glVertex3i(0, 0, 1); glEnd();
Spheres.c - display glColor3d(1, 1, 0); glPushMatrix(); glRotatef(alpha, 0, 1, 0); glTranslatef(1.0, 0.0, 0.0); glutWireSphere(0.25, 20, 20); glRotatef(alpha, 0, 1, 0); glTranslatef(0.5, 0.0, 0.0); glutWireSphere(0.125, 20, 20); glPopMatrix(); glutSwapBuffers(); }
Spheres.c - rotate
void rotate(void) { alpha = alpha + 1.0; if(alpha > 360.0) alpha = 1.0; usleep(5000); glutPostRedisplay(); }
“Realistic” scenesLet’s switch from Wire to Solid model:
Realistic? For “realism” we need lights and materials.
LightFrom a physical perspective, a surface can either emit light by self emission ( e.g. sun )
reflect light from other sources that illuminate it ( e.g. moon )
Types of LightAmbient - rays come from and scatter into all directions
Diffuse - rays come from one direction, scatter into all directions
Specular - rays come from one direction, scatter into one direction
Effect
Diffuse
Specular
Ambient
Lighting in OpenGL
Create and position one or more light sources glLightfv(GLenum light, GLenum pname, const GLfloat param);
light is specified by symbolic name GL_LIGHT0.At least 8 lights are supported ( GL_LIGHT0 - GL_LIGHT8 )
pname defines properties
param specifies the set of parameters for properties
glLightfv(GLenum light, GLenum pname, const GLfloat param);
Lighting in OpenGL
PropertiesParameter Default value Meaning
GL_AMBIENT ( 0.0, 0.0, 0.0, 1.0 ) ambient light intensity
GL_DIFFUSE ( 1.0, 1.0, 1.0, 1.0 ) diffuse light intensity
GL_SPECULAR ( 1.0, 1.0, 1.0, 1.0 ) specular light intensity
GL_POSITION ( 0.0, 0.0, 1.0, 0.0 ) ( x, y, z, w ) position of the light
GL_SPOT_DIRECTION ( 0.0, 0.0, -1.0 ) ( x, y, z ) direction of the spotlight
Parameter Default value Meaning
GL_SPOT_EXPONENT 0 spotlight exponent
GL_SPOT_CUTOFF 180 spotlight cutoff angle
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat white_light[] = { 1.0, 1.0, 1.0, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
Properties
PropertiesIn order to enable lighting we need: glEnable(GL_LIGHTING) and glEnable(GL_LIGHT0)
In order to specify shading we have to define it asglShadeModel(GL_SMOOTH);
Finally we enable and set depth: glEnable(GL_DEPTH_TEST);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
Material propertiesMaterial properties are set with glMaterialfv(GLenum face, GLenum pname, const GLfloat param);
face can be GL_FRONT, GL_BACK or GL_FRONT_AND_BACK.
pname defines properties
param specifies the set of parameters for properties
Material propertiesParameter Default value Meaning
GL_AMBIENT ( 0.2, 0.2, 0.2, 1.0 ) ambient colour of material
GL_DIFFUSE ( 0.8, 0.8, 0.8, 1.0 ) diffuse colour of material
GL_SPECULAR ( 0.0, 0.0, 0.0, 1.0 ) specular colour of material
GL_EMISSION ( 0.0, 0.0, 0.0, 1.0 ) emissive colour of material
GL_SHININESS 0 specular exponent
Light.c
Light.c - header and init#include <GL/glut.h>
void init(void); void display(void);
void init(void) { glMatrixMode (GL_PROJECTION); glLoadIdentity(); glOrtho (-1.5, 1.5, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
Light.c - displayvoid display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat white_light[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
Light.c - display
glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST);
glutSolidSphere (1.0, 48, 48); glFlush (); }
Light.c - mainint main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow ("Light"); init (); glutDisplayFunc(display); glutMainLoop(); return 0; }
MoveLight.c
SolidSpheres.c
SolidRobot.c
Bezier Surface
Bezier Surface
Curve: y = f ( x ), e.g. Circle: y = √(r² - x²) 0 ≤ | x | ≤ r
Surface: z = f ( x, y ), e.g. Spherical surface: z = √(r² - x² - y² )
Explicit representation:
Implicit representation:
Surface: f ( x, y, z ) = 0, e.g. Spherical surface: x² + y² + z² - r² = 0
QuadricsA quadric surface is defined by the general quadric equation: a1x2 + a2y2 + a3z2 + a4xy + a5yz + a6xz + a7x + a8y + a9z = 0
In order to use quadrics objects we typically:
Declare quadric object and create it: GLUquadricObj *qobj = gluNewQuadric();
Quadrics
Use gluQuadricDrawStyle(qobj, GLU_LINE) to determine whether the object is rendered as wireframe or solid
Invoke rendering routine gluCylinder(), gluSphere(), gluDisk() or gluPartialDisk()
Evaluators
Provide a way to specify points on a curve or surface
Allow us to describe any polynomial splines or surfaces of any degree ( B-splines, NURBS - Non-uniform B-splines, Bezier curves and surfaces etc. )
Evaluators
CommandglMap1f(GLenum target, TYPE u1, TYPE u2, GLint offset, GLint order, const TYPE *points);defines one-dimensional evaluator.
EvaluatorsGLenum target specifies what the control point represents. For example, GL_MAP1_VERTEX_3 specifies that x, y and z coordinates will be provided.
TYPE u1, TYPE u2 indicate the range of variable u, typically ( 0, 1 ) in the parametric form of the curve C[u] = [ X( u ) Y( u ) Z( u )]
GLint offset is an offset value between the beginning of one control point and the next.
GLint order is the degree of the polynomial plus one and should agree with the number of points
const TYPE *points is a pointer to the first coordinate of the first control point
Example:glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
Evaluators
EvaluatorsIn order to enable evaluator, we write glEnable(GL_MAP1_VERTEX_3)assuming target was GL_MAP1_VERTEX_3
In display(void), we finally render curve using glEvalCoord1f((GLfloat) u) where u is the domain coordinate previously defined in glMap1f
2D EvaluatorsSimilar to one dimension, except that all commands take two parameters, u and v, respectively.
Define evaluator(s) with glMap2{fd}()
Enable evaluator(s) with glEnable()
Invoke evaluator(s) by calling glEvalCoord2d() or with glMapGrid2() and glEvalMesh2()
2D EvaluatorsCommand
glMap2f(GLenum target, TYPE u1, TYPE u2, GLint u_offset, GLint u_order, TYPE v1, TYPE v2, GLint v_offset, GLint v_order, const TYPE *points);
defines two-dimensional evaluator.
Command glEnable(GL_MAP2_VERTEX_3) enables the corresponding evaluator with x, y and z coordinates to be provided.
BezierMesh.c
BezierMesh.c - header#include <GL/glut.h>
GLfloat ctrlpts[4][4][3] = { { {-1.5, -1.5, 4.0}, {-0.5, -1.5, 2.0}, { 0.5, -1.5, -1.0}, { 1.5, -1.5, 2.0} }, { {-1.5, -0.5, 1.0}, {-0.5, -0.5, 3.0}, { 0.5, -0.5, 0.0}, { 1.5, -0.5, -1.0} }, { {-1.5, 0.5, 4.0}, {-0.5, 0.5, 0.0}, { 0.5, 0.5, 3.0}, { 1.5, 0.5, 4.0} }, { {-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0}, { 0.5, 1.5, 0.0}, { 1.5, 1.5, -1.0} } };
void init(void); void display(void);
BezierMesh.c - mainint main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(480, 480); glutInitWindowPosition(100, 100); glutCreateWindow("Bezier Mesh"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
BezierMesh.c - displayvoid display(void) { int i, j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glPushMatrix(); glRotatef(85.0, 1.0, 1.0, 1.0); for(j = 0; j <= 30; j++) { glBegin(GL_LINE_STRIP); for(i = 0; i <= 30; i++) glEvalCoord2f((GLfloat) i / 30.0, (GLfloat) j / 30.0); glEnd();
BezierMesh.c - display
glBegin(GL_LINE_STRIP); for(i = 0; i <= 30; i++) glEvalCoord2f((GLfloat) j / 30.0, (GLfloat) i / 30.0); glEnd(); }
BezierMesh.c - display glPointSize(5.0); glColor3f(1.0, 1.0, 0.0); glBegin(GL_POINTS); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { glVertex3fv(&ctrlpoints[i][j][0]); } } glEnd();
glPopMatrix(); glFlush(); }
Textures
Refers to applying images / patterns to a surface
Individual values in texture array are often called texels, defined by texture coordinates T( s, t ).
Textures
Texture map associates a texel with each point in geometric object that is itself mapped to screen coordinates for display
Linear mapping a point on texture T( s, t ) to a point p( u, v ) is defined as: u = as + bt + c and v = ds + et + f
Required stepsEnable Texture Mapping glEnable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_2D);
Create a texture object GLubyte* texture;
typically by reading a raw byte image ( pnm - portable any map format ).
Build series of pre-filtered two-dimensional texture maps of decreasing resolutions ( mipmaps ) gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLubyte *texture);
Mipmaps
Mipmaps
GLenum target - specifies the target texture. Must be GL_TEXTURE_2D
GLint internalFormat - specifies internal storage format of the texture image, typically 1
GLsizei width and GLsizei height - specify the width and height of the texture image in pixels.
MipmapsGLenum format - specifies the format of the pixel data, typically GL_RGB
GLenum type - specifies the datatype for data
GLubyte *texture - specifies the pointer to the image data in memory
Example:gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, texture);
Required steps
Create or use named texture glBindTexture(GL_TEXTURE_2D, 0);
Specify texture environment ( optional, mixing colours and texture colours e.g. )
Required steps
Setup texture parameters ( optional, bilinear filters, clamping, repeating etc. )
Specify texels ( texture coordinates ) glTexCoord2f(float s, float t);
Rotating Earth
Earth.c - header#include <GLUT/glut.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
GLfloat ambient[3]; GLfloat diffuse[3]; GLfloat specular[3]; GLfloat shininess[] = {50.0f};
GLubyte* texture;
static GLfloat alpha = 0.0;
Earth.c - header
unsigned char* readPnm(char*, int*, int*); void getTexture(void); void init(void); void display(void); void rotate(void);
Earth.c - mainint main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(480, 480); glutInitWindowPosition(100,100); glutCreateWindow("Earth"); glutDisplayFunc(display); getTexture(); glutIdleFunc(rotate); init(); glutMainLoop(); return 0; }
Earth.c - readPnmunsigned char* readPnm(char* filename, int* width, int* height) { FILE* fp; int i, w, h, d; unsigned char* image; char head[70]; fp = fopen(filename, "rb"); if (!fp) { perror(filename); return NULL; }
Earth.c - readPnm
fgets(head, 70, fp);
if (strncmp(head, "P6", 2)) { fprintf(stderr, "%s: Not a raw PNM file\n", filename); return NULL; }
Earth.c - readPnm i = 0; while(i < 3) { fgets(head, 70, fp); if (head[0] == '#') continue; if (i == 0) i += sscanf(head, "%d %d %d", &w, &h, &d); else if (i == 1) i += sscanf(head, "%d %d", &h, &d); else if (i == 2) i += sscanf(head, "%d", &d); }
Earth.c - readPnm
image = (unsigned char*)malloc (sizeof(unsigned char) * w * h * 3); fread(image, sizeof(unsigned char), w * h * 3, fp); fclose(fp); *width = w; *height = h; return image; }
Earth.c - getTexture
void getTexture(void) { GLint w, h; texture = (GLubyte*) readPnm("/Users/branko/ Desktop/Earth/Earth/earth.pnm”, &w, &h); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_RGB, GL_UNSIGNED_BYTE, texture); free(texture); }
Earth.c - initvoid init(void) { glMatrixMode(GL_PROJECTION); gluPerspective(45, 1, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(2.3, 1.3, 2, 0, 0.25, 0, 0, 1, 0); GLfloat lightIntensity[] = {3.0f, 3.0f, 3.0f, 1.0f}; GLfloat lightPosition[] = {2.0f, 6.0f, 3.0f, 0.0f};
Earth.c - init glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightIntensity); glClearColor(0.0, 0.0, 0.0, 0.0); }
Earth.c - display
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glPushMatrix(); glRotatef(alpha, 0, 1, 0);
Earth.c - display
GLUquadricObj *qObj = gluNewQuadric(); gluQuadricNormals(qObj, GLU_SMOOTH); gluQuadricTexture(qObj, GL_TRUE); glRotatef(90, 1, 0, 0); gluSphere(qObj, 1.0f, 128, 128); glPopMatrix(); glutSwapBuffers(); }
Earth.c - rotate
void rotate(void) { alpha = alpha + 1.0; if(alpha > 360.0) alpha = 1.0; usleep(25000); glutPostRedisplay(); }