Commit 236cf089 authored by Jan Möbius's avatar Jan Möbius

Christopher:

Render interface updated to simplify the creation of new render-plugins
New Depth Peeling Renderer based on the new interface
Simplified Shader Pipeline Renderer due to the changes in IRenderrer

Jan:
Split RenderObject out of IRenderer File
Updated Documentation of IRenderer

refs #1377


git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@16081 383ad7c9-94d9-4d36-a494-682f7c89f535
parent a1c16ca7
#include <ACG/GL/gl.hh>
#include <ACG/ShaderUtils/GLSLShader.hh>
#include "Renderer.hh"
#include <ACG/GL/ShaderCache.hh>
#include <ACG/GL/VertexDeclaration.hh>
using namespace ACG;
// =================================================
void Renderer::addRenderObject(RenderObject* _renderObject)
{
// do some more checks for error detection
if (!_renderObject->vertexDecl)
std::cout << "error: missing vertex declaration" << std::endl;
else
{
renderObjects_.push_back(*_renderObject);
RenderObject* p = &renderObjects_.back();
if (!p->shaderDesc.numLights)
p->shaderDesc.numLights = numLights_;
else if (p->shaderDesc.numLights < 0 || p->shaderDesc.numLights >= SG_MAX_SHADER_LIGHTS)
p->shaderDesc.numLights = 0;
p->internalFlags_ = 0;
// precompile shader
ShaderCache::getInstance()->getProgram(&p->shaderDesc);
}
}
void Renderer::collectRenderObjects( GLState* _glState, SceneGraph::DrawModes::DrawMode _drawMode, SceneGraph::BaseNode* _sceneGraphRoot )
{
// collect light sources
collectLightNodes(_sceneGraphRoot);
// flush render objects
// clear() may actually free memory, resulting in capacity = 0
renderObjects_.resize(0);
// default material needed
ACG::SceneGraph::Material defMat;
defMat.baseColor(Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
defMat.ambientColor(Vec4f(0.2f, 0.2f, 0.2f, 1.0f));
defMat.diffuseColor(Vec4f(0.6f, 0.6f, 0.6f, 1.0f));
defMat.specularColor(Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
defMat.shininess(1.0f);
// defMat.alphaValue(1.0f);
// collect renderables
traverseRenderableNodes(_glState, _drawMode, _sceneGraphRoot, &defMat);
}
void Renderer::traverseRenderableNodes( GLState* _glState, SceneGraph::DrawModes::DrawMode _drawMode, SceneGraph::BaseNode* _node, const SceneGraph::Material* _mat )
{
if (_node)
{
SceneGraph::BaseNode::StatusMode status(_node->status());
bool process_children(status != SceneGraph::BaseNode::HideChildren);
SceneGraph::DrawModes::DrawMode nodeDM = _node->drawMode();
if (nodeDM == SceneGraph::DrawModes::DEFAULT)
nodeDM = _drawMode;
// If the subtree is hidden, ignore this node and its children while rendering
if (status != SceneGraph::BaseNode::HideSubtree)
{
if ( _node->status() != SceneGraph::BaseNode::HideNode )
_node->enter(*_glState, _drawMode);
// fetch material (Node itself can be a material node, so we have to
// set that in front of the nodes own rendering
SceneGraph::MaterialNode* matNode = dynamic_cast<SceneGraph::MaterialNode*>(_node);
if (matNode)
_mat = &matNode->material();
if (_node->status() != SceneGraph::BaseNode::HideNode)
_node->getRenderObjects(this, *_glState, nodeDM, _mat);
if (process_children)
{
SceneGraph::BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
// Process all children which are not second pass
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if (~(*cIt)->traverseMode() & SceneGraph::BaseNode::SecondPass)
traverseRenderableNodes( _glState, _drawMode, *cIt, _mat);
// Process all children which are second pass
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if ((*cIt)->traverseMode() & SceneGraph::BaseNode::SecondPass)
traverseRenderableNodes( _glState, _drawMode, *cIt, _mat);
}
if (_node->status() != SceneGraph::BaseNode::HideNode )
_node->leave(*_glState, nodeDM);
}
}
}
void Renderer::traverseLightNodes( ACG::SceneGraph::BaseNode* _node )
{
if (_node && numLights_ < SG_MAX_SHADER_LIGHTS)
{
BaseNode::StatusMode status(_node->status());
bool process_children(status != BaseNode::HideChildren);
// If the subtree is hidden, ignore this node and its children while rendering
if (status != BaseNode::HideSubtree)
{
if (_node->status() != BaseNode::HideNode)
{
ACG::SceneGraph::LightNode* lnode = dynamic_cast<ACG::SceneGraph::LightNode*>(_node);
if (lnode)
{
ACG::SceneGraph::LightSource light;
// lnode->getLightSource(&light);
lnode->getLightSourceViewSpace(&light);
// --------------------------
// add light to renderer
if (light.directional())
lightTypes_[numLights_] = ACG::SG_LIGHT_DIRECTIONAL;
else if (light.spotCutoff() > 179.5f)
lightTypes_[numLights_] = ACG::SG_LIGHT_POINT;
else
lightTypes_[numLights_] = ACG::SG_LIGHT_SPOT;
lights_[numLights_] = light;
++numLights_;
}
}
if (process_children)
{
BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
// Process all children which are not second pass
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
traverseLightNodes(*cIt);
// Process all children which are second pass
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if ((*cIt)->traverseMode() & BaseNode::SecondPass)
traverseLightNodes(*cIt);
}
}
}
}
void Renderer::collectLightNodes( ACG::SceneGraph::BaseNode* _node )
{
numLights_ = 0;
traverseLightNodes(_node);
}
This diff is collapsed.
......@@ -50,21 +50,8 @@
#include <OpenFlipper/BasePlugin/RenderInterface.hh>
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <ACG/Scenegraph/SceneGraph.hh>
#include <ACG/Scenegraph/MaterialNode.hh>
#include <ObjectTypes/Light/LightNode.hh>
#include <ACG/GL/IRenderer.hh>
#include <map>
/** \brief A simple renderer Example for the shader pipeline
*
* It has to derive from ACG::IRenderer as the nodes will will pass back the generated render objects
* via this objects addRenderObject() function.
*/
class Renderer : public QObject, BaseInterface, RenderInterface, LoggingInterface, ACG::IRenderer
{
Q_OBJECT
......@@ -99,167 +86,10 @@ private slots:
void render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties);
QString rendererName() {return QString("Alpha_Version_ShaderPipeline");}
void supportedDrawModes(ACG::SceneGraph::DrawModes::DrawMode& _mode) {_mode = ACG::SceneGraph::DrawModes::DEFAULT;}
QString checkOpenGL();
//=========================================================================
// Callback for the scenegraph nodes
//=========================================================================
public:
/** \brief callback for the nodes, which send new render objects via this function.
*
* AddRenderObject is typically called by a scenegraph nodes during the collection of renderable
* objects.
*
* A renderobject is a collection of opengl states, buffers and parameters, that correspond to exactly one draw call.
*/
virtual void addRenderObject(ACG::RenderObject* _renderObject);
//=========================================================================
// Render object collection
//=========================================================================
private:
/** \brief Traverse the scenegraph to collect render information
*
* Traverses the scenegraph and calls the getRenderObject function of each node.
* Each node can then add multiple renderobjects via addRenderObject to this renderer.
*
* Also collects all light sources in the scenegraph.
* The currently active list of renderobjects is invalidated too.
*/
void collectRenderObjects(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _sceneGraphRoot);
/** \brief Scene graph traversal for render object collection
*
* Calls getRenderObjects on each node of the scenegraph recursively.
*/
void traverseRenderableNodes( ACG::GLState* _glState,
ACG::SceneGraph::DrawModes::DrawMode _drawMode,
ACG::SceneGraph::BaseNode* _node,
const ACG::SceneGraph::Material* _mat);
//=========================================================================
// Light node collection
//=========================================================================
private:
/** \brief Find all light sources in the scene
*
* Find all light nodes in the scene and save them for the next render() call.
*
* The lights are collected in lights_ while the corresponding type ends up in lightTypes_
*/
virtual void collectLightNodes(ACG::SceneGraph::BaseNode* _node);
/** \brief Light Node traverser
*
* Finds all Light Nodes in the scenegraph and stores them for later use. This is a recursive function.
*/
void traverseLightNodes(ACG::SceneGraph::BaseNode* _node);
//=========================================================================
// Sorting
//=========================================================================
private:
/** \brief Compare priority of render objects
*
* compare function for qsort. This is required to compare render objects based
* on their prioerity and render them in the right order
*/
static int cmpPriority(const void*, const void*);
//=========================================================================
// Rendering
//=========================================================================
private:
/** \brief Binding VBOs (First state function)
*
* This is the first function called by renderObject().
*
* It binds vertex, index buffer and vertex format of a
* render object.
*
*/
virtual void bindObjectVBO(ACG::RenderObject* _obj,
GLSL::Program* _prog);
/** \brief Binding Uniforms (Second state function)
*
* This is the second function called by renderObject().
*
* Set common shader constants like model-view-projection matrix,
* material colors and light params.
*/
virtual void bindObjectUniforms(ACG::RenderObject* _obj,
GLSL::Program* _prog);
/** \brief Binding Render state (Third state function)
*
* This is the third function called by renderObject().
*
* Prepare the opengl state machine for a renderobject draw call.
*
* This includes any glEnable/glDisable states, depth-cmp functions, blend equation..
*/
virtual void bindObjectRenderStates(ACG::RenderObject* _obj);
/** \brief Executes the opengl draw call for one object (Fourth function)
*
* This is the fourth function called by renderObject().
*
* Executes one draw call for the given render object
*/
virtual void drawObject(ACG::RenderObject* _obj);
/** \brief Render one render object
*
* Fully prepares opengl for a renderobject and executes the draw call.
* This combines bindObjectVBO, bindObjectUniforms...
*
* Optionally render-states may not be changed, in case depth-peeling or
* similar global shader operations may require a fixed state setting.
*/
virtual void renderObject(ACG::RenderObject* _obj, GLSL::Program* _prog = 0, bool _constRenderStates = false);
//=========================================================================
// Debugging
//=========================================================================
private:
/** \brief Debugging function to dump list of render objects into a file
*
* Dump list of render objects to text file.
* @param _fileName name of text file to write to
* @param _sortedList dump sorted render objects in order, may be 0 to use the unsorted list instead
*/
void dumpRenderObjectsToText(const char* _fileName, ACG::RenderObject** _sortedList = 0) const;
//=========================================================================
// Variables
//=========================================================================
private:
/// Current number of lights (Filled by collectLightNodes)
int numLights_;
/// Light sources (Filled by collectLightNodes)
ACG::SceneGraph::LightSource lights_[SG_MAX_SHADER_LIGHTS];
/// Type of light sources (Filled by collectLightNodes)
ACG::ShaderGenLightType lightTypes_[SG_MAX_SHADER_LIGHTS];
/// Array of renderobjects (Filled by addRenderObject)
std::vector<ACG::RenderObject> renderObjects_;
};
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