Commits

Christian Fischer committed af80be8

added a LightingManager class to help creating scenes with lighting

Comments (0)

Files changed (14)

src/core/wiesel/graph/lighting/light_node_2d.cpp

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "light_node_2d.h"
+
+using namespace wiesel;
+
+
+LightNode2D::LightNode2D() {
+	setTransformDirty();
+}
+
+
+LightNode2D::~LightNode2D() {
+}
+
+
+void LightNode2D::setLightZPosition(float z) {
+	this->light_z = z;
+}
+
+
+vector3d LightNode2D::getWorldLocation() {
+	if (isTransformDirty()) {
+		updateTransform();
+	}
+
+	return vector3d(0.0f, 0.0f, light_z) * getWorldTransform();
+}
+
+
+void LightNode2D::onDraw(wiesel::video::RenderContext* render_context) {
+	Node2D::onDraw(render_context);
+}
+

src/core/wiesel/graph/lighting/light_node_2d.h

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_GRAPH_LIGHTING_LIGHTNODE_2D_H__
+#define __WIESEL_GRAPH_LIGHTING_LIGHTNODE_2D_H__
+
+#include <wiesel/wiesel-core.def>
+#include "wiesel/graph/2d/node2d.h"
+
+#include "light_source.h"
+
+
+namespace wiesel {
+
+	/**
+	 * @brief An implementation of \ref LightSource based on a \ref Node2D.
+	 * This creates a lightsource, which can be moved within a 2D world
+	 * by using the Node2D API functions.
+	 */
+	class WIESEL_CORE_EXPORT LightNode2D :
+			public Node2D,
+			public LightSource
+	{
+	public:
+		LightNode2D();
+		virtual ~LightNode2D();
+
+	public:
+		/**
+		 * @brief Set the Z position of this light.
+		 * This will change the light's distance to the rendered sprites
+		 * and therefore the appearance of the lightcone (depending on the shader).
+		 */
+		void setLightZPosition(float z);
+
+		/**
+		 * @brief Get the Z position of this light.
+		 */
+		inline float getLightZPosition() const {
+			return light_z;
+		}
+
+	// LightSource
+	public:
+		virtual vector3d getWorldLocation();
+
+	protected:
+		virtual void onDraw(wiesel::video::RenderContext *render_context);
+
+	private:
+		float		light_z;
+	};
+
+}
+
+#endif // __WIESEL_GRAPH_LIGHTING_LIGHTNODE_2D_H__

src/core/wiesel/graph/lighting/light_source.cpp

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "light_source.h"
+
+using namespace wiesel;
+
+
+LightSource::LightSource() {
+	this->enabled			= true;
+	this->strength			= 1.0f;
+	this->color_ambient		= vector3d(1.0f, 1.0f, 1.0f);
+	this->color_diffuse		= vector3d(1.0f, 1.0f, 1.0f);
+	this->color_specular	= vector3d(1.0f, 1.0f, 1.0f);
+	return;
+}
+
+LightSource::~LightSource() {
+}
+
+
+void LightSource::setLightEnabled(bool enabled) {
+	this->enabled = enabled;
+}
+
+
+void LightSource::setLightColorAmbient(float r, float g, float b) {
+	this->color_ambient = vector3d(r, g, b);
+}
+
+
+void LightSource::setLightColorAmbient(const vector3d& color) {
+	this->color_ambient = color;
+}
+
+
+void LightSource::setLightColorDiffuse(float r, float g, float b) {
+	this->color_diffuse = vector3d(r, g, b);
+}
+
+
+void LightSource::setLightColorDiffuse(const vector3d& color) {
+	this->color_diffuse = color;
+}
+
+
+void LightSource::setLightColorSpecular(float r, float g, float b) {
+	this->color_specular = vector3d(r, g, b);
+}
+
+
+void LightSource::setLightColorSpecular(const vector3d& color) {
+	this->color_specular = color;
+}
+
+
+void LightSource::setLightStrength(float strength) {
+	this->strength = strength;
+}
+

