Introduction to OpenGL ES - cs491f09.files.wordpress.com file18.11.2009 · What is OpenGL ES?...

Post on 22-Apr-2019

260 views 0 download

transcript

Introduction to OpenGL ES iPhone and iPod touch Development

Fall 2009 — Lecture 18

Questions?

Announcements

• Assignment #7 being released later this evening

Today’s Topics

• OpenGL Background

• UIView Revisited

• OpenGL Basics

• Transforms

• Drawing Geometry

• Examples

OpenGL Background

What is OpenGL?

• Open Graphics Library (OpenGL) is a cross-platform C-based interface used for 2D and 3D computer graphics

• OpenGL can specify models as points, lines, or polygons

• Shading techniques can be applied to models to produce different rendering effects

• OpenGL functions send graphics commands to the underlying hardware, where they are then rendered

• This hardware is dedicated to processing graphics commands, thus it is very fast

What is OpenGL ES?

• OpenGL for Embedded Systems (OpenGL ES) is a version of OpenGL designed for mobile devices

• Leverages modern mobile graphics hardware

• OpenGL ES is a generally a simplification of OpenGL

• Implementable given the constraints of mobile hardware

• Mostly a subset of OpenGL

Versions of OpenGL ES

• OpenGL ES 1.0

• OpenGL ES 1.1

• OpenGL ES 2.0

OpenGL ES 1.0

• Based on OpenGL 1.3 specification

OpenGL ES 1.1

• Based on OpenGL 1.5 specification

• Enhances functionality of OpenGL ES 1.0

• Backwards compatible

• Implements the standard graphics pipeline with a well-defined fixed-function pipeline

• Implements a traditional lighting and rasterization model that allows various parts of the pipeline to be enabled and configured to perform specific tasks, or disabled to improve performance

OpenGL ES 2.0

• Based on OpenGL 2.0 specification

• Shares many functions in common with OpenGL ES 1.1, but removes all functions that act on the fixed-function pipeline

• Replaced with a general-purpose shader-based pipeline

• Thus, it is not backwards compatible with OpenGL ES 1.1

• Shaders allow you to create your own vertex attributes and execute custom vertex and fragment functions directly on the graphics hardware

• Allows your application to completely customize the operations applied to each each vertex and fragment

Device Support

• iPhone 3GS and 3rd generation iPod touch

• Uses more powerful PowerVR SGX GPU

• http://www.imgtec.com/PowerVR/sgx.asp

• Supports OpenGL ES 1.1 & 2.0

• All other iPhone and iPod touch devices

• Uses more modest PowerVR MBX GPU

• http://www.imgtec.com/powervr/mbx.asp

• Supports OpenGL ES 1.1

UIView Revisited(Yes, again)

UIView Revisited

• Core Animation is fundamental to the iPhone graphics subsystem

• Every UIView is backed by a Core Animation layer

• As layers update their contents, they are animated and composited by Core Animation and presented to the display

CAEAGLLayer

• To use OpenGL ES you use a UIView backed by a CAEAGLLayer object

• A CAEAGLLayer object is aware of OpenGL ES and can be used to create rendering targets that act as part of Core Animation

•When your application finishes rendering a frame, you present the contents of the CAEAGLLayer object, where they are composited with the data from other views

OpenGL Basics

OpenGL Data Types

• Enumerations

• GLenum

• Booleans

• GLboolean

• Also defines GL_TRUE & GL_FALSE

• Numerical types

• GLbyte, GLshort, GLint, GLfloat, GLubyte, GLushort, GLuint

• GLvoid

• Used to denote no arguments or return values

OpenGL Function Naming Conventions

• OpenGL functions have a very specific naming convention that they follow

• Take the following OpenGL (not ES) function for example...

• gl — means that this function is part of OpenGL

• Vertex — the “actual” name of the function

• 3 — the number of arguments

• f — the arguments are of type float

glVertex3f(GLfloat x, GLfloat y, GLfloat z);

OpenGL Function Naming Conventions

• Many functions also have a “vector” form that accepts an array of values

• For example, the following function takes an array of 3 floats...

• There are also “normal” functions that don’t deal with multiple variations like so...

glBegin(GLenum mode);glEnd();

glVertex3fv(const GLfloat * v);

OpenGL Function Naming Conventions

• b — GLbyte

• s — GLshort

• i — GLint

• f — GLfloat

• u — unsigned, used in combination with b, s or i

• v — expects an array, used in combination with a base type

Coordinate System

• The OpenGL coordinate system puts

• positive X to the right

• positive Y upwards

• positive Z out from the screen

• Note: Y here is backwards from that of Core Graphics

