1. Trang chủ
  2. » Công Nghệ Thông Tin

3D Graphics with OpenGL ES and M3G- P20 ppt

10 191 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 168,09 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

In this approach, the vertex properties are placed in arrays, which are then passed to OpenGL using the following calls: void glColorPointerGLint size, GLenum type, GLsizei stride, GLvoi

Trang 1

8.1.1 PRIMITIVE TYPES

OpenGL ES 1.0 supports the geometric primitives shown in Figure 3.3: points, lines, and

triangles OpenGL ES 1.1 amends this list with point sprites

Points

The point is the simplest OpenGL primitive, and it requires only one vertex Its primary

property is its size, which is set by the function

void glPointSize{fx}(type size).

The point size corresponds to its diameter (the total width), defined in pixels, and it

defaults to 1 Points can be drawn either with or without antialiasing (enabled and

dis-abled with GL_POINT_SMOOTH) With antialiasing off, the points are drawn as squares

and the point size is rounded to the closest integer With antialiasing enabled, the points

are drawn as circles, and the alpha values of the pixels on the boundary are affected by

how much the point covers those pixels

Even though points can be drawn quite efficiently, in practice many graphics engines

are optimized for rendering of triangles This may mean that non-antialiased points are

drawn as two triangles, and the maximum point size for smooth points may be just one

pixel Similar optimizations may be used for line drawing

Point sprites and size attenuation

OpenGL ES 1.1 provides features for points that are especially useful for particle effects:

point sprites, point size arrays, and point size attenuation Many natural phenomena such

as rain, smoke, or fire, can be modeled by replicating several small pictures representing

raindrops, puffs of smoke, or individual flames The idea is that a set of points describes

the positions of point sprites, and their appearance comes from the current texture map

Section 9.2.8 describes how to apply a texture to points

When points are defined by an array, in OpenGL ES 1.0 they all have the same size, defined

by glPointSize{fx} In OpenGL ES 1.1 it is possible to give each point its own size

(see Section 8.1.2), and the point sizes may be attenuated by the distance between each

point and the camera The derived point size comes from the formula:

derived size = impl clamp



user clamp



size

 1

a + bd + cd2



(8.1)

where d is the eye-coordinate distance from the camera, the attenuated point size is

affec-ted by the distance attenuation coefficients a, b, c, it is clamped by user-specified min-max

Trang 2

range of GL_POINT_SIZE_MIN and GL_POINT_SIZE_MAX, and finally clamped to implementation-dependent point size range If multisampling is disabled, this is the size used for rasterizing the point With multisampling, the point size is clamped to have a minimum threshold, and the alpha value of the point is modulated by

alpha fade=



derived size threshold

2

The point attenuation components are set using

void glPointParameter{fx}(GLenum pname, T param) void glPointParameter{fx}v(GLenum pname, T * params)

where pname GL_POINT_SIZE_MIN and GL_POINT_SIZE_MAX are used to

change the clamping values for the point size calculation GL_POINT_DISTANCE_ ATTENUATIONis used to pass in params an array containing the distance attenuation coefficients a, b, and c, in that order GL_POINT_FADE_THRESHOLD_SIZE specifies

the point alpha fade threshold

Keeping the attenuation components in their default values (1, 0, 0) in practice disables point size attenuation

Point sprites are enabled by calling glEnable with the token GL_POINT_SPRITE_ OES When the global point sprite mode is enabled and the texture environment for the given texture unit is set to GL_COORD_REPLACE_OES (see Section 9.2.8), all points submitted for drawing are handled as point sprites A point sprite can be thought of as

a textured quad whose center lies at the transformed screen-space position of the vertex representing the point and whose screen dimensions are equivalent to the derived size of the point

Here is a simple code that draws a32 × 32 point sprite We use a single point size, but we could have varied it using glPointSizePointerOES

glPointSize( 32 );

glEnable( GL_POINT_SPRITE_OES );

glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE ); glDrawArrays( GL_POINTS, 0, 1 );

The entry point definition for glTexEnv is

void glTexEnv{ifx}(GLenum target, GLenum pname,T param), and its other uses for specifying how texture mapping is done are described in Section 9.2.5 and Section 9.2.7