src/core/wiesel/graph/lighting/light_source.h

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_GRAPH_LIGHTING_LIGHT_SOURCE_H__
+#define __WIESEL_GRAPH_LIGHTING_LIGHT_SOURCE_H__
+
+#include <wiesel/wiesel-core.def>
+#include <wiesel/math/vector3d.h>
+#include <wiesel/util/shared_object.h>
+
+
+namespace wiesel {
+
+	/**
+	 * @brief Abstract base class for any lightsources, which should be handled
+	 * by the \ref LightingManager.
+	 */
+	class WIESEL_CORE_EXPORT LightSource : public virtual SharedObject
+	{
+	public:
+		/**
+		 * @brief An enumeration of various light attributes.
+		 */
+		enum Attribute {
+			Attribute_Position,
+			Attribute_ColorAmbient,
+			Attribute_ColorDiffuse,
+			Attribute_ColorSpecular,
+			Attribute_Strength,
+		};
+
+
+	public:
+		LightSource();
+		virtual ~LightSource();
+
+	// properties
+	public:
+		/**
+		 * @brief Set whether this light is enabled or not.
+		 */
+		void setLightEnabled(bool enabled);
+
+		/**
+		 * @brief Get whether this light is enabled or not.
+		 */
+		inline bool isLightEnabled() const {
+			return enabled;
+		}
+
+
+		/**
+		 * @brief Set the light's ambient color.
+		 */
+		void setLightColorAmbient(float r, float g, float b);
+
+		/**
+		 * @brief Set the light's ambient color.
+		 */
+		void setLightColorAmbient(const vector3d& color);
+
+		/**
+		 * @brief Get the light's ambient color.
+		 */
+		inline const vector3d& getLightColorAmbient() const {
+			return color_ambient;
+		}
+
+
+		/**
+		 * @brief Set the light's diffuse color.
+		 */
+		void setLightColorDiffuse(float r, float g, float b);
+
+		/**
+		 * @brief Set the light's diffuse color.
+		 */
+		void setLightColorDiffuse(const vector3d& color);
+
+		/**
+		 * @brief Get the light's diffuse color.
+		 */
+		inline const vector3d& getLightColorDiffuse() const {
+			return color_diffuse;
+		}
+
+
+		/**
+		 * @brief Set the light's specular color.
+		 */
+		void setLightColorSpecular(float r, float g, float b);
+
+		/**
+		 * @brief Set the light's specular color.
+		 */
+		void setLightColorSpecular(const vector3d& color);
+
+		/**
+		 * @brief Get the light's specular color.
+		 */
+		inline const vector3d& getLightColorSpecular() const {
+			return color_specular;
+		}
+
+
+		/**
+		 * @brief Set the light's strength.
+		 */
+		void setLightStrength(float strength);
+
+		/**
+		 * @brief Get the light's strength.
+		 */
+		inline float getLightStrength() const {
+			return strength;
+		}
+
+	// overridables
+	public:
+		/**
+		 * @brief Computes the location of this light source in world space.
+		 */
+		virtual vector3d getWorldLocation() = 0;
+
+	private:
+		bool		enabled;
+		vector3d	color_ambient;
+		vector3d	color_diffuse;
+		vector3d	color_specular;
+		float		strength;
+	};
+
+} // namespace wiesel
+
+#endif // __WIESEL_GRAPH_LIGHTING_LIGHT_SOURCE_H__

