Commits

Christian Fischer committed 7c664d7

added ShaderTarget baseclass for configuring shader attributes

Comments (0)

Files changed (12)

src/core/wiesel/graph/2d/multisprite_node.cpp

 
 MultiSpriteNode::MultiSpriteNode() {
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->indices		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 
 MultiSpriteNode::MultiSpriteNode(Texture *texture) {
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->indices		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 }
 
 
-void MultiSpriteNode::setShader(Shader* shader) {
-	if (this->shader) {
-		this->shader->release();
-		this->shader = NULL;
-	}
-
-	if (shader) {
-		this->shader = shader;
-		this->shader->retain();
-	}
-
-	return;
-}
-
-
 MultiSpriteNode::index_t MultiSpriteNode::addSprite(SpriteFrame* sprite, float offset_x, float offset_y) {
 	return addSprite(sprite, vector2d(offset_x, offset_y));
 }
 			rebuildVertexBuffer();
 		}
 
-		render_context->setShader(shader);
+		applyShaderConfigTo(render_context);
 		render_context->setModelviewMatrix(getWorldTransform());
 		render_context->prepareTextureLayers(1);
 		render_context->setTexture(0, texture);
 		}
 	}
 
-	if (shader == NULL) {
+	if (getShader() == NULL) {
 		setShader(Shaders::instance()->getShaderFor(vbo));
 	}
 

src/core/wiesel/graph/2d/multisprite_node.h

 	 * This Node is designed to provide a very basic functionality, so each sprite can
 	 * have an individual offset, but no custom transformations like scaling or rotation.
 	 */
-	class WIESEL_CORE_EXPORT MultiSpriteNode : public Node2D
+	class WIESEL_CORE_EXPORT MultiSpriteNode : public Node2D, public video::ShaderTarget
 	{
 	public:
 		/**
 		void setSpriteHitDetection(SpriteHitDetection hit);
 
 		/**
-		 * @brief Set the Shader to be used for rendering.
-		 */
-		void setShader(video::Shader *shader);
-
-		/**
 		 * @brief Set the texture to be rendered.
 		 * NOTE: All frames must be within the same texture. When the texture is set to NULL
 		 * or to another texture, all sprite frames will be removed.
 		}
 
 		/**
-		 * @brief Get the currently used shader.
-		 */
-		inline video::Shader *getShader() {
-			return shader;
-		}
-
-		/**
 		 * @brief Get the currently used texture.
 		 */
 		inline video::Texture *getTexture() {
 		EntryList				entries;
 
 		video::Texture*			texture;
-		video::Shader*			shader;
 		video::IndexBuffer*		indices;
 		video::VertexBuffer*	vbo;
 		bool					vbo_dirty;

src/core/wiesel/graph/2d/sprite_node.cpp

 SpriteNode::SpriteNode() {
 	this->sprite		= NULL;
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 	this->hit_detection	= SpriteHitDetection_InnerBounds;
 SpriteNode::SpriteNode(Texture *texture) {
 	this->sprite		= NULL;
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 	this->hit_detection	= SpriteHitDetection_InnerBounds;
 
 	this->sprite		= NULL;
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 	this->hit_detection	= SpriteHitDetection_InnerBounds;
 
 	this->sprite		= NULL;
 	this->texture		= NULL;
-	this->shader		= NULL;
 	this->vbo			= NULL;
 	this->vbo_dirty		= true;
 	this->hit_detection	= SpriteHitDetection_InnerBounds;
 }
 
 
-void SpriteNode::setShader(Shader* shader) {
-	if (this->shader) {
-		this->shader->release();
-		this->shader = NULL;
-	}
-
-	if (shader) {
-		this->shader = shader;
-		this->shader->retain();
-	}
-
-	return;
-}
-
-
 void SpriteNode::setSpriteFrame(SpriteFrame* sprite) {
 	if (this->sprite != sprite) {
 		if (this->sprite) {
 			rebuildVertexBuffer();
 		}
 
-		render_context->setShader(shader);
+		this->applyShaderConfigTo(render_context);
 		render_context->setModelviewMatrix(getWorldTransform());
 		render_context->prepareTextureLayers(1);
 		render_context->setTexture(0, texture);
 		}
 	}
 
-	if (shader == NULL) {
+	if (getShader() == NULL) {
 		setShader(Shaders::instance()->getShaderFor(vbo));
 	}
 

src/core/wiesel/graph/2d/sprite_node.h

 #include <wiesel/wiesel-core.def>
 
 #include "node2d.h"
+#include "wiesel/video/shader.h"
+#include "wiesel/video/shader_target.h"
 #include "wiesel/video/texture.h"
 #include "wiesel/video/vertexbuffer.h"
 #include "wiesel/geometry.h"
 	/**
 	 * @brief A Node for displaying a single sprite.
 	 */
-	class WIESEL_CORE_EXPORT SpriteNode : public Node2D
+	class WIESEL_CORE_EXPORT SpriteNode : public Node2D, public video::ShaderTarget
 	{
 	public:
 		/**
 		void setSpriteHitDetection(SpriteHitDetection hit);
 
 		/**
-		 * @brief Set the Shader to be used for rendering.
-		 */
-		void setShader(video::Shader *shader);
-
-		/**
 		 * @brief Set a new sprite frame for this node.
 		 */
 		void setSpriteFrame(SpriteFrame *sprite);
 		}
 
 		/**
-		 * @brief Get the currently used shader.
-		 */
-		inline video::Shader *getShader() {
-			return shader;
-		}
-
-		/**
 		 * @brief Get the current sprite frame (if any)
 		 */
 		inline SpriteFrame *getSpriteFrame() {
 		video::Texture*			texture;
 		rectangle				texture_rect;
 
-		video::Shader*			shader;
 		video::VertexBuffer*	vbo;
 		bool					vbo_dirty;
 	};

src/core/wiesel/video/render_context.h

 
 #include "wiesel/wiesel-core.def"
 #include "screen.h"
+#include "shader.h"
 #include "types.h"
 
 #include <wiesel/device.h>
 		virtual void setShader(Shader *shader) = 0;
 
 		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param type		The attribute's type.
+		 * @param elements	The number of elements within the parameter, to use an array of values.
+		 * @param pValue	Pointer to the value, which will be delivered to the shader.
+		 */
+		virtual void setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue) = 0;
+
+		/**
 		 * @brief Set a texture for a specific texture unit.
 		 * @param index		The index of the texture unit to set.
 		 *					Needs to be smaller than the texture unit maximum.

src/core/wiesel/video/shader.h

 			Texture,
 		};
 
+		/**
+		 * @brief A list of valid types for shader attributes.
+		 */
+		enum ValueType {
+			TypeInt32,
+
+			TypeFloat,
+
+			TypeVector2f,
+			TypeVector3f,
+			TypeVector4f,
+
+			TypeMatrix4x4f,
+		};
+
+
 		/// Alias type for an indiced list of attribute names
 		typedef std::vector<std::string>				AttributeNamesByIndex;
 
 		/// set the projection matrix for the current shader
 		virtual bool setProjectionMatrix(const matrix4x4 &matrix) = 0;
 
+		/// set a uniform shader value, see ShaderTarget::setShaderValue
+		virtual bool setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue) = 0;
+
 	private:
 		Shader*		shader;
 	};

src/core/wiesel/video/shader_target.cpp

+/**
+ * Copyright (C) 2012
+ * 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 <string.h>
+
+#include "shader_target.h"
+#include "render_context.h"
+
+using namespace wiesel;
+using namespace wiesel::video;
+
+
+ShaderTarget::ShaderTarget() {
+	this->shader		= NULL;
+}
+
+ShaderTarget::~ShaderTarget() {
+	for(ValueMap::iterator it=values.begin(); it!=values.end(); it++) {
+		delete it->second;
+	}
+
+	setShader(NULL);
+}
+
+
+void ShaderTarget::setShader(Shader* shader) {
+	if (this->shader != shader) {
+		if (this->shader) {
+			this->shader->release();
+			this->shader = NULL;
+		}
+
+		if (shader) {
+			this->shader = shader;
+			this->shader->retain();
+		}
+	}
+
+	return;
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, const void *pValue) {
+	ValueMap::iterator it = values.find(name);
+
+	// when the value already exists, but has a different type, we need to delete the old one
+	if (it != values.end()) {
+		if (it->second->match(type, elements) == false) {
+			delete it->second;
+			values.erase(it);
+			it = values.end();
+		}
+	}
+
+	// create a new element, if none exists
+	if (it == values.end()) {
+		it = values.insert(std::pair<std::string,entry*>(name, new entry(type, elements))).first;
+	}
+
+	assert(it != values.end());
+	assert(it->second->match(type, elements));
+
+	// now we can assign the value
+	it->second->set(pValue);
+
+	return;
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, int32_t i) {
+	setShaderValue(name, Shader::TypeInt32, 1, &i);
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, float f) {
+	setShaderValue(name, Shader::TypeFloat, 1, &f);
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, const vector2d &v) {
+	setShaderValue(name, Shader::TypeVector2f, 1, (const float*)v);
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, const vector3d &v) {
+	setShaderValue(name, Shader::TypeVector3f, 1, (const float*)v);
+}
+
+
+void ShaderTarget::setShaderValue(const std::string &name, const matrix4x4 &m) {
+	setShaderValue(name, Shader::TypeMatrix4x4f, 1, (const float*)m);
+}
+
+
+
+void ShaderTarget::applyShaderConfigTo(RenderContext* rc) {
+	rc->setShader(getShader());
+
+	for(ValueMap::iterator it=values.begin(); it!=values.end(); it++) {
+		rc->setShaderValue(it->first, it->second->type, it->second->elements, it->second->data);
+	}
+
+	return;
+}
+
+
+
+
+ShaderTarget::entry::entry() {
+	assert(false);
+}
+
+ShaderTarget::entry::entry(Shader::ValueType type, size_t elements) {
+	size_t value_size = 0;
+
+	switch(type) {
+		case Shader::TypeInt32: {
+			value_size = 4;
+			break;
+		}
+
+		case Shader::TypeFloat: {
+			value_size = 4;
+			break;
+		}
+
+		case Shader::TypeVector2f: {
+			value_size = 8;
+			break;
+		}
+
+		case Shader::TypeVector3f: {
+			value_size = 12;
+			break;
+		}
+
+		case Shader::TypeVector4f: {
+			value_size = 16;
+			break;
+		}
+
+		case Shader::TypeMatrix4x4f: {
+			value_size = 64;
+			break;
+		}
+	}
+
+	// ensure, our value type was valid
+	assert(value_size > 0);
+
+	this->type      = type;
+	this->elements  = elements;
+	this->data_size = value_size * elements;
+	this->data      = new char[data_size];
+
+	return;
+}
+
+
+ShaderTarget::entry::~entry() {
+	if (data) {
+		delete data;
+	}
+
+	return;
+}
+
+
+bool ShaderTarget::entry::match(Shader::ValueType type, size_t elements) {
+	return this->type==type && this->elements == elements;
+}
+
+
+void ShaderTarget::entry::set(const void *pValue) {
+	assert(data);
+	memcpy(data, pValue, data_size);
+
+	return;
+}

src/core/wiesel/video/shader_target.h

+/**
+ * Copyright (C) 2012
+ * 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_SHADER_TARGET_H__
+#define	__WIESEL_VIDEO_SHADER_TARGET_H__
+
+#include "wiesel/wiesel-core.def"
+
+#include <wiesel/util/shared_object.h>
+
+#include "shader.h"
+
+#include <string>
+
+
+namespace wiesel {
+namespace video {
+
+
+	class RenderContext;
+
+
+	/**
+	 * @brief This is the baseclass for any class which uses shaders.
+	 */
+	class WIESEL_CORE_EXPORT ShaderTarget : public virtual SharedObject
+	{
+	public:
+		ShaderTarget();
+		virtual ~ShaderTarget();
+
+	public:
+		/**
+		 * @brief Set the Shader to be used for rendering.
+		 */
+		void setShader(Shader *shader);
+
+		/**
+		 * @brief Get the currently used shader.
+		 */
+		inline Shader *getShader() {
+			return shader;
+		}
+
+
+	public:
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param type		The attribute's type.
+		 * @param elements	The number of elements within the parameter, to use an array of values.
+		 * @param pValue	Pointer to the value, which will be delivered to the shader.
+		 */
+		void setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, const void *pValue);
+
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param i			The integer value for the shader attribute.
+		 */
+		void setShaderValue(const std::string &name, int32_t i);
+
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param f			The float value for the shader attribute.
+		 */
+		void setShaderValue(const std::string &name, float f);
+
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param v			The vector value for the shader attribute.
+		 */
+		void setShaderValue(const std::string &name, const vector2d &v);
+
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param v			The vector value for the shader attribute.
+		 */
+		void setShaderValue(const std::string &name, const vector3d &v);
+
+		/**
+		 * @brief Set the uniform attribute for the current shader.
+		 * @param name		The unique name of the shader attribute.
+		 * @param m			The matrix value for the shader attribute.
+		 */
+		void setShaderValue(const std::string &name, const matrix4x4 &m);
+
+
+		/**
+		 * @brief Applies the stored shader attributes to the given \ref RenderContext.
+		 */
+		void applyShaderConfigTo(RenderContext *rc);
+
+	private:
+		struct entry
+		{
+		private:
+			entry();
+			
+		public:
+			entry(Shader::ValueType type, size_t elements);
+			~entry();
+			
+			bool match(Shader::ValueType type, size_t elements);
+			void set(const void *pValue);
+
+			Shader::ValueType	type;
+			size_t				elements;
+			size_t				data_size;
+			char*				data;
+		};
+
+	private:
+		typedef std::map<std::string,entry*> ValueMap;
+
+		Shader*		shader;
+		ValueMap	values;
+	};
+
+} /* namespace video */
+} /* namespace wiesel */
+#endif	/* __WIESEL_VIDEO_SHADER_TARGET_H__ */

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

 }
 
 