Pitfall: Point clipping in OpenGL ES works so that if the transformed vertex of the point

is outside the view frustum, the whole primitive is considered to be outside the frustum

Trang 3

and is thus discarded This way a very simple clipping formula can be applied already

at the geometry stage to cull away the point geometry As a side effect, points or point

sprites wider than one pixel vanish before all of the pixels of the primitive move outside

of the view frustum If this is a problem the application can set the viewport to be larger

than the display and set the scissor to match the size of the display

Although this should work as specified in the API, in practice most implementations

of OpenGL ES in the market have some issues with either the point clipping when the

viewport has been extended, or with point sprites in general

Lines

There are three ways for defining a set of lines in OpenGL ES The first is a collection of

separate lines, with a line segment connecting the first and the second vertices, then the

third and the fourth, and so on The second type is a line strip, which simply connects

each vertex in a list to the next one with a line segment The third type is the line loop,

which closes a line strip by adding a segment between the last and first vertex

The line width, in pixels, can be set with

void glLineWidth{fx}(GLfloatwidth),

and the lines can be drawn either with or without antialiasing (enabled and disabled with

GL_LINE_SMOOTH)

The desktop OpenGL also supports stippling, that is, dotting and dashing the lines.

Since this can be emulated by texture mapping the lines, stippling is not supported in

OpenGL ES

Polygons

The only Polygon type supported by OpenGL ES is a triangle Desktop OpenGL also

sup-ports quadrilaterals, n-sided polygons, and screen-aligned rectangles, but these were left

out of OpenGL ES for the reasons described in Section 3.1.1

There are three methods for defining triangles in OpenGL ES The first way is as a

collection of separate triangles, where the first three vertices of a vertex array form the

first triangle, the next three form the second triangle, and so forth The second way is

a triangle strip There the first three vertices create a triangle, and after that, every new

vertex creates a new triangle by connecting to the two previous vertices The third way is

a triangle fan Again, the first triangle is made of the first three vertices After that, every

new vertex creates a new triangle using the new vertex, the previous vertex, and the first

vertex Thus the triangles create a fan around the first vertex

Trang 4

8.1.2 SPECIFYING VERTEX DATA

The original model for specifying vertex data in OpenGL used the glBegin - glEnd model For example, a triangle strip of two triangles, with two red and two green vertices, could be specified by

/* glBegin - glEnd NOT SUPPORTED BY OpenGL ES!! */

glColor4f ( 1.0f, 0.0f, 0.0f, 1.0f );

glVertex3f( 0.0f, 1.0f, 0.0f );

glVertex3f( 0.0f, 0.0f, 0.0f );

glColor4f ( 0.0f, 1.0f, 0.0f, 1.0f );

glVertex3f( 1.0f, 1.0f, 0.0f );

glVertex3f( 1.0f, 0.0f, 0.0f );

glEnd();

The function glBegin indicates the primitive type The current values of vertex proper-ties such as color, the normal vector, and texture coordinates are specified in an arbitrary order A call to glVertex specifies the vertex location and completes the vertex defi-nition using the current property values This approach creates a very complicated state machine, and requires a large number of function calls to render the geometry, slowing

graphics hardware down Display lists are a way to deal with this issue by collecting all the

GL calls and their arguments into a list which can be cached by the graphics engine, and later drawn using a single function call

Desktop OpenGL 1.1 introduced vertex arrays, which greatly simplified specification of

the vertex data, and made both the glBegin - glEnd model and the display lists largely redundant In this approach, the vertex properties are placed in arrays, which are then passed to OpenGL using the following calls:

void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid * pointer) void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid * pointer) void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid * pointer) void glNormalPointer(GLenum type, GLsizei stride, GLvoid * pointer)

void glPointSizePointerOES(GLenum type, GLsizei stride, GLvoid * pointer)

All of the functions above have similar syntax The parameter size describes the dimen-sionality of the data, e.g., size = 2 for glVertexPointer indicates that the x and y coordinates are specified, while z is left to the default value of 0 Note that for

glNormalPointerand glPointSizePointerOES the size parameter is omitted,

as normals always have three components and points only one The type parameter is used

to denote the basic type for storing the array data See Table 8.1 for the allowed