(x, y, z)

Perspective View

• Objects get smaller as you move away

• Parallel lines no longer appear parallel

• Lines converge as you get far away

Orthogonal View

• Objects remain the same size as you move away

• Parallel lines remain parallel

• Lines do not converge

Setting Up an Orthographic View

CGRect rect = view.bounds; glOrthof(-1.0, // Left 1.0, // Right -1.0 / (rect.size.width / rect.size.height), // Bottom 1.0 / (rect.size.width / rect.size.height), // Top 0.01, // Near 10000.0); // FarglViewport(0, 0, rect.size.width, rect.size.height);

Image & Code by Jeff LaMarche (see additional resources slide for link)

Setting Up a Perspective View

CGRect rect = view.bounds; GLfloat size = .01 * tanf(DEGREES_TO_RADIANS(45.0) / 2.0);

glFrustumf(-size, // Left size, // Right -size / (rect.size.width / rect.size.height), // Bottom size / (rect.size.width / rect.size.height), // Top .01, // Near 1000.0); // Far

Images & Code by Jeff LaMarche (see additional resources slide for link)

Transforms

Transforms

• Definition (Webster):

• The operation of changing one configuration or expression into another in accordance with a mathematical rule

Translate Rotate Scale

glTranslate

• Multiples the current matrix by the following translation matrix...

void glTranslatef (GLfloat x, GLfloat y, GLfloat z);

1 0 0 x0 1 0 y0 0 1 z0 0 0 1

glRotate

• glRotate produces a rotation of angle degrees around the vector (x, y, z)

• Multiplied by...

void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

x^2(1-c)+c xy(1-c)-zs xz(1-c)+ys 0yx(1-c)+zs y^2(1-c)+c yz(1-c)-xs 0xz(1-c)-ys yz(1-c)+xs z^2(1-c)+c 0 0 0 0 1

Where c = cos (angle), s = sin (angle), and ||(x, y, z)|| = 1 (if not, then GL will normalize this vector)

glScale

• glScale produces nonuniform scaling along the x, y, and z axes

• The three parameters indicate the desired scale factor along each of the three axes

• Multiplies by the following matrix...x 0 0 00 y 0 00 0 z 00 0 0 1

void glScalef (GLfloat x, GLfloat y, GLfloat z);

Other Matrix Functions

• Multiply the current matrix by the specified matrix...

• Load an identity matrix...

• Push/Pop useful for temporary transforms...

void glMultMatrixf (const GLfloat *m);

void glLoadIdentity (void);

void glPopMatrix (void);void glPushMatrix (void);

Drawing Geometry

OpenGL on the Desktop

• Full-blow OpenGL provides several mechanisms for drawing geometry onto the screen

• A common approach is to declare what you’re drawing via a begin, declare all points, and then call end, like so...

• In OpenGL you can choose from a lot of different geometry...

• Points, lines, triangles, quads, polygons (in several different drawing flavors)

glBegin(GL_TRIANGLES); // Drawing Using TrianglesglVertex3f( 0.0f, 1.0f, 0.0f); // TopglVertex3f(-1.0f,-1.0f, 0.0f); // Bottom LeftglVertex3f( 1.0f,-1.0f, 0.0f); // Bottom RightglEnd(); // Finished Drawing The Triangle!

Triangles

• Unlike OpenGL on the desktop, OpenGL ES only supports drawing triangle primitives

• Triangles can be specified in a number of ways...

• Triangles

• Triangle strips

• Triangle fans

• Additionally the glBegin/glEnd style is not supported

• Instead you must pre-load your vertices into an array and feed that off to OpenGL ES

GL_TRIANGLES

• Every three vertices are turned into a triangle

• If there’s an extra one or two vertices left over at the end of the array, they are discarded

6

4 5

1

2

3

GL_TRIANGLE_STRIP

• Draws a triangle using the first three vertices

• For each additional vertex, another triangle is drawn using the last two vertices and the additional new vertex

4

51

2

3

GL_TRIANGLE_FAN

• Starts by drawing a triangle using the first three vertexes

• Each vertex after that creates a new triangle using the first vertex (overall), the previous vertex and the current vertex

• The result is a fan shaped polygon

4

5

1

2 3

Winding

• Geometry in OpenGL typically doesn’t have “both sides” to it like an object in the real world would

• Geometry has a front and back face to it

• OpenGL doesn’t (usually) draw the backside of objects

• Order of vertices matters

• Top triangle is back facing as points declared in clockwise order from current view

• Bottom triangle is front facing as points declared in counter-clock order from the current view

3

1 2

1

3

2

Examples

A Note About These Examples

• The example that follow are Jeff LaMarche’s great iPhone OpenGL ES ports of NeHe Production’s OpenGL Lessons

• Links to both authors websites are provided under the additional resources section at the end of these slides

• The only notable change I made was to remove the following line in the App Delegate’s app did finish launching method..

• This was already instantiated in the NIB, doing so again was giving me issues

window = [[UIWindow alloc] initWithFrame:rect];

The Example Code

• There’s a lot of stuff that’s taken care of for you in this sample code...

• Setting up the custom UIView

• Setting up & configuring the CAEAGLLayer instance

• Setting up lifecycle events

• Providing animation hooks

• Delegating setup and draw of the scene back to the app delegate

Translating & Drawing Basic Geometry

The App Delegate’s -drawView: Method

• These lines of setup/tear-down perform the following...

• Clears the screen

• Resets/re-centers the view about the origin

• Tells OpenGL to expect arrays of vertices

• Tells OpenGL to turn off expecting arrays of vertices

glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glEnableClientState(GL_VERTEX_ARRAY);

// ...

glDisableClientState(GL_VERTEX_ARRAY);

The App Delegate’s -drawView: Method

• These lines actually tell OpenGL about the triangle’s info...

• Declares the geometry

• Move the position to place the triangle

• Tell OpenGL about the geometry

• Tell OpenGL to draw the geometry as a triangle strip

const GLfloat triVertices[] = { 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f }; !glTranslatef(-2.0f,1.0f,-6.0f);glVertexPointer(3, GL_FLOAT, 0, triVertices); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);

The App Delegate’s -drawView: Method

• These lines actually tell OpenGL about the square’s info...

• Declares the geometry

• Move the position to place the square

• Tell OpenGL about the geometry

• Tell OpenGL to draw the geometry as a triangle fan

const GLfloat quadVertices[] = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 0.0f!};

