Commit 1a13482e authored by Christopher Tenter's avatar Christopher Tenter

new feature: scene layer and overlay layer with RenderObjects

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@18634 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 726f01bb
......@@ -233,15 +233,25 @@ void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph
// Sort renderable objects based on their priority
// ==========================================================
const size_t numRenderObjects = getNumRenderObjects();
const size_t numRenderObjects = getNumRenderObjects(),
numOverlayObjects = getNumOverlayObjects();
// sort for priority
if (sortedObjects_.size() < numRenderObjects)
sortedObjects_.resize(numRenderObjects);
if (overlayObjects_.size() < numOverlayObjects)
overlayObjects_.resize(numOverlayObjects);
// init sorted objects array
for (size_t i = 0; i < numRenderObjects; ++i)
sortedObjects_[i] = &renderObjects_[i];
size_t sceneObjectOffset = 0, overlayObjectOffset = 0;
for (size_t i = 0; i < renderObjects_.size(); ++i)
{
if (renderObjects_[i].overlay)
overlayObjects_[overlayObjectOffset++] = &renderObjects_[i];
else
sortedObjects_[sceneObjectOffset++] = &renderObjects_[i];
}
sortRenderObjects();
......@@ -276,9 +286,9 @@ void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph
// search list of render object for objects requiring the scene depth map
bool requiresSceneDepths = false;
for (size_t i = 0; i < numRenderObjects; ++i)
for (size_t i = 0; i < renderObjects_.size(); ++i)
{
if (sortedObjects_[i]->depthMapUniformName)
if (renderObjects_[i].depthMapUniformName)
requiresSceneDepths = true;
}
......@@ -289,8 +299,56 @@ void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph
void IRenderer::finishRenderingPipeline()
void IRenderer::finishRenderingPipeline(bool _drawOverlay)
{
if (_drawOverlay)
{
const int numOverlayObj = getNumOverlayObjects();
// two-pass overlay rendering:
// 1. clear depth buffer at pixels of overlay objects
// 2. render overlay with correct depth-testing
// 1. pass: clear depth to max value at overlay footprint
for (int i = 0; i < numOverlayObj; ++i)
{
RenderObject* obj = getOverlayRenderObject(i);
if (obj->depthTest && obj->depthFunc != GL_ALWAYS)
{
float depthMax = 1.0f;
if (obj->depthFunc == GL_GREATER || obj->depthFunc == GL_GEQUAL)
depthMax = 0.0f;
// save depth setting of renderobject
Vec2f depthRange = obj->depthRange;
bool depthWrite = obj->depthWrite;
GLenum depthFunc = obj->depthFunc;
// reset depth to maximal distance by using depth range
obj->depthRange = Vec2f(depthMax, depthMax);
obj->depthWrite = true;
obj->depthFunc = GL_ALWAYS;
renderObject(obj);
// restore depth setting
obj->depthRange = depthRange;
obj->depthWrite = depthWrite;
obj->depthFunc = depthFunc;
}
}
// 2. render overlay with correct depth-testing
for (int i = 0; i < numOverlayObj; ++i)
{
RenderObject* obj = getOverlayRenderObject(i);
renderObject(obj);
}
}
glDepthMask(1);
glColorMask(1,1,1,1);
......@@ -377,7 +435,10 @@ void IRenderer::clearInputFbo( const ACG::Vec4f& clearColor )
void IRenderer::sortRenderObjects()
{
qsort(&sortedObjects_[0], getNumRenderObjects(), sizeof(ACG::RenderObject*), cmpPriority);
if (!sortedObjects_.empty())
qsort(&sortedObjects_[0], getNumRenderObjects(), sizeof(ACG::RenderObject*), cmpPriority);
if (!overlayObjects_.empty())
qsort(&overlayObjects_[0], getNumOverlayObjects(), sizeof(ACG::RenderObject*), cmpPriority);
}
......@@ -584,10 +645,11 @@ void IRenderer::drawObject(ACG::RenderObject* _obj)
void IRenderer::renderObject(ACG::RenderObject* _obj,
GLSL::Program* _prog,
bool _constRenderStates)
bool _constRenderStates,
unsigned int _shaderModifiers)
{
// select shader from cache
GLSL::Program* prog = _prog ? _prog : ACG::ShaderCache::getInstance()->getProgram(&_obj->shaderDesc);
GLSL::Program* prog = _prog ? _prog : ACG::ShaderCache::getInstance()->getProgram(&_obj->shaderDesc, _shaderModifiers);
bindObjectVBO(_obj, prog);
......@@ -633,9 +695,23 @@ void IRenderer::addLight(const LightData& _light)
int IRenderer::getNumRenderObjects() const
{
return renderObjects_.size();
int n = 0;
for (size_t i = 0; i < renderObjects_.size(); ++i)
if (!renderObjects_[i].overlay)
++n;
return n;
}
int IRenderer::getNumOverlayObjects() const
{
int n = 0;
for (size_t i = 0; i < renderObjects_.size(); ++i)
if (renderObjects_[i].overlay)
++n;
return n;
}
int IRenderer::getNumLights() const
{
......@@ -651,6 +727,14 @@ ACG::RenderObject* IRenderer::getRenderObject( int i )
return sortedObjects_[i];
}
ACG::RenderObject* IRenderer::getOverlayRenderObject( int i )
{
if (overlayObjects_.empty())
return &renderObjects_[i];
return overlayObjects_[i];
}
IRenderer::LightData* IRenderer::getLight( int i )
{
return &lights_[i];
......
......@@ -196,8 +196,10 @@ protected:
*
* Optionally render-states may not be changed, in case depth-peeling or
* similar global shader operations may require a fixed state setting.
*
* Shader modifiers can be combined and applied to this pass.
*/
virtual void renderObject(ACG::RenderObject* _obj, GLSL::Program* _prog = 0, bool _constRenderStates = false);
virtual void renderObject(ACG::RenderObject* _obj, GLSL::Program* _prog = 0, bool _constRenderStates = false, unsigned int _shaderModifiers = 0);
/** \brief Binding VBOs (First state function)
*
......@@ -246,14 +248,15 @@ protected:
protected:
/** \brief Reset OpenGL state
/** \brief Draw overlay objects and reset OpenGL state
*
* Optionally renders overlay objects.
* Resets critical OpenGL states to default to prevent crashes.
* - deactivate framebuffer
* - disable shaders
* - disable vbo
*/
virtual void finishRenderingPipeline();
virtual void finishRenderingPipeline(bool _drawOverlay = true);
/** \brief Save input Fbo configuration (fbo id + viewport)
*/
......@@ -360,15 +363,21 @@ public:
//=========================================================================
protected:
/// Get the number of collected render objects
/// Get the number of collected render objects (not including overlay objects)
int getNumRenderObjects() const;
/// Get the number of render objects in the overlay (for instance objects from coordsys are overlayed)
int getNumOverlayObjects() const;
/// Get the number of current light sources
int getNumLights() const;
/// Get render objects in the sorted list by index
/// Get render objects in the sorted list by index (not including overlay objects)
ACG::RenderObject* getRenderObject(int i);
/// Get render objects in the sorted list by index (only overlay objects)
ACG::RenderObject* getOverlayRenderObject(int i);
/// Get light by index
LightData* getLight(int i);
......@@ -407,9 +416,12 @@ protected:
std::vector<ACG::RenderObject> renderObjects_;
/// sorted list of renderobjects (sorted in rendering order)
/// sorted list of renderobjects without overlay objects (sorted in rendering order)
std::vector<ACG::RenderObject*> sortedObjects_;
/// sorted list of overlay-only renderobjects (sorted in rendering order)
std::vector<ACG::RenderObject*> overlayObjects_;
/**
* Stores fbo containing a depth map for each viewport.
* The depth map is computed in a z-prepass if at least one RenderObject makes use of the scene depth map.
......
......@@ -171,6 +171,7 @@ void RenderObject::setMaterial( const SceneGraph::Material* _mat )
RenderObject::RenderObject()
: priority(0),
overlay(false),
modelview(GLMatrixf(ACG::Vec3f(1.0,0.0,0.0),ACG::Vec3f(0.0,1.0,0.0),ACG::Vec3f(0.0,0.0,1.0))),
proj(modelview),
vertexBuffer(0), indexBuffer(0), sysmemIndexBuffer(0),
......
......@@ -119,6 +119,19 @@ struct ACGDLLEXPORT RenderObject
*/
int priority;
/** \brief Layer based rendering
*
* The renderer currently supports two layers:
* - scene layer
* - overlay layer
*
* Usually a render plugin operates on the scene layer only and
* overlayed objects are rendered on top of the result.
* For instance, meshes are rendered in the scene layer while coordsys objects are overlayed.
*
* \note default = false
*/
bool overlay;
/// Modelview transform
GLMatrixd modelview;
......
......@@ -449,6 +449,7 @@ void CoordsysNode::getRenderObjects( IRenderer* _renderer, GLState& _state, cons
ro.depthTest = true;
ro.depthWrite = true;
ro.inZPrePass = false;
ro.overlay = true;
if ( mode_ == SCREENPOS ) {
......@@ -502,33 +503,16 @@ void CoordsysNode::getRenderObjects( IRenderer* _renderer, GLState& _state, cons
// clear the depth buffer behind the coordsys
ro.priority = -4;
ro.depthRange = Vec2f(1.0f, 1.0f);
ro.depthFunc = GL_ALWAYS;
drawCoordsys(_renderer, &ro);
// regrab of transforms needed, drawCoordsys overwrites this
ro.modelview = _state.modelview();
ro.priority = -3;
ro.priority = 3;
ro.depthRange = Vec2f(0.0f, 1.0f);
ro.depthFunc = GL_LESS;
// draw coordsys
drawCoordsys(_renderer, &ro);
// set depth buffer to 0 so that nothing can paint over cordsys
ro.modelview = _state.modelview();
ro.priority = -2;
ro.depthRange = Vec2f(0.0, 0.0);
ro.depthFunc = GL_ALWAYS;
ro.glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
// Koordinatensystem zeichnen
drawCoordsys(_renderer, &ro);
// Projection reload
_state.pop_projection_matrix();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment