A VAO and the VBOs it references |
glDrawArrays(mode, start, nVertices); |
glDrawElements(mode, nVertices, vertexIndexType, vertexIndices) |
As shown in the bottom figure on the right, this function allows you to use the vertices in the VBOs in a completely arbitrary order based on the specified vertex indices.
Carefully read this glDrawElements reference page for further details, examples, and typical use cases.
makeXAxisCylinder(x1, x2, r, nPoints) { // nPoints around a cylindrical slice; must be at least 4 // since the last point on a slice must be a copy of the first. theta = 0; dTheta = 2π/(nPoints-1) // Each trip through the loop will produce two points: one at // the base of the cylinder (x=x1) and one at the top (x=x2): for (i=0 ; i<2*nPoints ; i+=2) { ny = r*cos(theta) nz = r*sin(theta) vboPts[i] = (x1, ny, nz) vboPts[i+1] = (x2, ny, nz) // ny and nz also specify the normal vector along this ruling: vboNormals[i] = vboNormals[i+1] = (0, ny, nz) theta += dTheta } // Then create the VAO and VBOs you need, filling them with the // data you just computed. }In the render method for the class containing this cylinder, you use a single glDrawArrays call to render the entire cylinder (sans end caps):
void SomeModelViewClass::render() { <Save current GLSL program in 'pgm'; establish GLSL program; establish global viewing and lighting> renderXxx(<maybe some parameters>); glUseProgram(pgm); } void SomeModelViewClass::renderXxx(<maybe some parameters>) { <do actual rendering of object, assuming all global context is established> }Both render and renderXxx are public methods. With this design, an instance of SomeModelViewClass can be created and added to the Controller in the usual way.
OR
Some other class instance can create one or more instances of this class, not add them to the Controller, and then call their renderXxx method, without calling their render method at all. When used this way, such objects are NEVER added directly to the Controller; rather their renderXxx methods are simply called directly from their "owning" ModelView subclass' render method as needed. Only the actual top-level ModelView instance is added to the Controller.
For examples, see CGLString or BasicShapeRenderer.
Note that while render is required of any concrete ModelView subclass, the implementation structure of render shown here – and in particular the use of renderXxx – is simply a design pattern that is quite useful. There is no framework-enforced interface to such a renderXxx.
For an example, review the basketball example.
Some model attributes need to be per-vertex; others are per-primitive. We are focusing on attributes related to the lighting model here, and they are most commonly done as per-primitive. Hence that will be our approach here.
We only will present those attributes needed for project 2. We will return to this topic in 3D Geometry and Attribute Modeling 102 later.