[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32615] branches/soc-2010-moguri-2/source: Custom GLSL Uniform per object

Dalai Felinto dfelinto at gmail.com
Wed Oct 20 21:38:04 CEST 2010


Revision: 32615
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32615
Author:   dfelinto
Date:     2010-10-20 21:38:04 +0200 (Wed, 20 Oct 2010)

Log Message:
-----------
Custom GLSL Uniform per object

This patch allows one to control shaders in the material level (as alread supported) and in object level.
For example, you can have 10 objects sharing the same mesh/material/shader. If you want to change the uniform for one of them you simply need to add the uniform for the object (obj.addUniform). Any uniform stored in the object will be binded (sent to the graphic card) after the ones from the material. That way they "overwrite" those specific uniforms (names must match) while still uses the rest of properties from the material.

* code-note:
In order to implement that I had to (1) create a ListBase in the object (2) pass a pointer for this ListBase for the MeshSlot.

* I put together two sample files:
http://blenderecia.orgfree.com/blender/obj_uniform_simple_sample.blend (simple sample, just to show the API and what can be done)
http://blenderecia.orgfree.com/blender/obj_uniform_hue_sample.blend (more advanced, illustrating a bit the kind of application this can have)

** Note:
Although GLSL custom shaders are not so popular (give its complexity) this is the kind of funcionality that anyone using custom (or built-in) shaders may need one day. So it's nice to finally support it (in the branch at least).

Modified Paths:
--------------
    branches/soc-2010-moguri-2/source/blender/gpu/GPU_material.h
    branches/soc-2010-moguri-2/source/blender/gpu/intern/gpu_material.c
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/BL_BlenderShader.cpp
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.cpp
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.h
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonSeq.cpp
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonSeq.h
    branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonShaders.cpp
    branches/soc-2010-moguri-2/source/gameengine/Rasterizer/CMakeLists.txt
    branches/soc-2010-moguri-2/source/gameengine/Rasterizer/Makefile
    branches/soc-2010-moguri-2/source/gameengine/Rasterizer/RAS_MaterialBucket.h
    branches/soc-2010-moguri-2/source/gameengine/Rasterizer/SConscript

Modified: branches/soc-2010-moguri-2/source/blender/gpu/GPU_material.h
===================================================================
--- branches/soc-2010-moguri-2/source/blender/gpu/GPU_material.h	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/blender/gpu/GPU_material.h	2010-10-20 19:38:04 UTC (rev 32615)
@@ -126,6 +126,7 @@
 
 void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap);
 void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]);
+void GPU_material_bind_custom_uniforms(GPUMaterial *material, struct ListBase *uniforms);
 void GPU_material_unbind(GPUMaterial *material);
 void GPU_material_unbind_uniforms(GPUMaterial *material);
 int GPU_material_bound(GPUMaterial *material);

Modified: branches/soc-2010-moguri-2/source/blender/gpu/intern/gpu_material.c
===================================================================
--- branches/soc-2010-moguri-2/source/blender/gpu/intern/gpu_material.c	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/blender/gpu/intern/gpu_material.c	2010-10-20 19:38:04 UTC (rev 32615)
@@ -378,7 +378,6 @@
 {
 	if(material->pass) {
 		GPUShader *shader = GPU_pass_shader(material->pass);
-		CustomUniform *cu;
 		int loc, i;
 		PointerRNA ma_ptr;
 		LinkData *nlink;
@@ -406,45 +405,8 @@
 		}
 
 		/* handle custom uniforms */
-		for(cu=material->ma->csi.uniforms.first; cu; cu=cu->next) {
-			loc = GPU_shader_get_uniform(shader, cu->name);
+		GPU_material_bind_custom_uniforms(material, &material->ma->csi.uniforms);
 
-			// If the uniform wasn't found, go on to the next one
-			if (loc < 0)
-				continue;
-
-			if(cu->type >= MA_UNF_FLOAT && cu->type <= MA_UNF_VEC4)
-			{
-				if (cu->size > 1)
-					GPU_shader_uniform_vector(shader, loc, cu->size, 1, (float*)(cu->data));
-				else
-					GPU_shader_uniform_vector(shader, loc, 1, 1, (float*)(&cu->data));
-			}
-			else if(cu->type == MA_UNF_INT)
-			{
-				if (cu->size > 1)
-					GPU_shader_uniform_ivector(shader, loc, cu->size, 1, (int*)(cu->data));
-				else
-					GPU_shader_uniform_ivector(shader, loc, 1, 1, (int*)(&cu->data));
-			}
-			else if(cu->type == MA_UNF_SAMPLER2D)
-			{
-				Tex *tex;
-				GPUTexture *gtex;
-
-				tex = (Tex*)cu->data;
-				if (tex)
-				{
-					gtex = GPU_texture_from_blender(tex->ima, &tex->iuser, 1.0, 0);
-					if (gtex)
-					{
-						GPU_texture_bind(gtex, 3);
-						GPU_shader_uniform_texture(shader, loc, gtex);
-					}
-				}
-			}
-		}
-
 		/* handle rna uniforms */
 		RNA_pointer_create((ID*)material->ma, &RNA_Material, material->ma, &ma_ptr);
 
@@ -501,6 +463,55 @@
 	}
 }
 