src/core/wiesel/graph/lighting/lighting_manager.cpp

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "lighting_manager.h"
+
+using namespace wiesel;
+using namespace wiesel::video;
+
+
+LightingManager::LightingManager() {
+	this->max_light_sources			= 4;
+	this->memberindex_lights_count	= -1;
+	this->buffer_template			= new ShaderConstantBufferTemplate();
+}
+
+
+LightingManager::~LightingManager() {
+	removeAllLightSources();
+	removeAllTargets();
+}
+
+
+
+void LightingManager::addLightSource(LightSource* light) {
+	if (light) {
+		std::set<LightSource*>::iterator it = managed_light_sources.find(light);
+		if (it == managed_light_sources.end()) {
+			managed_light_sources.insert(keep(light));
+		}
+	}
+
+	return;
+}
+
+
+void LightingManager::removeLightSource(LightSource* light) {
+	if (light) {
+		std::set<LightSource*>::iterator it = managed_light_sources.find(light);
+		if (it != managed_light_sources.end()) {
+			release(*it);
+			managed_light_sources.erase(it);
+		}
+	}
+
+	return;
+}
+
+
+void LightingManager::removeAllLightSources() {
+	for(std::set<LightSource*>::iterator it=managed_light_sources.begin(); it!=managed_light_sources.end(); it++) {
+		release(*it);
+	}
+
+	managed_light_sources.clear();
+
+	return;
+}
+
+
+
+void LightingManager::addTarget(ShaderTarget* target) {
+	if (target) {
+		{
+			std::set<ShaderTarget*>::iterator it = managed_targets.find(target);
+			if (it != managed_targets.end()) {
+				return;
+			}
+		}
+
+		managed_targets.insert(keep(target));
+
+		Node2D *node2d = dynamic_cast<Node2D*>(target);
+		if (node2d) {
+			std::set<Node2D*>::iterator it = managed_2d_nodes.find(node2d);
+			if (it == managed_2d_nodes.end()) {
+				managed_2d_nodes.insert(keep(node2d));
+			}
+		}
+
+		// assign all shader data to this target
+		Shader* current_shader = getCurrentLightingShader();
+		if (current_shader) {
+			target->setShader(current_shader);
+		}
+		else {
+			// when no default shader provided by the lighting manager,
+			// the target must already contain a valid shader.
+			assert(target->getShader() != NULL);
+		}
+
+		target->assignShaderConstantBuffer(
+				getConstantBufferName(),
+				getConstantBuffer()
+		);
+	}
+
+	return;
+}
+
+
+void LightingManager::removeTarget(ShaderTarget* target) {
+	if (target) {
+		{
+			std::set<ShaderTarget*>::iterator it = managed_targets.find(target);
+			if (it != managed_targets.end()) {
+				release(*it);
+				managed_targets.erase(it);
+			}
+		}
+
+		Node2D *node2d = dynamic_cast<Node2D*>(target);
+		if (node2d) {
+			std::set<Node2D*>::iterator it = managed_2d_nodes.find(node2d);
+			if (it != managed_2d_nodes.end()) {
+				release(*it);
+				managed_2d_nodes.erase(it);
+			}
+		}
+	}
+
+	return;
+}
+
+
+void LightingManager::removeAllTargets() {
+	for(std::set<ShaderTarget*>::iterator it=managed_targets.begin(); it!=managed_targets.end(); it++) {
+		release(*it);
+	}
+
+	for(std::set<Node2D*>::iterator it=managed_2d_nodes.begin(); it!=managed_2d_nodes.end(); it++) {
+		release(*it);
+	}
+
+	managed_targets.clear();
+	managed_2d_nodes.clear();
+
+	return;
+}
+
+
+
+void LightingManager::setDefaultLightingShader(Shader* shader) {
+	if (shader) {
+		// chec, if the shader contains the correct constant buffer
+		assert(shader->findConstantBufferTemplate(getConstantBufferName()) == getConstantBufferTemplate());
+
+		this->default_lighting_shader = shader;
+	}
+
+	return;
+}
+
+
+Shader* LightingManager::getDefaultLightingShader() {
+	return default_lighting_shader;
+}
+
+
+Shader* LightingManager::getCurrentLightingShader() {
+	if (default_lighting_shader) {
+		return default_lighting_shader;
+	}
+
+	return NULL;
+}
+
+
+
+const ShaderConstantBufferWriter::data_t LightingManager::getShaderDataPointer(const std::string &name, ValueType type, size_t elements) const {
+	return buffer->getShaderDataPointer(name, type, elements);
+}
+
+
+bool LightingManager::doSetShaderValue(const std::string &name, ValueType type, size_t elements, const void *pValue) {
+	return buffer->setShaderValue(name, type, elements, pValue);
+}
+
+
+
+void LightingManager::render(RenderContext *render_context) {
+	preRender();
+
+	Node::render(render_context);
+
+	return;
+}
+
+
+void LightingManager::preRender() {
+	int current_light_index = 0;
+
+	for(
+			std::set<LightSource*>::iterator
+			light_it=managed_light_sources.begin();
+			light_it!=managed_light_sources.end();
+			light_it++
+	) {
+		LightSource *light = *light_it;
+
+		if (light->isLightEnabled() == false) {
+			continue;
+		}
+
+		// set all light members
+		for(LightInfoMembers::iterator it=light_info_members.begin(); it!=light_info_members.end(); it++) {
+			assert(current_light_index < static_cast<int>(it->member_index_per_light.size()));
+			ShaderConstantBufferTemplate::index_t var_index = it->member_index_per_light[current_light_index];
+
+			switch(it->attribute) {
+				case LightSource::Attribute_Position: {
+					const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(var_index);
+					vector3d world_location = light->getWorldLocation();
+
+					if (world_location != *(reinterpret_cast<const vector3d*>(data))) {
+						buffer->setShaderValueAt(var_index, world_location);
+					}
+
+					break;
+				}
+
+				case LightSource::Attribute_ColorAmbient: {
+					const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(var_index);
+
+					if (light->getLightColorAmbient() != *(reinterpret_cast<const vector3d*>(data))) {
+						buffer->setShaderValueAt(var_index, light->getLightColorAmbient());
+					}
+
+					break;
+				}
+
+				case LightSource::Attribute_ColorDiffuse: {
+					const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(var_index);
+
+					if (light->getLightColorDiffuse() != *(reinterpret_cast<const vector3d*>(data))) {
+						buffer->setShaderValueAt(var_index, light->getLightColorDiffuse());
+					}
+
+					break;
+				}
+
+				case LightSource::Attribute_ColorSpecular: {
+					const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(var_index);
+
+					if (light->getLightColorSpecular() != *(reinterpret_cast<const vector3d*>(data))) {
+						buffer->setShaderValueAt(var_index, light->getLightColorSpecular());
+					}
+
+					break;
+				}
+
+				case LightSource::Attribute_Strength: {
+					const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(var_index);
+
+					if (light->getLightStrength() != *(reinterpret_cast<const float*>(data))) {
+						buffer->setShaderValueAt(var_index, light->getLightStrength());
+					}
+
+					break;
+				}
+			}
+		}
+
+		++current_light_index;
+	}
+
+	// update the number of active lights
+	if (memberindex_lights_count != -1) {
+		const ShaderConstantBuffer::data_t data = buffer->getShaderDataPointerAt(memberindex_lights_count);
+
+		if (current_light_index != *(reinterpret_cast<const int*>(data))) {
+			buffer->setShaderValueAt(memberindex_lights_count, current_light_index);
+		}
+	}
+
+	return;
+}