glTranslatef(4.0f, 0.0f, 0.0f);glVertexPointer(3, GL_FLOAT, 0, quadVertices);glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

The Resulting App

• The app draws the 2 pieces of geometry that we pushed down to OpenGL ES

• Translates left and draws the triangle

• Translates right and draws the square

Adding Color

The -drawView: Method

• Added code to color the square a solid color...

• Sets the “current” color

• As before, we then tell OpenGL about the geometry and tell it to draw it

glLoadIdentity();glTranslatef(2.0f,1.0f,-6.0f);glColor4f(0.5, 0.0, 0.8, 1.0); // NEWglVertexPointer(3, GL_FLOAT, 0, quadVertices);glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

The -drawView: Method

• Added code to color the triangle...

• Declares colors at each vertex

• Enables OpenGL to accept color arrays

• Tell’s OpenGL what colors to use

• Disables coloring

const GLfloat triVertexColors[] = { 1.0f, 0.0f, 0.0f, 1.0f, // Red 0.0f, 1.0f, 0.0f, 1.0f, // Green 0.0f, 0.0f, 1.0f, 1.0f // Blue};!glTranslatef(-2.0f,1.0f,-6.0f);glVertexPointer(3, GL_FLOAT, 0, triVertices); !glEnableClientState (GL_COLOR_ARRAY); // NEWglColorPointer (4, GL_FLOAT, 0, triVertexColors); // NEWglDrawArrays(GL_TRIANGLE_STRIP, 0, 3); glDisableClientState (GL_COLOR_ARRAY); // NEW

The Resulting App

• Draws the same 2 pieces of geometry that we pushed down to OpenGL ES, but colors both pieces of geometry

• Translates left, tells OpenGL what colors to use, then draws the triangle

• Translates right and draws the square

Rotating and Animating

Firing the Animation Update

• The following methods setup the -drawView code to be executed at regular intervals...

- (void)startAnimation { animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];}

- (void)stopAnimation { [animationTimer invalidate]; animationTimer = nil;}

Calculating the Current Rotation Angle

• The following code sets up to different floats which will store the current rotation

• Updates the rotation angle based on time elapsedstatic GLfloat rtri; // Angle For The Trianglestatic GLfloat rquad; // Angle For The Quad

// ...

static NSTimeInterval lastDrawTime;if (lastDrawTime) { NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;

rtri += 20.0 * timeSinceLastDraw; if (rtri > 360.0) rtri -= 360.0;! ! rquad -= 15.0 * timeSinceLastDraw; if (rquad < 0.0) rquad += 360.0;}lastDrawTime = [NSDate timeIntervalSinceReferenceDate];

Telling OpenGL About the Rotations

• Before we draw each item, we now apply the rotation matrix to adjust the orientation

