opengl proamming guide chapter 3——Drawing with OpenGL

the primary use of opengl is to render graphics into a framebuffer. to accomplish this, complex objects are broken up into primitives——points, lines, and triangles that when drawn at high enough density give the appearance of 2D and 3D objects.

opengl includes many functions for rendering such primitives. these functions allow u to describe the layout of primitives in memory, how many primitives to render, and what form they take, and even to render many copies of the same set of primitives with one function call. these are arguably the most important functions in opengl, as without them, u would not be able to do much but clear the screen.

opengl graphics primitives
opengl includes support for many primitive types. eventually they all get rendered as one of three types——points, lines, or triangles. line and triangle can be combined together to form strips, loops (for lines), and fans (for triangles). points, lines, and triangles are the native primitive types supported by most graphics hardware. other primitives types are supported by opengl, including patches, which are used as inputs to the tessellator and the adjacency primitives that are designed to be used as inputs to the geometry shader.

points
points are represented by a single vertex. the vertex represents a point in four-dimensional homogenous coordinates. as such, a point really has no area, and so in opengl it is really an analogue for a square region of the display (or draw buffer). when rendering points, opengl determines which pixels are covered by the point using a set of rules called rasterization rules. the rules of rasterizating a point in opengl are quite straightfoward——a sample is considered covered by a point if it falls within a square centered on the point’s location in window coordinates. the side length of the square is equal to the point’s sizze, which is fixed state (set with glPointSize()), or the value written to the gl_PointSize built-in variable in the vertex, tessellation, or geometry shader. the value written to gl_PointSize in the shader is used only if GL_PROGRAM_POINT_SIZE is enabled, otherwise it is ignored and the fixed state value set with
glPointSize() is used.

void glPointSize(GLfloat size);

sets the fixed size, in pixels, that will be used for points when GL_PROGRAM_POINT_SIZE is not enabled.

The default point size is 1.0. Thus, when points are rendered, each vertex essentially becomes a single pixel on the screen (unless it’s clipped, of course). If the point size is increased (either with glPointSize(), or by writing a value larger than 1.0 to gl_PointSize), then each point vertex may end up lighting more than one pixel. For example, if the point size is 1.2 pixels and the point’s vertex lies exactly at a pixel center, then only that pixel will be lit. However, if the point’s vertex lies exactly midway between two horizontally or vertically adjacent pixel centers, then both of those pixels will be lit (i.e., two pixels will be lit). If the point’s vertex lies at the exact midpoint between four adjacent pixels, then all four pixels will be lit—for a total of four pixels being lit for one point!

data in opengl buffers
almost everything u will ever do with opengl will involve buffers full of data. buffers in opengl are represented as buffer objects. u have already had a brief introduction to buffer objects in chapter 1. however, in this section we will dig a little deeper into the specifics of how buffer objects are used; ways to create, manage, and desctroy them; and the best parctices associated with buffer objects.

creating and allocating buffers
as with many things in opengl, buffer objects are named using GLuint values. values are reseved using the glGenBuffers() command. this function has already been described in chaper 1, but we include the prototype there again for handy reference.

void glGenBuffers(GLsizei n, GLuint *buffers);

Returns n currently unused names for buffer objects in the array buffers.

After calling glGenBuffers(), you will have an array of buffer object names in buffers, but at this time, they’re just placeholders. They’re not actually buffer objects—yet. The buffer objects themselves are not actually created until the name is first bound to one of the buffer binding points on the context. This is important because OpenGL may make decisions about the best way to allocate memory for the buffer object based on where it is bound. The buffer binding points (called targets) are described in Table 3.2.

A buffer object actually is created by binding one of the names reserved by a call to glGenBuffers() to one of the targets in Table 3.2 using glBindBuffer(). As with glGenBuffers(), glBindBuffer() was introduced in Chapter 1, but we include its prototype here again for completeness.

void glBindBuffer(GLenum target, GLuint buffer);

Binds the buffer object named buffer to the buffer-binding point as specified by target. target must be one of the OpenGL buffer-binding targets, and buffer must be a name reserved by a call to glGenBuffers(). If this the first time the name buffer has been bound, a buffer object is created with that name.

Right, so we now have a buffer object bound to one of the targets listed in Table 3.2, now what? The default state of a newly created buffer object is a buffer with no data in it. Before it can be used productively, we must put some data into it.

getting data into and out of buffers
there are many ways to get data into and out of buffers in opengl. these range from explicitly providing the data, to replacing parts of the data in a buffer object with new data, to generating the data with opengl and recoding it into the buffer object. the simplest way to get data into a buffer object is to load data into the buffer at time of allocation. this is accomplished through the use of the glBufferData() function. there is the prototype of glBufferData() again.

void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);

Allocates size bytes of storage for the buffer object bound to target. If data is non-NULL, that space is initialized with the contents of memory addressed by data. usage is provided to allow the application to supply OpenGL with a hint as to the intended usage for the data in the buffer.

initializing part of a buffer
suppose u have an array containing some vertex data, another containing some color information, and yet another containing texture coordinates or some other data. u would like to pack the data back to back into one big buffer object so that opengl can use it. the arrays may or may not be contiguous in memory, so u can not use glBufferData() to upload all of it in one go. further, if u use glBufferData() to upload, say,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值