+void GPU_material_bind_custom_uniforms(GPUMaterial *material, ListBase *uniforms)
+{
+	if(material->pass && (*uniforms).first) {
+		GPUShader *shader = GPU_pass_shader(material->pass);
+		CustomUniform *cu;
+		int loc;
+
+		/* handle custom uniforms */
+		for(cu=(*uniforms).first; cu; cu=cu->next) {
+			loc = GPU_shader_get_uniform(shader, cu->name);
+
+			// If the uniform wasn't found, go on to the next one
+			if (loc < 0)
+				continue;
+
+			if(cu->type >= MA_UNF_FLOAT && cu->type <= MA_UNF_VEC4)
+			{
+				if (cu->size > 1)
+					GPU_shader_uniform_vector(shader, loc, cu->size, 1, (float*)(cu->data));
+				else
+					GPU_shader_uniform_vector(shader, loc, 1, 1, (float*)(&cu->data));
+			}
+			else if(cu->type == MA_UNF_INT)
+			{
+				if (cu->size > 1)
+					GPU_shader_uniform_ivector(shader, loc, cu->size, 1, (int*)(cu->data));
+				else
+					GPU_shader_uniform_ivector(shader, loc, 1, 1, (int*)(&cu->data));
+			}
+			else if(cu->type == MA_UNF_SAMPLER2D)
+			{
+				Tex *tex;
+				GPUTexture *gtex;
+
+				tex = (Tex*)cu->data;
+				if (tex)
+				{
+					gtex = GPU_texture_from_blender(tex->ima, &tex->iuser, 1.0, 0);
+					if (gtex)
+					{
+						GPU_texture_bind(gtex, 3);
+						GPU_shader_uniform_texture(shader, loc, gtex);
+					}
+				}
+			}
+		}
+	}
+}
+
 void GPU_material_unbind(GPUMaterial *material)
 {
 	if (material->pass) {

Modified: branches/soc-2010-moguri-2/source/gameengine/Ketsji/BL_BlenderShader.cpp
===================================================================
--- branches/soc-2010-moguri-2/source/gameengine/Ketsji/BL_BlenderShader.cpp	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/gameengine/Ketsji/BL_BlenderShader.cpp	2010-10-20 19:38:04 UTC (rev 32615)
@@ -235,6 +235,7 @@
 		obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f;
 
 	GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol);
+	GPU_material_bind_custom_uniforms(gpumat, ms.uniforms);
 
 	mBlendMode = GPU_material_blend_mode(gpumat, obcol);
 }

Modified: branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.cpp
===================================================================
--- branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.cpp	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.cpp	2010-10-20 19:38:04 UTC (rev 32615)
@@ -76,6 +76,7 @@
 #include "KX_SG_NodeRelationships.h"
 
 #include "BLI_math.h"
+#include "BLI_listbase.h"
 
 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
@@ -115,6 +116,10 @@
 	KX_NormalParentRelation * parent_relation = 
 		KX_NormalParentRelation::New();
 	m_pSGNode->SetParentRelation(parent_relation);
+
+	// make sure the list is NULL
+	uniforms.first = NULL;
+	uniforms.last = NULL;
 };
 
 
@@ -154,6 +159,10 @@
 		Py_DECREF(m_attr_dict);
 	}
 #endif // DISABLE_PYTHON
+
+	//cleaning the uniform list
+	m_uniforms.clear();
+
 }
 
 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
@@ -529,6 +538,7 @@
 		{
 			ms = *mit;
 			ms->m_bObjectColor = m_bUseObjectColor;
+			ms->uniforms = &this->uniforms;
 			ms->m_RGBAcolor = m_objectColor;
 			ms->m_bVisible = m_bVisible;
 			ms->m_bCulled = m_bCulled || !m_bVisible;
@@ -1486,6 +1496,7 @@
 	KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
 	KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
 	KX_PYMETHODTABLE(KX_GameObject, sendMessage),
+	KX_PYMETHODTABLE_O(KX_GameObject, addUniform),
 	
 	// dict style access for props
 	{"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
@@ -1525,6 +1536,7 @@
 	KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive",	KX_GameObject, pyattr_get_children_recursive),
 	KX_PYATTRIBUTE_RO_FUNCTION("attrDict",	KX_GameObject, pyattr_get_attrDict),
 	KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor),
+	KX_PYATTRIBUTE_RO_FUNCTION("uniforms", KX_GameObject, pyattr_get_uniforms),
 	
 	/* Experemental, dont rely on these yet */
 	KX_PYATTRIBUTE_RO_FUNCTION("sensors",		KX_GameObject, pyattr_get_sensors),
@@ -1533,6 +1545,28 @@
 	{NULL} //Sentinel
 };
 