src/core/wiesel/graph/lighting/lighting_manager.h

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_GRAPH_LIGHTING_LIGHTING_MANAGER_H__
+#define __WIESEL_GRAPH_LIGHTING_LIGHTING_MANAGER_H__
+
+#include <wiesel/graph/node.h>
+#include <wiesel/util/shared_object.h>
+#include <wiesel/wiesel-core.def>
+
+#include "wiesel/video/shader_constantbuffer.h"
+#include "wiesel/video/shader_target.h"
+
+#include "light_source.h"
+
+
+namespace wiesel {
+
+	/**
+	 * @brief The LightingManager is a helper class to manage light sources
+	 * and lighting targets.
+	 * The LightingManager needs to be part of the scene graph, either as a
+	 * parent of all targets and lights, or a sibling within the tree. When
+	 * added as a sibling, it should have a high priority in order to get
+	 * invoked before rendering the targets itself.
+	 */
+	class WIESEL_CORE_EXPORT LightingManager :
+			public Node,
+			public video::ShaderConstantBufferWriter
+	{
+	friend class LightingManagerBuilder;
+
+	private:
+		LightingManager();
+
+	public:
+		virtual ~LightingManager();
+
+	// managing lights
+	public:
+		/**
+		 * @brief Adds a new \ref LightSource to this lighting manager.
+		 */
+		void addLightSource(LightSource *light);
+
+		/**
+		 * @brief Removes a light source from this manager.
+		 */
+		void removeLightSource(LightSource *light);
+
+		/**
+		 * @brief Removes all light sources from this manager.
+		 */
+		void removeAllLightSources();
+
+	// managing objects
+	public:
+		/**
+		 * @brief Adds a \ref ShaderTarget to this lighting manager, which will
+		 * receive all data managed by this object.
+		 */
+		void addTarget(video::ShaderTarget *target);
+
+		/**
+		 * @brief Removes a shader target from this manager.
+		 */
+		void removeTarget(video::ShaderTarget *target);
+
+		/**
+		 * @brief Removes all targets from this manager.
+		 */
+		void removeAllTargets();
+
+	// managing shaders
+	public:
+		/**
+		 * @brief Set a shader, which should be used for all managed targets per default.
+		 * When set, this shader will be set for all targets under the manager's control.
+		 */
+		void setDefaultLightingShader(video::Shader *shader);
+
+		/**
+		 * @brief Get the current default shader for all managed objects.
+		 */
+		video::Shader *getDefaultLightingShader();
+
+		/**
+		 * @brief Get the currently used shader, depending on the currently active lights.
+		 * @return A shader, when a default shader was configured, or \c NULL, if not.
+		 */
+		video::Shader *getCurrentLightingShader();
+
+	// properties
+	public:
+		/**
+		 * @brief Set the maximum number of active light sources, which can be handled
+		 * by the lighting manager and the according shaders at the same time.
+		 */
+		inline uint8_t getMaxLightSources() const {
+			return max_light_sources;
+		}
+
+		/**
+		 * @brief Get the name of the uniform member which contains the lights data.
+		 */
+		inline const std::string& getLightsUniformName() const {
+			return membername_lights;
+		}
+
+		/**
+		 * @brief Get the name of the uniform member which contains the number of currently active lights.
+		 */
+		inline const std::string& getLightsCountUniformName() const {
+			return membername_lights_count;
+		}
+
+		/**
+		 * @brief Get the name of the constant buffer, which contains the light-information
+		 * managed by this lighting manager.
+		 */
+		inline const std::string& getConstantBufferName() const {
+			return buffer_name;
+		}
+
+		/**
+		 * @brief Get the template for constant buffers containing the light-information
+		 * managed by this lighting manager.
+		 */
+		inline video::ShaderConstantBufferTemplate* getConstantBufferTemplate() {
+			return buffer_template;
+		}
+
+		/**
+		 * @brief Get the template for constant buffers containing the light-information
+		 * managed by this lighting manager.
+		 */
+		inline const video::ShaderConstantBufferTemplate* getConstantBufferTemplate() const {
+			return buffer_template;
+		}
+
+		/**
+		 * @brief Get the constant buffer containing the light-information
+		 * manager by this lighting manager.
+		 */
+		inline video::ShaderConstantBuffer* getConstantBuffer() {
+			return buffer;
+		}
+
+	// ShaderConstantBufferWriter
+	public:
+		virtual const data_t getShaderDataPointer(const std::string &name, video::ValueType type, size_t elements) const;
+
+	// ShaderConstantBufferWriter
+	protected:
+		virtual bool doSetShaderValue(const std::string &name, video::ValueType type, size_t elements, const void *pValue);
+
+
+	public:
+		virtual void render(video::RenderContext *render_context);
+
+	protected:
+		virtual void preRender();
+
+	private:
+		struct LightInfoMember {
+			LightSource::Attribute		attribute;
+			video::ValueType			type;
+			std::string					name;
+
+			std::vector<video::ShaderConstantBufferTemplate::index_t>		member_index_per_light;
+		};
+
+		typedef std::vector<LightInfoMember>	LightInfoMembers;
+
+	private:
+		uint8_t											max_light_sources;
+
+		std::string										membername_lights_count;
+		std::string										membername_lights;
+		video::ShaderConstantBufferTemplate::index_t	memberindex_lights_count;
+		LightInfoMembers								light_info_members;
+
+		std::string										buffer_name;
+		ref<video::ShaderConstantBufferTemplate>		buffer_template;
+		ref<video::ShaderConstantBuffer>				buffer;
+
+		ref<video::Shader>								default_lighting_shader;
+
+		std::set<LightSource*>							managed_light_sources;
+		std::set<video::ShaderTarget*>					managed_targets;
+		std::set<Node2D*>								managed_2d_nodes;
+	};
+
+} // namespace wiesel
+
+#endif // __WIESEL_GRAPH_LIGHTING_LIGHTING_MANAGER_H__