combi-nations of size and type for each array Also note that glPointSizePointerOES is

only supported in OpenGL ES 1.1

The stride parameter gives the distance in bytes between consecutive array elements Finally, the pointer parameter points to the actual vertex attribute data.

Trang 5

T a b l e 8.1: Vertex array sizes (values per vertex) and data types.

Length  8 bytes

Offset:

X coordinate

short (16-bit)

Y coordinate short (16-bit)

Z coordinate short (16-bit)

s texture coordinate char (8-bit)

t texture coordinate char (8-bit)

F i g u r e 8.1:Example of packed vertex array data.

The stride can be used to skip data if the vertex array is in an interleaved format

Figure 8.1 shows an example of packed vertex data that stores vertex coordinates and

texture coordinates in an interleaved format The vertex pointer in this case would point

to the beginning of the array and have a stride value of 8 (equaling the size of the packed

vertex) The texture coordinate pointer in this case would point to the beginning of the

array plus 6 bytes, and the stride value would be 8 bytes

Specifying a stride of zero always matches the stride that would be used for tightly packed

vertex data For example, if the vertex array has three GL_SHORT coordinates and a stride

of zero, the implementation interprets the actual stride as being 6 bytes

Performance tip: Depending on the implementation, the vertex data format may have

a great impact on performance For example, the amount of bandwidth required for

transmitting the geometry data over the system buses depends directly on the type used

to specify the vertex data Also, especially for pure software-based implementations of

OpenGL ES on mobile devices that often lack floating-point units, using floating-point

vertex data may force the implementation to fall into a much slower version of the

trans-formation and lighting pipeline Even with the integer data types, using the more

com-pact data types gives the implementation more freedom to optimize performance Often

GL_SHORTis enough for almost any kind of vertex data in 3D

Trang 6

The arrays have to be explicitly enabled (or disabled) using

void glEnableClientState(GLenum cap) void glDisableClientState(GLenum cap)

where the cap parameter is one of

GL_COLOR_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY, GL_VERTEX_ARRAY, or GL_POINT_SIZE_ARRAY_OES.

OpenGL ES 1.0 supports the multitexturing API but is not required to provide more than one texturing unit, while OpenGL ES 1.1 guarantees the availability of at least two textur-ing units

void glClientActiveTexture(GLenumtexture)

is used to select which of texture units is affected by glTexCoordPointer, glEnable ClientState(GL_TEXTURE_COORD_ARRAY), and glDisableClientState

(GL_TEXTURE_COORD_ARRAY) calls The parameter texture defines the new active

texture unit (GL_TEXTURE0, GL_TEXTURE1, etc.)

Default values

OpenGL ES allows a default value to be set for normals, colors, and texture coordinates, and then the corresponding vertex array does not need to be specified If one of the arrays has not been enabled with glEnableClientState, these default values are used instead The following calls are used to define the default values:

void glNormal3{fx}(Tnx,Tny,Tnz)

void glColor4{fx ub}(Tred,Tgreen,Tblue,Talpha)

void glMultiTexCoord4{fx}(GLenumtarget,Ts,Tt,Tr,Tq)

The target is GL_TEXTUREi, where 0 ≤ i < the value of GL_MAX_TEXTURE_UNITS

which is an implementation-dependent value

8.1.3 DRAWING THE PRIMITIVES

Once the vertex data has been specified, there are two functions that can be used to draw the resulting shapes The function

void glDrawArrays(GLenummode,GLintfirst,GLsizeicount)

Trang 7

is used to draw consecutive primitives starting from the first index in the vertex array The

parameter mode defines the type of the primitives to be drawn: GL_POINTS, GL_LINES,

GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, or

GL_TRIANGLE_FAN The count determines how many vertices are submitted for

rendering

glDrawArraysis typically used in cases where triangles are represented with strips

that are organized directly in the correct order The second drawing function uses a list of

indices to the vertex array to define the primitives:

void glDrawElements(GLenummode,GLsizecount,

GLenumtype,const GLvoid *indices)

The parameter mode is the same as in glDrawArrays type defines the type of

the data that is stored in the array indices and can be either GL_UNSIGNED_BYTE

or GL_UNSIGNED_SHORT count determines the number of indices to process See