+void OpenGlRenderContext::setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue) {
+	if (active_shader_content) {
+		active_shader_content->setShaderValue(name, type, elements, pValue);
+	}
+
+	return;
+}
+
+
+
 void OpenGlRenderContext::setTexture(uint16_t index, Texture* texture) {
 	// check if the texture list is big enough.
 	// when this assert fails, there may be missing a prepareTextures call

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

 
 	public:
 		virtual void setShader(Shader *shader);
+		virtual void setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue);
 		virtual void setTexture(uint16_t index, Texture *texture);
 		virtual void prepareTextureLayers(uint16_t layers);
 		virtual void clearTextures();

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

 
 	return false;
 }
+
+
+bool GlShaderContent::setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue) {
+	std::map<std::string,GLint>::iterator it = uniform_attributes.find(name);
+
+	if (it != uniform_attributes.end() && it->second != -1) {
+		GLint attrib_handle = it->second;
+
+		switch(type) {
+			case Shader::TypeInt32: {
+				if (elements == 1) {
+					glUniform1i(attrib_handle, *(reinterpret_cast<GLint*>(pValue)));
+				}
+				else {
+					glUniform1iv(attrib_handle, elements, reinterpret_cast<GLint*>(pValue));
+				}
+
+				break;
+			}
+
+			case Shader::TypeFloat: {
+				if (elements == 1) {
+					glUniform1f(attrib_handle, *(reinterpret_cast<GLfloat*>(pValue)));
+				}
+				else {
+					glUniform1fv(attrib_handle, elements, reinterpret_cast<GLfloat*>(pValue));
+				}
+
+				break;
+			}
+
+			case Shader::TypeVector2f: {
+				glUniform2fv(attrib_handle, elements, reinterpret_cast<GLfloat*>(pValue));
+				break;
+			}
+
+			case Shader::TypeVector3f: {
+				glUniform3fv(attrib_handle, elements, reinterpret_cast<GLfloat*>(pValue));
+				break;
+			}
+
+			case Shader::TypeVector4f: {
+				glUniform4fv(attrib_handle, elements, reinterpret_cast<GLfloat*>(pValue));
+				break;
+			}
+
+			case Shader::TypeMatrix4x4f: {
+				glUniformMatrix4fv(attrib_handle, elements, false, reinterpret_cast<GLfloat*>(pValue));
+				break;
+			}
+		}
+
+		CHECK_GL_ERROR;
+
+		return true;
+	}
+
+	return false;
+}
+

