Commit 5d09ad68 authored by Christopher Tenter's avatar Christopher Tenter
Browse files

nodes can now access all RenderObjects emitted by nodes in their scenegraph...

nodes can now access all RenderObjects emitted by nodes in their scenegraph subtree by attaching RenderObjectMods to the renderer
parent 7d6bbd88
......@@ -71,6 +71,8 @@
namespace ACG
{
int IRenderer::maxClipDistances_ = -1;
IRenderer::IRenderer()
: numLights_(0),
renderObjects_(0),
......@@ -307,6 +309,14 @@ void IRenderer::addRenderObject(ACG::RenderObject* _renderObject)
ACG::RenderObject* p = &renderObjects_.back();
// apply modifiers
size_t numMods = renderObjectModifiers_.size();
for (size_t i = 0; i < numMods; ++i)
{
if (renderObjectModifiers_[i])
renderObjectModifiers_[i]->apply(p);
}
if (!p->shaderDesc.numLights)
p->shaderDesc.numLights = numLights_;
......@@ -419,7 +429,10 @@ void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::D
void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _node, const ACG::SceneGraph::Material* _mat )
void IRenderer::traverseRenderableNodes( ACG::GLState* _glState,
ACG::SceneGraph::DrawModes::DrawMode _drawMode,
ACG::SceneGraph::BaseNode* _node,
const ACG::SceneGraph::Material* _mat )
{
if (_node)
{
......@@ -435,8 +448,11 @@ void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph
if (status != ACG::SceneGraph::BaseNode::HideSubtree)
{
if ( _node->status() != ACG::SceneGraph::BaseNode::HideNode )
if (_node->status() != ACG::SceneGraph::BaseNode::HideNode)
{
_node->enter(*_glState, nodeDM);
_node->attachRenderObjectModifiers(this, *_glState, nodeDM);
}
// fetch material (Node itself can be a material node, so we have to
......@@ -467,8 +483,11 @@ void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph
}
if (_node->status() != ACG::SceneGraph::BaseNode::HideNode )
if (_node->status() != ACG::SceneGraph::BaseNode::HideNode)
{
_node->leave(*_glState, nodeDM);
_node->detachRenderObjectModifiers(this, *_glState, nodeDM);
}
}
}
}
......@@ -648,6 +667,9 @@ void IRenderer::finishRenderingPipeline(bool _drawOverlay)
glBindVertexArray(0);
#endif
for (int i = 0; i < maxClipDistances_; ++i)
glDisable(GL_CLIP_DISTANCE0 + i);
glDepthMask(1);
glColorMask(1,1,1,1);
......@@ -924,6 +946,20 @@ void IRenderer::bindObjectRenderStates(ACG::RenderObject* _obj)
// ACG::GLState::shadeModel(_obj->shadeModel);
ACG::GLState::blendFunc(_obj->blendSrc, _obj->blendDest);
if (maxClipDistances_ < 0)
{
glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances_);
maxClipDistances_ = std::min(maxClipDistances_, 32); // clamp to 32 bits
}
for (int i = 0; i < maxClipDistances_; ++i)
{
if (_obj->clipDistanceMask & (1 << i))
glEnable(GL_CLIP_DISTANCE0 + i);
else
glDisable(GL_CLIP_DISTANCE0 + i);
}
}
void IRenderer::drawObject(ACG::RenderObject* _obj)
......@@ -1042,6 +1078,20 @@ void IRenderer::addLight(const LightData& _light)
}
void IRenderer::addRenderObjectModifier(RenderObjectModifier* _mod)
{
renderObjectModifiers_.push_back(_mod);
}
void IRenderer::removeRenderObjectModifier(RenderObjectModifier* _mod)
{
for (int i = int(renderObjectModifiers_.size()) - 1; i >= 0; --i)
{
if (renderObjectModifiers_[i] == _mod)
renderObjectModifiers_.erase(renderObjectModifiers_.begin() + i);
}
}
int IRenderer::getNumRenderObjects() const
{
int n = 0;
......
......@@ -133,6 +133,27 @@ public:
*/
virtual void addLight(const LightData& _light);
/** \brief Callback for the scenegraph nodes, which adds a render object modifier to the renderer via this function
*
* This function is needed whenever a scenegraph node wants to set certain rendering parameters for all its child nodes.
* A scenegraph node does not have direct access to render object created within its subtree.
* Instead, it can implement a render object modifier and attach it to the renderer.
* This modifier is applied to all render objects added to this renderer until it gets removed again.
*
* A good place to call this function is in the derived BaseNode::attachRenderObjectModifiers() function.
*
* @param _mod address of the modifier. It has to remain in memory until it gets removed from the renderer!
*/
virtual void addRenderObjectModifier(RenderObjectModifier* _mod);
/** \brief Callback for the scenegraph nodes, which removes a render object modifier from the renderer
*
* Remove a previously added modifier. RenderObjects added to the renderer afterwards will not be affected anymore.
*
* @param _mod address of the modifier.
*/
virtual void removeRenderObjectModifier(RenderObjectModifier* _mod);
//=========================================================================
// Render object collection and OpenGL setup for shader-based rendering
//=========================================================================
......@@ -465,6 +486,9 @@ protected:
/// sorted list of overlay-only renderobjects (sorted in rendering order)
std::vector<ACG::RenderObject*> overlayObjects_;
/// active render object modifiers
std::vector<ACG::RenderObjectModifier*> renderObjectModifiers_;
/**
* 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.
......@@ -505,6 +529,9 @@ protected:
/// error-detection level for checking render objects
int errorDetectionLevel_;
/// max number of clip distance outputs in a vertex shader
static int maxClipDistances_;
private:
//=========================================================================
......
......@@ -205,6 +205,8 @@ RenderObject::RenderObject()
blendSrc(GL_SRC_ALPHA), blendDest(GL_ONE_MINUS_SRC_ALPHA),
depthRange(0.0f, 1.0f),
clipDistanceMask(0),
patchDefaultInnerLevel(1.0f, 1.0f),
patchDefaultOuterLevel(1.0f, 1.0f, 1.0f, 1.0f),
......
......@@ -255,6 +255,12 @@ struct ACGDLLEXPORT RenderObject
Vec2f depthRange; //!< glDepthRange: (znear, zmax)
// enable/disable clip planes
// bit i decides whether the vertex shader output gl_ClipDistance[i] is enabled or disabled
// default: all zero (disabled)
GLuint clipDistanceMask;
// ---------------------------
// default tessellation lod, if only a tess-eval, but no tess-control shader is specified
// this is ignored otherwise
......@@ -533,7 +539,7 @@ private:
class ACGDLLEXPORT RenderObjectModifier
{
public:
RenderObjectModifier() {}
RenderObjectModifier(const std::string& _name = "") : name_(_name) {}
virtual ~RenderObjectModifier() {}
/** \brief apply the modifier
......@@ -543,6 +549,11 @@ public:
*/
virtual void apply(RenderObject* _obj) = 0;
/// Get name of the modifier
const std::string& name() const { return name_; }
private:
std::string name_;
};
......
......@@ -193,29 +193,40 @@ public:
*/
virtual void draw(GLState& /* _state */, const DrawModes::DrawMode& /* _drawMode */) {}
/** \brief Deferred draw call with shader based renderer.
*
* The renderer calls this function to collect the geometry that should be rendered from the nodes.
*
* Add any renderable geometry to the renderer via _renderer->addRenderObject()
*
* The material is fetched from the last active material node and may be used to setup Renderobjects,
* but may as well be ignored.
*
* \note You should not draw anything yourself in this function.
*
* @param _renderer The renderer which will be used. Add your geometry into this class
* @param _state The current GL State when this object is called
* @param _drawMode The active draw mode
* @param _mat Current material
*/
virtual void getRenderObjects(IRenderer* _renderer, GLState& _state , const DrawModes::DrawMode& _drawMode , const Material* _mat) {}
/** The leave function is used to restore GL states the have been changed.
This function must restore the status before enter() !
*/
virtual void leave(GLState& /* _state */, const DrawModes::DrawMode& /* _drawMode */) {}
/** This function is called when traversing the scene graph and
arriving at this node in render objects mode. It can be used to
attach modifiers to a renderer that can modify any render object parameters.
*/
virtual void attachRenderObjectModifiers(IRenderer* _renderer, GLState& /*_state */, const DrawModes::DrawMode& /*_drawMode*/) {}
/** \brief Deferred draw call with shader based renderer.
*
* The renderer calls this function to collect the geometry that should be rendered from the nodes.
*
* Add any renderable geometry to the renderer via _renderer->addRenderObject()
*
* The material is fetched from the last active material node and may be used to setup Renderobjects,
* but may as well be ignored.
*
* \note You should not draw anything yourself in this function.
*
* @param _renderer The renderer which will be used. Add your geometry into this class
* @param _state The current GL State when this object is called
* @param _drawMode The active draw mode
* @param _mat Current material
*/
virtual void getRenderObjects(IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat) {}
/** The detachRenderObjectModifiers function is used to detach modifiers from the renderer.
This function must restore the status before enter() !
*/
virtual void detachRenderObjectModifiers(IRenderer* _renderer, GLState& /* _state */, const DrawModes::DrawMode& /* _drawMode */) {}
/** This function is called when traversing the scene graph during picking
and arriving at this node. It can be used to store GL states that
will be changed in order to restore then in the leavePick()
......
Supports Markdown
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