• The triangle is being rotated about Y, the square about X// triangleglLoadIdentity(); glTranslatef(-2.0f,1.0f,-6.0f);glRotatef(rtri,0.0f,1.0f,0.0f); // PERFORM ROTATIONglEnableClientState(GL_VERTEX_ARRAY);glEnableClientState (GL_COLOR_ARRAY);glColorPointer (4, GL_FLOAT, 0, triVertexColors);glVertexPointer(3, GL_FLOAT, 0, triVertices); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);glDisableClientState (GL_COLOR_ARRAY);

// squareglLoadIdentity();glColor4f(0.5, 0.0, 0.8, 1.0);glTranslatef(2.0f,1.0f,-6.0f);glRotatef(rquad,1.0f,0.0f,0.0f); // PERFORM ROTATIONglVertexPointer(3, GL_FLOAT, 0, quadVertices);glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

Modified glClear

• Since we’re going to have things rotating into and away from the screen, we need to tell OpenGL to clear its depth buffer used in calculating the depth of drawn geometry...

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

The Resulting App

• Draws the same 2 colored pieces of geometry that we pushed down to OpenGL ES, but now they rotate in 3D space

• Translates left, rotates about Y, tells OpenGL what colors to use, then draws the triangle

• Translates right, rotates about X and draws the square

Geometry with Depth“Real” 3D

Declaring the Pyramid’s Points

static const GLfloat pyramidVertices[] = { 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f };

• The following code defines the pyramids 5 points in 3D space...

Declaring the Pyramid’s Faces

static const GLubyte pyramidVertexFaces[] = { 0, 1, 2, // Defines Front Face 0, 3, 2, // Defines Right Face 0, 3, 4, // Defines Back Face 0, 1, 4 // Defines Left Face };

• The following code defines the pyramids 4 sides...

Declaring the Pyramid’s Colors

static const GLubyte triVertexColors[] = { 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 255, 255 };

• The following code defines the 5 colors for each vertex to be interpolated across the face of the pyramid in 3D space...

Drawing the Pyramid

static const GLubyte triNumberOfIndices = 12;

// ...

// pyramidglLoadIdentity(); glTranslatef(-2.0f,1.0f,-6.0f);glRotatef(rtri,0.0f,1.0f,0.0f);glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState (GL_COLOR_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, pyramidVertices); glColorPointer(4, GL_UNSIGNED_BYTE, 0, triVertexColors); for(int i = 0; i < triNumberOfIndices; i += 3) { ! glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &pyramidVertexFaces[i]); }

glDisableClientState (GL_COLOR_ARRAY);

• The following code defines the cubes 8 points in 3D space...

Declaring the Cubes Points

static const GLfloat cubeVertices[] = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-1.0f, 1.0f, -1.0f,-1.0f, 1.0f, -1.0f, 1.0f,-1.0f, 1.0f, 1.0f,-1.0f, 1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f };

• The following code defines the cubes 6 sides...

Declaring the Cube’s Faces

const GLubyte cubeVertexFaces[] = { 0, 1, 5, // Half of top face 0, 5, 4, // Other half of top face

4, 6, 5, // Half of front face 4, 6, 7, // Other half of front face

0, 1, 2, // Half of back face 0, 3, 2, // Other half of back face

1, 2, 5, // Half of right face 2, 5, 6, // Other half of right face

0, 3, 4, // Half of left face 7, 4, 3, // Other half of left face

3, 6, 2, // Half of bottom face 6, 7, 3, // Other half of bottom face

};

• The following code defines the 8 colors for each vertex to be interpolated across the face of the cube in 3D space...

Declaring the Cube’s Colors

const GLubyte cubeFaceColors[] = { 0, 255, 0, 255, 255, 125, 0, 255, 255, 0, 0, 255, 255, 255, 0, 255, 0, 0, 255, 255, 255, 0, 255, 255};

Drawing the Cube

static const GLubyte cubeNumberOfIndices = 36;

// ...

// cubeglLoadIdentity();glTranslatef(2.0f,1.0f,-6.0f);glRotatef(rquad, 1.0f, 1.0f, 1.0f);!glVertexPointer(3, GL_FLOAT, 0, cubeVertices);int colorIndex = 0;for(int i = 0; i < cubeNumberOfIndices; i += 3) { glColor4ub(cubeFaceColors[colorIndex], cubeFaceColors[colorIndex+1], cubeFaceColors[colorIndex+2], cubeFaceColors[colorIndex+3]); int face = (i / 3.0); if (face%2 != 0.0) colorIndex+=4;

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &cubeVertexFaces[i]);}

The Resulting App

• Expanded to draw objects with depth and rotate around in 3D space