src/core/wiesel/graph/lighting/lighting_manager_builder.cpp

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "lighting_manager_builder.h"
+#include "lighting_manager.h"
+
+#include <sstream>
+
+using namespace wiesel;
+using namespace wiesel::video;
+
+
+LightingManagerBuilder::LightingManagerBuilder() {
+	this->manager				= new LightingManager();
+	this->finished				= false;
+	this->lightinfo_created		= false;
+}
+
+
+LightingManagerBuilder::~LightingManagerBuilder() {
+	assert(this->manager == NULL);
+	assert(this->finished);
+	
+	// delete the manager, when the builder was destructed,
+	// before the construction was finished.
+	if (this->manager) {
+		assert(this->manager->getReferenceCount() == 0);
+		delete this->manager;
+		this->manager = NULL;
+	}
+
+	return;
+}
+
+
+void LightingManagerBuilder::setMaxLightSources(uint8_t max_light_sources) {
+	assert(manager);
+	if (manager) {
+		manager->max_light_sources = max_light_sources;
+	}
+
+	return;
+}
+
+
+uint8_t LightingManagerBuilder::getMaxLightSources() const {
+	if (manager) {
+		return manager->getMaxLightSources();
+	}
+
+	return 0;
+}
+
+
+void LightingManagerBuilder::setConstantBufferName(const std::string& name) {
+	assert(manager);
+	if (manager) {
+		manager->buffer_name = name;
+	}
+
+	return;
+}
+
+
+std::string LightingManagerBuilder::getConstantBufferName() const {
+	if (manager) {
+		return manager->getConstantBufferName();
+	}
+
+	return std::string();
+}
+
+
+void LightingManagerBuilder::setLightsUniformName(const std::string& name) {
+	if (manager) {
+		manager->membername_lights = name;
+	}
+
+	return;
+}
+
+
+std::string LightingManagerBuilder::getLightsUniformName() const {
+	if (manager) {
+		return manager->getLightsUniformName();
+	}
+
+	return std::string();
+}
+
+
+void LightingManagerBuilder::setLightsCountUniformName(const std::string& name) {
+	if (manager) {
+		manager->membername_lights_count = name;
+	}
+
+	return;
+}
+
+
+std::string LightingManagerBuilder::getLightsCountUniformName() const {
+	if (manager) {
+		return manager->getLightsCountUniformName();
+	}
+
+	return std::string();
+}
+
+
+
+
+void LightingManagerBuilder::addLightInfoMember(LightSource::Attribute attribute, ValueType type, const std::string& name) {
+	LightInfoMember member;
+	member.attribute	= attribute;
+	member.type			= type;
+	member.name			= name;
+
+	lightinfo_struct.push_back(member);
+}
+
+
+void LightingManagerBuilder::addDefaultLightInfoMember(LightSource::Attribute attribute) {
+	switch(attribute) {
+		case LightSource::Attribute_Position: {
+			addLightInfoMember(LightSource::Attribute_Position,			TypeVector3f,		"position"	);
+			break;
+		}
+
+		case LightSource::Attribute_ColorAmbient: {
+			addLightInfoMember(LightSource::Attribute_ColorAmbient,		TypeVector3f,		"ambient_color"		);
+			break;
+		}
+
+		case LightSource::Attribute_ColorDiffuse: {
+			addLightInfoMember(LightSource::Attribute_ColorDiffuse,		TypeVector3f,		"diffuse_color"		);
+			break;
+		}
+
+		case LightSource::Attribute_ColorSpecular: {
+			addLightInfoMember(LightSource::Attribute_ColorSpecular,	TypeVector3f,		"specular_color"		);
+			break;
+		}
+
+		case LightSource::Attribute_Strength: {
+			addLightInfoMember(LightSource::Attribute_Strength,			TypeFloat,			"strength"	);
+			break;
+		}
+	}
+
+	return;
+}
+
+
+void LightingManagerBuilder::finishLightInfoMembers() {
+	assert(lightinfo_created == false);
+	assert(finished == false);
+	assert(manager);
+
+	if (lightinfo_created == false && finished == false && manager) {
+		assert(getLightsUniformName().empty() == false);
+		if (getLightsUniformName().empty()) {
+			return;
+		}
+
+		if (getLightsCountUniformName().empty() == false) {
+			getConstantBufferTemplate()->addEntry(TypeInt32, 1, getLightsCountUniformName());
+		}
+
+		// fill the constant buffer template with all required members
+		for(int light=0; light<getMaxLightSources(); light++) {
+			for(LightInfoStruct::iterator it=lightinfo_struct.begin(); it!=lightinfo_struct.end(); it++) {
+				std::stringstream ss;
+				ss << getLightsUniformName();
+				ss << '[' << light << ']';
+				ss << '.' << it->name;
+
+				getConstantBufferTemplate()->addEntry(it->type, 1, ss.str());
+			}
+		}
+
+		// create a list containing indices for all light info members
+		manager->light_info_members.reserve(lightinfo_struct.size());
+		for(LightInfoStruct::iterator it=lightinfo_struct.begin(); it!=lightinfo_struct.end(); it++) {
+			LightingManager::LightInfoMember info_member;
+			info_member.attribute	= it->attribute;
+			info_member.type		= it->type;
+			info_member.name		= it->name;
+			info_member.member_index_per_light.resize(getMaxLightSources());
+
+			for(int light=0; light<getMaxLightSources(); light++) {
+				std::stringstream ss;
+				ss << getLightsUniformName();
+				ss << '[' << light << ']';
+				ss << '.' << it->name;
+
+				ShaderConstantBufferTemplate::index_t idx;
+				idx = getConstantBufferTemplate()->findShaderValueIndex(ss.str());
+				assert(idx != -1);
+
+				info_member.member_index_per_light[light] = idx;
+			}
+
+			manager->light_info_members.push_back(info_member);
+		}
+
+		// get the index of the lights count member
+		if (getLightsCountUniformName().empty() == false) {
+			ShaderConstantBufferTemplate::index_t idx;
+			idx = getConstantBufferTemplate()->findShaderValueIndex(getLightsCountUniformName());
+			manager->memberindex_lights_count = idx;
+		}
+		else {
+			manager->memberindex_lights_count = -1;
+		}
+
+		// create the constant buffer based on this template
+		manager->buffer = new ShaderConstantBuffer(manager->getConstantBufferTemplate());
+
+		// initialize the buffer with zero active lights
+		manager->getConstantBuffer()->setShaderValue(getLightsCountUniformName(), 0);
+
+		lightinfo_created = true;
+	}
+
+	return;
+}
+
+
+
+
+ShaderConstantBufferTemplate* LightingManagerBuilder::getConstantBufferTemplate() {
+	if (manager) {
+		return manager->buffer_template;
+	}
+
+	return NULL;
+}
+
+
+LightingManager* LightingManagerBuilder::create() {
+	assert(this->manager);
+
+	if (this->manager) {
+		if (this->lightinfo_created == false) {
+			finishLightInfoMembers();
+		}
+
+		// clear the object reference to the created manager
+		// and set the builder's state to 'finished'
+		LightingManager* _manager = this->manager;
+		this->manager  = NULL;
+		this->finished = true;
+
+		return _manager;
+	}
+
+	return NULL;
+}
+

