«

»

Jun 18 2013

Squeaky clean – almost

[important]TL;DR: Rendering refactored for OGL3.x clean context. Lots of bugs. Takes time. New Revision soon.[/important]

The new revision is getting harder and harder to commit the more I try to clean the code. What cleaning am I talking about? The first part of getting a clean OpenGL 3.x context to work, that cleaning.

So, where to start?

First of all, no more matrix-related stuff. I included glm.hpp, made 3 std::stack<glm::mat4> for model, view and projection, added a caching system for MV,MVP,VP and normal matrices and a matrix upload system for shaders that will be ported to UBOs in the following commits (the code is in place, but isn’t tested enough, so I’m using regular uniforms for now)

[code lang=”cpp”]
///Getting the normal matrix for the current model
void _queryMatrix(const EXTENDED_MATRIX& mode, glm::mat3& mat){
assert(mode == NORMAL_MATRIX /*|| mode == … */);
_clean();
// Normal Matrix
mat = _isUniformScaled ? glm::mat3(_MVCachedMatrix) :
glm::inverseTranspose(glm::mat3(_MVCachedMatrix));
}
[/code]

Next, I needed a clean way of representing geometry and the relationship it has with a certain program,
thus, every batch is contained within a VAO and generated only if a valid shader program was specified. If the specified shader program is not bound or for some other reason, is not valid, the draw command will silently return (well, not in debug).

The new shader + vao + new matrix system led to the implementation of a RenderInstance class that holds an Object3D, it’s transform, a flag for calling the onDraw() method and a flag for 2D rendering. The Object3D contains the geometry and material, the transform holds the model to world matrix that will become active on shader use, the preDraw is for geometry refreshing (changing vertex data or using custom shaders as opposed to the the material ones) and so on and the 2D flag will set an ortho projection for the current instance only. More features will be added as needed for this.

Rendering is thus simplified to this:

[code lang=”cpp”]

void WaterPlane::render(SceneGraphNode* const sgn){
GFX_DEVICE.renderInstance(_plane->renderInstance());
}

void Object3D::render(SceneGraphNode* const sgn){
if(!GFX_DEVICE.excludeFromStateChange(SceneNode::getType())){
_renderInstance->transform(sgn->getTransform());
}
GFX_DEVICE.renderInstance(_renderInstance);
}

[/code]

No more manual binding of VBOs or specifying ARRAY_BUFFER bindings by hand or rendering with a different shader than the one the VAO was created with (unless needed and attributes match – e.g. depthPass*.glsl and lighting*.glsl are interchangeable as far as the object is concerned). This also led to avoiding the rebind of the same VAO and shader programs.

Another cool feature was the usage of GLEW_MX and GLFW3 to allow the creation of a separate GL context in a background thread used for both texture loading and uploading to GPU and shader compiling (shaders are still read from file in the main thread to make use of GLSW’s nice caching features for already opened files). Reading small files isn’t a problem for shaders, but linking will no longer cause small lockups in rendering. All loading requests are serialized in a FIFO queue in the loader thread and glFlush is called after each load command is executed (load commands are the entire loading methods, not line by line commands.) The ResourceDecriptor was modified to allow bypassing this mechanism and loading elements in the main thread if needed:

[code lang=”cpp”]

///The threadedLoad() method generates the texture, reads data from file, creates mipmaps, sets params etc
bool glTexture::generateHWResource(const std::string& name) {
GFX_DEVICE.loadInContext(_threadedLoading ? GFX_LOADING_CONTEXT : GFX_RENDERING_CONTEXT,
DELEGATE_BIND(&glTexture::threadedLoad, this, name));
return true;
}

///_loadQueue is a boost::lockfree::spsc_queue
void GL_API::loadInContextInternal(){
glfwMakeContextCurrent(Divide::GL::_loaderWindow);
#ifdef GLEW_MX
Divide::GL::initGlew();
#endif
while(!_closeLoadingThread){
if(_loadQueue.empty()){
boost::this_thread::sleep(boost::posix_time::milliseconds(5));//<Avoid burning the CPU – Ionut
continue;
}
boost::function0<GLvoid> callback;
while(_loadQueue.pop(callback)){
callback();
glFlush();
}
}
glfwMakeContextCurrent(NULL);
}
[/code]

CEGUI was updated to 0.8.2 and FTGL was modified to allow a clean OGL3.x context.
CEGUI,FTGL and GLIM were modified to allow the usage of GLEW_MX, and FTGL was modified to allow configurable vertex position attribute location.

Another big change is the drop of Visual Studio 2008 support to improve productivity. Along with this, Divide-Sever and Divide-Networking projects were deleted from SVN and moved inside Divide Framework. Also, all of the ReCast files are moved to a separate project. The new layout is as follows:

Click for full size

New solution layout

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>