src/opengl/wiesel/video/gl/gl_shader_content.h

 		/// set the modelview matrix
 		virtual bool setModelviewMatrix(const matrix4x4 &matrix);
 
-#if 0
-	private:
-		/**
-		 * @brief bind all attributes configured in the shaders.
-		 */
-		void bindAttributes();
+		/// set a uniform shader value, see ShaderTarget::setShaderValue
+		virtual bool setShaderValue(const std::string &name, Shader::ValueType type, size_t elements, void *pValue);
 
-		/**
-		 * @brief get the OpenGL handle to a specific uniform parameter.
-		 */
-		GLint getUniformHandle(const std::string &name) const;
-
-		/**
-		 * @brief release the shader.
-		 */
-		void release_shader();
-
-	// private members
-	private:
-		std::vector<Shader*>	shaders;
-		GLuint					program;
-		bool					need_link;
-
-		GLint					uniform_handle_projection_matrix;
-		GLint					uniform_handle_modelview_matrix;
-		GLint					attrib_handle_vertex_position;
-		GLint					attrib_handle_vertex_normal;
-		GLint					attrib_handle_vertex_color;
-		std::vector<GLint>		attrib_handle_vertex_texcoords;
-		std::vector<GLint>		attrib_handle_vertex_textures;
-
-		std::map<std::string,GLint>	uniform_attributes;
-#endif
 	private:
 		/// Alias type for an indiced list of attribute names
 		typedef std::vector<GLint>						AttributeHandlesByIndex;