src/core/wiesel/graph/lighting/lighting_manager_builder.h

+/**
+ * Copyright (C) 2013
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_VIDEO_LIGHTING_MANAGER_BUILDER_H__
+#define __WIESEL_VIDEO_LIGHTING_MANAGER_BUILDER_H__
+
+#include <wiesel/wiesel-core.def>
+
+#include "lighting_manager.h"
+
+
+namespace wiesel {
+
+
+	/**
+	 * @brief A helper class to construct a new instance of \ref LightingManager.
+	 */
+	class WIESEL_CORE_EXPORT LightingManagerBuilder
+	{
+	public:
+		LightingManagerBuilder();
+		virtual ~LightingManagerBuilder();
+
+	public:
+		/**
+		 * @brief A struct describing a single element within the light-info struct.
+		 */
+		struct LightInfoMember {
+			std::string					name;
+			LightSource::Attribute		attribute;
+			video::ValueType			type;
+		};
+
+
+		/**
+		 * @brief Alias type for a collection of light info members,
+		 * which describes the light info struct within the shader.
+		 */
+		typedef std::vector<LightInfoMember>	LightInfoStruct;
+
+	public:
+		/**
+		 * @brief Set the maximum number of active light sources, which can be handled
+		 * by the lighting manager and the according shaders at the same time.
+		 * When the given number is too small, some lights may disappear in the final scene.
+		 * @param max_light_sources		The maximum number of lights allowed simultaneously.
+		 *								The value should be positive and non-zero.
+		 */
+		void setMaxLightSources(uint8_t max_light_sources);
+
+		/**
+		 * @brief Set the maximum number of active light sources, which can be handled
+		 * by the lighting manager and the according shaders at the same time.
+		 */
+		uint8_t getMaxLightSources() const;
+
+		/**
+		 * @brief Set the name of the constant buffer, which contains the light information
+		 * generated by the created lighting manager.
+		 */
+		void setConstantBufferName(const std::string& name);
+
+		/**
+		 * @brief Get the name of the constant buffer, which contains the light information
+		 */
+		std::string getConstantBufferName() const;
+
+		/**
+		 * @brief Set the name of the uniform member which contains the lights data.
+		 */
+		void setLightsUniformName(const std::string& name);
+
+		/**
+		 * @brief Get the name of the uniform member which contains the lights data.
+		 */
+		std::string getLightsUniformName() const;
+
+		/**
+		 * @brief Set the name of the uniform member which contains the number of currently active lights.
+		 */
+		void setLightsCountUniformName(const std::string& name);
+
+		/**
+		 * @brief Get the name of the uniform member which contains the number of currently active lights.
+		 */
+		std::string getLightsCountUniformName() const;
+
+	public:
+		/**
+		 * @brief Adds a member to the light info struct.
+		 * @param attribute		The light attribute type.
+		 * @param type			The value type for this member.
+		 * @param name			The member's name.
+		 */
+		void addLightInfoMember(LightSource::Attribute attribute, video::ValueType type, const std::string& name);
+
+		/**
+		 * @brief Adds a light info member with it's default parameters.
+		 * @param attribute		The light attribute type.
+		 */
+		void addDefaultLightInfoMember(LightSource::Attribute attribute);
+
+		/**
+		 * @brief Finishes the light info members within the shader constant buffer.
+		 * This will be invoked automatically in \ref create, but may be used earlier,
+		 * to be able to add additional uniform members behind the lights data.
+		 */
+		virtual void finishLightInfoMembers();
+
+		/**
+		 * @brief Get all light info members added to the current lighting manager.
+		 */
+		inline const LightInfoStruct* getLightInfoMembers() const {
+			return &lightinfo_struct;
+		}
+
+	public:
+		/**
+		 * @brief Provides access to the lighting managers constant buffer template
+		 * to add custom attributes to it, which are not under control of the
+		 * generated lighting manager.
+		 */
+		video::ShaderConstantBufferTemplate* getConstantBufferTemplate();
+
+		/**
+		 * @brief Finally creates the instance of the generated lighting manager.
+		 * After calling this function, the builder is invalid and should be deleted.
+		 */
+		virtual LightingManager* create();
+
+	private:
+		LightingManager*	manager;
+
+		LightInfoStruct		lightinfo_struct;
+		bool				lightinfo_created;
+
+		bool				finished;
+	};
+
+} // namespace wiesel
+
+#endif // __WIESEL_VIDEO_LIGHTING_MANAGER_BUILDER_H__

