Unity - appspot.combranko-cirovic.appspot.com/CP3830/OpenGL.notes.pdf · What is OpenGL? OpenGL is...

Post on 30-Jan-2018

268 views 0 download

Transcript of Unity - appspot.combranko-cirovic.appspot.com/CP3830/OpenGL.notes.pdf · What is OpenGL? OpenGL is...

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(); }