+KX_PYMETHODDEF_DOC_O(KX_GameObject, addUniform,
+	"addUniform(uniform) -- Adds the uniform to the shader's uniform list")
+{
+	if (!PyType_IsSubtype(&KX_PythonUniform::Type, Py_TYPE(value)))
+		return NULL;
+
+	KX_PythonUniform *uniform = static_cast<KX_PythonUniform*>BGE_PROXY_REF(value);
+
+
+	BLI_addhead(&(this->uniforms), uniform->GetCustomUniform());
+	m_uniforms.push_back(uniform);
+
+	Py_RETURN_NONE;
+}
+
+PyObject* KX_GameObject::pyattr_get_uniforms(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+	return KX_PythonSeq_CreatePyObject(self->m_proxy, KX_PYGENSEQ_OB_TYPE_UNIFORMS);
+
+}
+
 PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
 {
 	KX_Scene *scene = KX_GetActiveScene();

Modified: branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.h
===================================================================
--- branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.h	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_GameObject.h	2010-10-20 19:38:04 UTC (rev 32615)
@@ -49,6 +49,7 @@
 #include "KX_IPhysicsController.h" /* for suspend/resume */
 #include "DNA_object_types.h"
 #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */
+#include "KX_PythonShaders.h" /* for custom uniforms */
 #define KX_OB_DYNAMIC 1
 
 //Forward declarations.
@@ -107,10 +108,19 @@
 	SG_Node*							m_pSGNode;
 
 	MT_CmMatrix4x4						m_OpenGL_4x4Matrix;
+
+	ListBase uniforms; // for custom shaders
+	UniformList m_uniforms;
 	
 public:
 	bool								m_isDeformable;
 
+	UniformList& GetUniforms() {
+		return m_uniforms; }
+
+	KX_PYMETHOD_DOC_O(KX_GameObject, addUniform);
+	static PyObject*	pyattr_get_uniforms(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+
 	/**
 	 * Helper function for modules that can't include KX_ClientObjectInfo.h
 	 */

Modified: branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonSeq.cpp
===================================================================
--- branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonSeq.cpp	2010-10-20 13:51:37 UTC (rev 32614)
+++ branches/soc-2010-moguri-2/source/gameengine/Ketsji/KX_PythonSeq.cpp	2010-10-20 19:38:04 UTC (rev 32615)
@@ -81,6 +81,8 @@
 		return ((BL_ArmatureObject *)self_plus)->GetChannelNumber();
 	case KX_PYGENSEQ_SHADER_TYPE_UNIFORMS:
 		return ((KX_PythonShader *)self_plus)->GetUniforms().size();
+	case KX_PYGENSEQ_OB_TYPE_UNIFORMS:
+		return ((KX_GameObject *)self_plus)->GetUniforms().size();
 	default:
 		/* Should never happen */
 		PyErr_SetString(PyExc_SystemError, "invalid type, internal error");
@@ -182,6 +184,18 @@
 
 			return uniforms[index]->GetProxy();
 		}
+		case KX_PYGENSEQ_OB_TYPE_UNIFORMS:
+		{
+			UniformList& uniforms= ((KX_GameObject *)self_plus)->GetUniforms();
+
+			if (index<0) index += uniforms.size();
+			if (index<0 || index>= uniforms.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+
+			return uniforms[index]->GetProxy();
+		}
 	}
 	
 	PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug");
@@ -260,6 +274,17 @@
 			}
 			break;
 		}
+		case KX_PYGENSEQ_OB_TYPE_UNIFORMS:
+		{
+			UniformList& uniforms= ((KX_GameObject *)self_plus)->GetUniforms();
+			KX_PythonUniform *uniform;
+			for (unsigned int index=0;index<uniforms.size();index++) {
+				uniform= uniforms[index];
+				if (uniform->GetName() == key)
+					return static_cast<PyObjectPlus *>(uniform);
+			}
+			break;
+		}
 		case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS:
 		{
 			return ((BL_ArmatureObject*)self_plus)->GetConstraint(key);


@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list