I've recently taken a peek at blender's viewport rendering code. There are a few thoughts I'd like to share here and listen to opinions of course.
Right now there are a couple of OpenGL rendering modes for blender: VBO, GLSL, and Solid mode. There is quite a lot of duplicated code in there and a few improvements that could be made. In particular there are a few bugs that relate to VBO mostly to do with multiple materials and textures and not without good reason. This discussion is oriented mostly towards VBOs but can be generalized to simple OpenGL 1.1 vertex arrays. So, let's take a look at what one may do... First of all, when talking about real time display we must make a bridge between OpenGL data representation and Blender internal mesh representation. Central to the speed of drawing is the notion of indices and batches. Each vertex in a mesh is associated with an index,so we can generate a triangle by connecting vertices with indices 2,4 and 15 for example. If we are concerned with rendering time we must also minimize the calls we make to OpenGL. VBOs are excellent in this regard. The idea is to prepare an array with vertex data(called attributes) like position, normal, uv etc and a separate array containing indices to recreate the faces and send it to OpenGL with one draw call. This packet of geometry is called batch. Batches in OpenGL have a few restrictions. For instance, only one GLSL shader can be active for a given batch so multiple materials have to be separated into multiple batches or selected through conditionals in the shader. The same applies to texture images as well. Faces containing different image textures can't be rendered in the same batch(Recently the array textures extension lifted this restriction). So, to summarize the differences between OpenGL and Blender * For every OpenGL vertex in a VBO one can associate only one texture coordinate, one normal or generally only one attribute(see vertex color or tangent for bump maps). One index is associated with one vertex and its corresponding attributes. * Blender stores data per face and a few per vertex. A vertex only has one normal but it can have many UV's(at the seams for instance)and many Vertex Colors. In blender a vertex index is not enough to get all the data related a vertex. Moreover, each face in a mesh can have different texture images or materials associated with it. One batch is not enough to render a mesh with multiple textures or materials. So, in order to counter the fact that blender is face-centric and OpenGL is vertex/batch-centric, the current way blender draws is based on glDrawArrays. In order to use this OpenGL command, every triangle is written in a buffer with the proper data. Indices are not used and a lot of data is duplicated (for a vertex used in 4 polygons we send roughly 4 times the 'same' vertex data to the GPU). Now, if we were to send data through a command like glDrawElements, using indices, we could reduce the amount of data sent to the GPU and most probably viewport rendering times (GPUs use caching schemes to avoid processing the same vertices again). The requirement is that we need way to sort through the data to create a 1-1 correspondence between attributes and indices. So, the idea is to introduce a setup step that groups vertices based on islands (quite similar to the select linked tool). These can serve as batches for OpenGL and serve a lot of purposes: * Speed of drawing. Less data sent to GPU, and even further optimizations to send triangle strips instead of triangles can be made, further reducing the data sent to the GPU. * Less duplicated code. Right now there are quite a few branches in the code, each doing last-minute-setup while with good initial setup, we simply select the batches we need to render. Bugs are easier to detect. We have one area in the code for data setup, and data is already formatted for easy drawing. So, to highlight the algorithm. * First group mesh faces by materials (This already happens I think) * Group faces by textures (Ensures that multitexture drawing works correctly) * Group vertices by linked UV's * Group vertices by vertex colors To group vertices, we iterate through the faces and for every vertex that has had multiple UV's or vertex colors, we generate a new vertex and link the face with the index of the new vertex. This is standard procedure for game exporters. _______________________________________________ Bf-committers mailing list [email protected] http://lists.blender.org/mailman/listinfo/bf-committers