Section 6.4 for further discussion about the benefits of indexed rendering, such as

better use of vertex caches

The following example code renders red triangles using both of these methods

static const GLbyte vertices1[8*2] = { 0,0, 0,0, — 20,20, 20,20,

— 20,40, 20,40, — 20,60, 20,60 };

static const GLbyte vertices2[7*2] = { 0,100, 100,0, 0, — 100,

— 100,0, 0,50, 45,20,

— 45,20 };

glEnableClientState( GL_VERTEX_ARRAY );

glColor4ub( 255, 0, 0, 255 );

glVertexPointer( 2, GL_BYTE, 0, vertices1 );

/* skip vertex 0, draw five triangles */

glDrawArrays( GL_TRIANGLE_STRIP, 1, 7 );

glVertexPointer( 2, GL_BYTE, 0, vertices2 );

/* draw three triangles, using the first seven vertices */

glDrawElements( GL_TRIANGLES, 9, GL_UNSIGNED_SHORT, indices );

8.1.4 VERTEX BUFFER OBJECTS

Since the vertex arrays are stored in user-controlled memory, and the user can change

their content between draw calls without the graphics engine being aware of the change,

the GL driver cannot cache them This results in costly data transfers between the system

memory and the graphics engine whenever draw calls are issued Vertex buffer objects,

introduced in OpenGL ES 1.1, provide a mechanism for storing the vertex arrays into

memory controlled by the graphics server and allow buffer data updates only via explicit

function calls A driver may then optimize the vertex buffer usage by storing that data in

an optimized memory layout, or by converting the values into a type that executes faster

on the hardware

Trang 8

A buffer object is created with a call to

void glBindBuffer(GLenumtarget,GLuintbuffer)

where target is GL_ARRAY_BUFFER and buffer is a handle to the buffer If buffer is an

unused handle and greater than 0, a new zero-sized memory buffer is created Otherwise

the existing buffer object becomes bound If 0 is given for buffer, the graphics engine will

behave as if there were no currently bound vertex buffer object

A list of existing buffer objects and their resources are deleted with

void glDeleteBuffers(GLsizein,const GLuint *buffers)

If any of the buffer objects being deleted are bound as active vertex attribute pointers, the bindings are released when the function call returns

Handles to the buffers can be created by calling

void glGenBuffers(GLsizein,GLuint *buffers)

which stores n buffer object handles to an array specified by buffers and marks them as

being used The actual buffers still need to be created with glBindBuffer A side effect

of glDeleteBuffers is to make the deleted handles available again

The actual data are stored into the currently bound vertex buffer object by calling

void glBufferData(GLenumtarget,GLsizeiptrsize,const GLvoid *data,

GLenumusage)

If the buffer object already contains data, the old data is freed and replaced by the new

data For the vertex data the parameter target is set to GL_ARRAY_BUFFER, size gives the size of the data to be copied in bytes, data is a pointer to the source data, and usage

gives a hint about the intended usage for this vertex buffer object GL_STATIC_DRAW advises the driver to optimize for data staying constant across GL draw calls, while GL_DYNAMIC_DRAWindicates that the data for this buffer object are changed dynami-cally between subsequent frames or even between draw calls

void glBufferSubData(GLenumtarget,GLintptroffset,GLsizeiptrsize,const

GLvoid *data)

is used to replace some of the data in the serside store for the currently bound

ver-tex buffer object target is again GL_ARRAY_BUFFER, and offset gives an offset in bytes

to the location from which the data is to be replaced in the server-side store size gives the length of data to be replaced, and data gives the actual data to be copied to the

server-side store Note that this function cannot be used to extend the size of the server

side store If offset+size extends beyond the data buffer stored originally with a call to

glBufferData, a GL error is generated and the data will not be copied

Performance tip: At first sight, GL_DYNAMIC_DRAW does not seem to improve

on the standard vertex arrays, as the driver is assuming that the data is modi-fied often However, if the data behind the vertex buffer object is shared even for

Trang 9

two draw calls, GL_DYNAMIC_DRAW allows the driver to keep the data in the

server-side storage across those invocations, whereas a standard vertex array would have

to be sent every time GL_DYNAMIC_DRAW hints to the implementation that it should