src/core/wiesel/graph/node.cpp

 
 
 void Node::updateTransform() {
+	// update the parent's transform first, if neccessary
+	if (getParent() && getParent()->isTransformDirty()) {
+		getParent()->updateTransform();
+	}
+
 	// compute the local transform
 	local_transform = matrix4x4::identity;
 	computeLocalTransform(&local_transform);

src/core/wiesel/video/shader_constantbuffer.cpp

 }
 
 
+ShaderConstantBufferTemplate::index_t ShaderConstantBufferTemplate::findShaderValueIndex(const std::string& name) const {
+	for(index_t i=getEntries()->size(); --i>=0;) {
+		if ((*(getEntries()))[i].name == name) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+
+
 ShaderConstantBuffer *ShaderConstantBufferTemplate::getSharedBuffer() {
 	if (shared_buffer == NULL) {
 		shared_buffer = new ShaderConstantBuffer(this);
 
 
 
-ShaderConstantBuffer::index_t ShaderConstantBuffer::getShaderValueIndex(const std::string& name) const {
-	if (getTemplate()) {
-		for(index_t i=getTemplate()->getEntries()->size(); --i>=0;) {
-			if ((*(getTemplate()->getEntries()))[i].name == name) {
-				return i;
-			}
-		}
-	}
-
-	return -1;
-}
-
-
-
 const ShaderConstantBuffer::data_t ShaderConstantBuffer::getShaderDataPointer(const std::string &name, ValueType type, size_t elements) const {
 	if (getTemplate()) {
 		for(
 }
 
 
+const ShaderConstantBuffer::data_t ShaderConstantBuffer::getShaderDataPointerAt(ShaderConstantBufferTemplate::index_t index) const {
+	if (getTemplate()) {
+		const ShaderConstantBufferTemplate::EntryList *entries = getTemplate()->getEntries();
+		assert(index < static_cast<int>(entries->size()));
+
+		if (index >= 0 && index < static_cast<int>(entries->size())) {
+			return data + entries->at(index).offset;
+		}
+	}
+
+	return NULL;
+}
+
+
 
 bool ShaderConstantBuffer::writeDataAtOffset(size_t offset, const void *pValue, size_t size) {
 	if (

src/core/wiesel/video/shader_constantbuffer.h

 		/// Alias type for a list of entries
 		typedef std::vector<Entry>		EntryList;
 
+		/// type for indices of the values within this buffer
+		typedef signed int index_t;
+
 	public:
 		ShaderConstantBufferTemplate();
 
 		const Entry *findEntry(const std::string &name) const;
 
 		/**
+		 * @brief Tries to find the index of a specific shader value.
+		 * @param name		Name of the variable to get.
+		 * @return The index of the requested variable or \c -1, when not found.
+		 */
+		index_t findShaderValueIndex(const std::string& name) const;
+
+		/**
 		 * @brief Returns the list of all entries, contained in this buffer.
 		 */
 		inline const EntryList* getEntries() const {
 	// data access
 	public:
 		/**
-		 * @brief Get the index of a specific shader value.
-		 * @param name		Name of the variable to get.
-		 * @return The index of the requested variable or \c -1, when not found.
-		 */
-		index_t getShaderValueIndex(const std::string& name) const;
-
-		/**
 		 * @brief Writes raw data to a given offset.
 		 * The buffer needs to be large enough to store the whole data block,
 		 * otherwise the operation will fail.
 
 	// ShaderConstantBufferWriter
 	public:
+		/**
+		 * @brief Get a pointer to the value of a variable by it's index.
+		 * @param index		The index of the requested variable.
+		 * @return A pointer to the requested variable, or \c NULL, when the variable was not found.
+		 */
+		virtual const data_t getShaderDataPointerAt(ShaderConstantBufferTemplate::index_t index) const;
+
 		virtual const data_t getShaderDataPointer(const std::string &name, ValueType type, size_t elements) const;
 
 	// ShaderConstantBufferWriter

src/core/wiesel/video/shader_target.cpp

 }
 
 
+bool ShaderTarget::assignShaderConstantBuffer(const std::string& name, ShaderConstantBuffer* buffer) {
+	// buffer needs to be valid - no empty buffer slots are allowed
+	assert(buffer);
+	if (buffer == NULL) {
+		return false;
+	}
+
+	// the shader needs to be set before assigning buffers
+	assert(getShader());
+
+	if (getShader()) {
+		ShaderConstantBufferTemplate *tpl = getShader()->findConstantBufferTemplate(name);
+		assert(tpl);
+
+		if (tpl) {
+			assert(tpl == buffer->getTemplate());
+
+			if (tpl == buffer->getTemplate()) {
+				BufferMap::iterator it = buffers.find(name);
+				if (it != buffers.end()) {
+					if (it->second != buffer) {
+						release(it->second);
+						it->second = keep(buffer);
+					}
+				}
+				else {
+					buffers[name] = keep(buffer);
+				}
+
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+
+ShaderConstantBuffer* ShaderTarget::findAssignedShaderConstantBuffer(const std::string& name) {
+	BufferMap::iterator it = buffers.find(name);
+	if (it != buffers.end()) {
+		return it->second;
+	}
+
+	return NULL;
+}
+
+
 bool ShaderTarget::doSetShaderValue(const std::string &name, ValueType type, size_t elements, const void *pValue) {
 	bool success = false;
 

src/core/wiesel/video/shader_target.h

 			return shader;
 		}
 
+		/**
+		 * @brief Assigns a n existing shader constant buffer to this target.
+		 * A buffer may be used for multiple targets.
+		 * The shader has to be set before assigning a buffer and the buffer
+		 * must belong to the target's current shader.
+		 * @param name		The name of the buffer, which will be assigned.
+		 * @param buffer	The buffer to be assigned.
+		 * @return \c true on success, \c false otherwise.
+		 */
+		bool assignShaderConstantBuffer(const std::string& name, ShaderConstantBuffer *buffer);
+
+		/**
+		 * @brief Get a constant buffer, which is currently assigned to this shader target.
+		 * @param name		The name of the requested buffer.
+		 * @return The requested buffer, or \c NULL, when no buffer was found.
+		 */
+		ShaderConstantBuffer* findAssignedShaderConstantBuffer(const std::string& name);
+
 	// ConstantBufferSetter
 	public:
 		virtual const data_t getShaderDataPointer(const std::string &name, ValueType type, size_t elements) const;

src/opengl/wiesel/video/gl/gl_render_context.cpp

 				ShaderConstantBuffer *projection_buffer = projection_buffer_template->getSharedBuffer();
 
 				// get the data pointer
-				ShaderConstantBuffer::data_t projection_data_ptr = projection_buffer->getShaderDataPointer(
-													Shaders::UNIFORM_PROJECTION_MATRIX,
-													TypeMatrix4x4f,
-													1
-				);
+				ShaderConstantBuffer::data_t projection_data_ptr = projection_buffer->getShaderDataPointerAt(0);
 
 				// check if the projection matrix has changed
 				if (this->projection != *(reinterpret_cast<const matrix4x4*>(projection_data_ptr))) {