not perform particularly costly optimizations for the data representation as it will get

replaced many times

After a vertex buffer object is set up, it can be bound to any vertex attribute array by calling

the relevant function such as glColorPointer The pointer argument now does not

contain the vertex data, but an offset to the currently bound vertex buffer object Multiple

vertex array pointers can be set up from the same vertex buffer object, e.g., packed vertex

data representations can be used the same way as with standard vertex array calls The

vertex buffer objects are disabled with glBindBuffer(GL_ARRAY_BUFFER, 0),

after which the vertex pointer calls work as described in Section 8.1.2

Array indices in buffer objects

It is also possible to store indices that are used with glDrawElements into buffer

objects by setting the target argument of calls glBindBuffer, glBufferData,

and glBufferSubData to GL_ELEMENT_ARRAY_BUFFER If the currently bound

buffer object is a GL_ELEMENT_ARRAY_BUFFER, glDrawElements takes the index

data from the buffer, and interprets the indices parameter as an offset to the buffer object

data

Example

The following example code renders some colored triangles using vertex buffer objects:

-100,0, 0,50, 45,20, -45,20 };

255,0,0,255, 255,255,255,255, 255,0,255,255, 255,255,0,255,

0,255,255,255 };

/* create handles */

GLuint handle[3];

glGenBuffers( 3, &handle[0] );

/* load the vertex data into the first VBO */

glBindBuffer( GL_ARRAY_BUFFER, handle[0] );

glBufferData( GL_ARRAY_BUFFER, sizeof(vertices),

&vertices[0], GL_STATIC_DRAW );

/* load the index data into the second VBO */

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, handle[1] );

glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices),

&indices[0], GL_STATIC_DRAW );

/* load the color data into the third VBO */

glBindBuffer( GL_ARRAY_BUFFER, handle[2] );

glBufferData( GL_ARRAY_BUFFER, sizeof(colors),

Trang 10

glEnableClientState( GL_VERTEX_ARRAY );

glEnableClientState( GL_COLOR_ARRAY );

glBindBuffer( GL_ARRAY_BUFFER, handle[0] );

glVertexPointer( 2, GL_BYTE, 0, NULL );

glBindBuffer( GL_ARRAY_BUFFER, handle[2] );

glColorPointer( 4, GL_UNSIGNED_BYTE, 0, NULL );

/* skip vertex 0, draw five triangles */

glDrawArrays( GL_TRIANGLE_STRIP, 1, 6 );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, handle[1] );

/* draw three triangles, using the first seven vertices */

glDrawElements( GL_TRIANGLES, 9, GL_UNSIGNED_SHORT, NULL );

/* Unbind all VBOs */

glBindBuffer( GL_ARRAY_BUFFER, 0 );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

8.2 VERTEX TRANSFORMATION PIPELINE

This section covers the vertex transformation pipeline, shown in Figure 8.2 First, the vertex coordinates and the vertex normals are transformed from model coordinates to

eye coordinates using the modelview matrix Lighting and user clipping are done in the eye coordinate space Next the projection matrix transforms the lit vertices into the clip

space, where the primitives formed from the vertices are clipped against the viewing frus-tum After clipping, the vertices are transformed into normalized device coordinates by

a perspective division, and the primitives are rasterized, i.e., converted into pixels The

texture matrix is also applied to texture coordinates during the rasterization to correctly sample the texture maps Finally the viewport transformation determines where and with

which depth values the rasterized fragments are stored into the frame buffer The math-ematics behind the transformation pipeline are described in Chapter 2

8.2.1 MATRICES

The matrix functions operate on the current matrix The active matrix type is selected using

void glMatrixMode(GLenummode)

Modelview

Matrix

Projection Matrix

Perspective Division

Viewport Transformation

Object

Coordinates

Clip Coordinates

Normalized Device Coordinates

Window Coordinates

Eye Coordinates

F i g u r e 8.2: The vertex transformation pipeline is parametrized by user-given modelview and projection matrices, and view-port transformation parameters 4D homogeneous coordinates are mapped from clip coordinates to normalized device

coor-dinates by a division by the fourth, w, component.

Ngày đăng: 03/07/2014, 11:20