Commits

Leonard Ritter committed 7e74a8c Merge

merged trunk

  • Participants
  • Parent commits d0373cf, bbd7305

Comments (0)

Files changed (17)

File blender/release/scripts/startup/bl_ui/properties_material.py

         row.prop(game, "use_backface_culling")
         row.prop(game, "invisible")
         row.prop(game, "text")
+        row.prop(game, "cutout")
 
         row = layout.row()
         row.label(text="Alpha Blend:")

File blender/source/blender/makesdna/DNA_material_types.h

 // Use Textures - not defined directly in the UI
 #define GEMAT_TEX		4096 /* KX_TEX */
 
+// Render to Z-buffer only
+#define GEMAT_CUTOUT    8192
+
 
 /* **************** MATERIAL ********************* */
 

File blender/source/blender/makesrna/intern/rna_material.c

 	RNA_def_property_ui_text(prop, "Backface Culling", "Hide Back of the face in Game Engine ");
 	RNA_def_property_update(prop, 0, "rna_Material_draw_update");
 
+	prop = RNA_def_property(srna, "cutout", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", GEMAT_CUTOUT); /* use bitflags */
+	RNA_def_property_ui_text(prop, "Cutout", "Only render to Z-Buffer in Game Engine");
+	RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
 	prop = RNA_def_property(srna, "text", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", GEMAT_TEXT); /* use bitflags */
 	RNA_def_property_ui_text(prop, "Text", "Use material as text in Game Engine ");

File blender/source/gameengine/Converter/BL_BlenderDataConversion.cpp

 		// use lighting?
 		material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT;
 		material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED;
+		material->ras_mode |= ( mat->game.flag & GEMAT_CUTOUT )?ZMASK:0;
 
 		// cast shadows?
 		material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0;
 				// only zsort alpha + add
 				bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT);
 				bool zsort = (alpha_blend == GEMAT_ALPHA_SORT);
+				bool zmask = (ma)?((ma->game.flag & GEMAT_CUTOUT)!=0):false;
 				bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode;
 
 				// don't need zort anymore, deal as if it it's alpha blend
 					kx_polymat = new KX_PolygonMaterial();
 				kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
 					tile, tilexrep, tileyrep, 
-					alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol);
+					alpha_blend, alpha, zsort, zmask, light, lightlayer, tface, (unsigned int*)mcol);
 				polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
 	
 				if (ma) {

File blender/source/gameengine/Ketsji/BL_Material.h

 	WIRE=64,
 	CAST_SHADOW=128,
 	TEX=256,
-	TWOSIDED=512
+	TWOSIDED=512,
+	ZMASK=1024
 };
 
 // -------------------------------------

File blender/source/gameengine/Ketsji/KX_BlenderMaterial.cpp

 		data->alphablend,
 		((data->ras_mode &ALPHA)!=0),
 		((data->ras_mode &ZSORT)!=0),
+		((data->ras_mode &ZMASK)!=0),
 		((data->ras_mode &USE_LIGHT)!=0),
 		((data->ras_mode &TEX)),
 		game
 		else
 			tmp->setShaderData(false, rasty);
 
+		if (mMaterial->ras_mode &ZMASK)
+			rasty->SetColorMask(false);
+		else
+			rasty->SetColorMask(true);
+
 		if (mMaterial->ras_mode &TWOSIDED)
 			rasty->SetCullFace(false);
 		else
 		else
 			tmp->setBlenderShaderData(false, rasty);
 
+		if (mMaterial->ras_mode &ZMASK)
+			rasty->SetColorMask(false);
+		else
+			rasty->SetColorMask(true);
+
 		if (mMaterial->ras_mode &TWOSIDED)
 			rasty->SetCullFace(false);
 		else
 		else
 			tmp->setTexData( false,rasty);
 
+		if (mMaterial->ras_mode &ZMASK)
+			rasty->SetColorMask(false);
+		else
+			rasty->SetColorMask(true);
+
 		if (mMaterial->ras_mode &TWOSIDED)
 			rasty->SetCullFace(false);
 		else

File blender/source/gameengine/Ketsji/KX_PolygonMaterial.cpp

 		int alphablend,
 		bool alpha,
 		bool zsort,
+		bool zmask,
 		bool light,
 		int lightlayer,
 		struct MTFace* tface,
 							alphablend,
 							alpha,
 							zsort,
+							zmask,
 							light,
 							(texname && texname != ""?true:false), /* if we have a texture we have image */
 							ma?&ma->game:NULL);

File blender/source/gameengine/Ketsji/KX_PolygonMaterial.h

 		int alphablend,
 		bool alpha,
 		bool zsort,
+		bool zmask,
 		bool light,
 		int lightlayer,
 		struct MTFace* tface,

File blender/source/gameengine/Rasterizer/RAS_BucketManager.cpp

 {
 	BucketList::iterator it;
 
-	for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++)
-		delete (*it);
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
 
-	for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++)
-		delete(*it);
-	
-	m_SolidBuckets.clear();
-	m_AlphaBuckets.clear();
+		for (it = m_Buckets[listidx].begin(); it != m_Buckets[listidx].end(); it++)
+			delete (*it);
+		m_Buckets[listidx].clear();
+
+	}
 }
 
 void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha)
 	// disable it.
 	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
 
-	OrderBuckets(cameratrans, m_AlphaBuckets, slots, true);
+	OrderBuckets(cameratrans, m_Buckets[ALPHA_LIST], slots, true);
 	
 	for (sit=slots.begin(); sit!=slots.end(); ++sit) {
 		rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj);
 	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
 }
 
-void RAS_BucketManager::RenderSolidBuckets(
-	const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
+void RAS_BucketManager::RenderCutoutBuckets(const MT_Transform& cameratrans,
+	RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
 {
 	BucketList::iterator bit;
 
 	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
 
-	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
-#if 1
+	for (bit = m_Buckets[CUTOUT_LIST].begin(); bit != m_Buckets[CUTOUT_LIST].end(); ++bit) {
 		RAS_MaterialBucket* bucket = *bit;
 		RAS_MeshSlot* ms;
 		// remove the mesh slot form the list, it culls them automatically for next frame
 			// it will be culled out by frustrum culling
 			ms->SetCulled(true);
 		}
-#else
-		list<RAS_MeshSlot>::iterator mit;
-		for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
-			if (mit->IsCulled())
-				continue;
+	}
+}
 
-			rendertools->SetClientObject(rasty, mit->m_clientObj);
+void RAS_BucketManager::RenderSolidBuckets(
+	const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
+{
+	BucketList::iterator bit;
 
-			while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools))
-				(*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit);
+	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+
+	for (bit = m_Buckets[SOLID_LIST].begin(); bit != m_Buckets[SOLID_LIST].end(); ++bit) {
+		RAS_MaterialBucket* bucket = *bit;
+		RAS_MeshSlot* ms;
+		// remove the mesh slot form the list, it culls them automatically for next frame
+		while((ms = bucket->GetNextActiveMeshSlot()))
+		{
+			rendertools->SetClientObject(rasty, ms->m_clientObj);
+			while (bucket->ActivateMaterial(cameratrans, rasty, rendertools))
+				bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms);
 
 			// make this mesh slot culled automatically for next frame
 			// it will be culled out by frustrum culling
-			mit->SetCulled(true);
+			ms->SetCulled(true);
 		}
-#endif
 	}
-	
-	/* this code draws meshes order front-to-back instead to reduce overdraw.
-	 * it turned out slower due to much material state switching, a more clever
-	 * algorithm might do better. */
-#if 0
-	vector<sortedmeshslot> slots;
-	vector<sortedmeshslot>::iterator sit;
-
-	OrderBuckets(cameratrans, m_SolidBuckets, slots, false);
-
-	for (sit=slots.begin(); sit!=slots.end(); ++sit) {
-		rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj);
-
-		while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
-			sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
-	}
-#endif
 }
 
 void RAS_BucketManager::Renderbuckets(
 	/* beginning each frame, clear (texture/material) caching information */
 	rasty->ClearCachingInfo();
 
+	RenderCutoutBuckets(cameratrans, rasty, rendertools);
 	RenderSolidBuckets(cameratrans, rasty, rendertools);	
 	RenderAlphaBuckets(cameratrans, rasty, rendertools);	
 
 
 	bucketCreated = false;
 
-	for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++)
-		if (*(*it)->GetPolyMaterial() == *material)
-			return *it;
-	
-	for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++)
-		if (*(*it)->GetPolyMaterial() == *material)
-			return *it;
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		for (it = m_Buckets[listidx].begin(); it != m_Buckets[listidx].end(); it++)
+			if (*(*it)->GetPolyMaterial() == *material)
+				return *it;
+	}
 	
 	RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material);
 	bucketCreated = true;
 
+	BucketListType targetBucket;
 	if (bucket->IsAlpha())
-		m_AlphaBuckets.push_back(bucket);
+		targetBucket = ALPHA_LIST;
+	else if (bucket->IsZMask())
+		targetBucket = CUTOUT_LIST;
 	else
-		m_SolidBuckets.push_back(bucket);
+		targetBucket = SOLID_LIST;
+	m_Buckets[targetBucket].push_back(bucket);
 	
 	return bucket;
 }
 	
 	distance = 10.0;
 
-	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit)
-		(*bit)->Optimize(distance);
-	for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit)
-		(*bit)->Optimize(distance);
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		for (bit = m_Buckets[listidx].begin(); bit != m_Buckets[listidx].end(); ++bit)
+			(*bit)->Optimize(distance);
+	}
 }
 
 void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat)
 	BucketList::iterator bit;
 	list<RAS_MeshSlot>::iterator mit;
 
-	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
-		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
-			for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
-				if (mit->m_DisplayList) {
-					mit->m_DisplayList->Release();
-					mit->m_DisplayList = NULL;
-				}
-			}
-		}
-	}
-	
-	for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
-		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
-			for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
-				if (mit->m_DisplayList) {
-					mit->m_DisplayList->Release();
-					mit->m_DisplayList = NULL;
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		for (bit = m_Buckets[listidx].begin(); bit != m_Buckets[listidx].end(); ++bit) {
+			if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+				for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+					if (mit->m_DisplayList) {
+						mit->m_DisplayList->Release();
+						mit->m_DisplayList = NULL;
+					}
 				}
 			}
 		}
 	BucketList::iterator bit;
 	list<RAS_MeshSlot>::iterator mit;
 
-	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
-		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
-			(*bit)->GetPolyMaterial()->ReleaseMaterial();
-		}
-	}
-	
-	for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
-		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
-			(*bit)->GetPolyMaterial()->ReleaseMaterial();
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		for (bit = m_Buckets[listidx].begin(); bit != m_Buckets[listidx].end(); ++bit) {
+			if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+				(*bit)->GetPolyMaterial()->ReleaseMaterial();
+			}
 		}
 	}
 }
 	list<RAS_MeshSlot>::iterator mit;
 	int i;
 
-
-	for (i=0; i<m_SolidBuckets.size(); i++) {
-		RAS_MaterialBucket *bucket = m_SolidBuckets[i];
-		if (mat == bucket->GetPolyMaterial()) {
-			m_SolidBuckets.erase(m_SolidBuckets.begin()+i);
-			delete bucket;
-			i--;
-		}
-	}
-
-	for (int i=0; i<m_AlphaBuckets.size(); i++) {
-		RAS_MaterialBucket *bucket = m_AlphaBuckets[i];
-		if (mat == bucket->GetPolyMaterial()) {
-			m_AlphaBuckets.erase(m_AlphaBuckets.begin()+i);
-			delete bucket;
-			i--;
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		for (i=0; i<m_Buckets[listidx].size(); i++) {
+			RAS_MaterialBucket *bucket = m_Buckets[listidx][i];
+			if (mat == bucket->GetPolyMaterial()) {
+				m_Buckets[listidx].erase(m_Buckets[listidx].begin()+i);
+				delete bucket;
+				i--;
+			}
 		}
 	}
 }
 	// printf("BEFORE %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
 	BucketList::iterator it;
 
-	for (it = other->GetSolidBuckets().begin(); it != other->GetSolidBuckets().end(); ++it)
-		(*it)->GetPolyMaterial()->Replace_IScene(scene);
+	for (int listidx = 0; listidx < LIST_MAX; ++listidx) {
+		BucketListType type = (BucketListType)listidx;
 
-	GetSolidBuckets().insert( GetSolidBuckets().end(), other->GetSolidBuckets().begin(), other->GetSolidBuckets().end() );
-	other->GetSolidBuckets().clear();
+		for (it = other->GetBuckets(type).begin(); it != other->GetBuckets(type).end(); ++it)
+			(*it)->GetPolyMaterial()->Replace_IScene(scene);
 
-	for (it = other->GetAlphaBuckets().begin(); it != other->GetAlphaBuckets().end(); ++it)
-		(*it)->GetPolyMaterial()->Replace_IScene(scene);
-
-	GetAlphaBuckets().insert( GetAlphaBuckets().end(), other->GetAlphaBuckets().begin(), other->GetAlphaBuckets().end() );
-	other->GetAlphaBuckets().clear();
+		GetBuckets(type).insert( GetBuckets(type).end(), other->GetBuckets(type).begin(), other->GetBuckets(type).end() );
+		other->GetBuckets(type).clear();
+	}
 	//printf("AFTER %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
 }
 

File blender/source/gameengine/Rasterizer/RAS_BucketManager.h

 
 class RAS_BucketManager
 {
+	enum BucketListType {
+		CUTOUT_LIST = 0,
+		SOLID_LIST = 1,
+		ALPHA_LIST = 2,
+		LIST_MAX,
+	};
+
 	typedef std::vector<class RAS_MaterialBucket*> BucketList;
-	BucketList m_SolidBuckets;
-	BucketList m_AlphaBuckets;
 	
+	BucketList m_Buckets[LIST_MAX];
+
 	struct sortedmeshslot;
 	struct backtofront;
 	struct fronttoback;
 
 	/* for merging */
 	void MergeBucketManager(RAS_BucketManager *other, SCA_IScene *scene);
-	BucketList & GetSolidBuckets() {return m_SolidBuckets;}
-	BucketList & GetAlphaBuckets() {return m_AlphaBuckets;}
+	BucketList & GetCutoutBuckets() {return m_Buckets[CUTOUT_LIST];}
+	BucketList & GetSolidBuckets() {return m_Buckets[SOLID_LIST];}
+	BucketList & GetAlphaBuckets() {return m_Buckets[ALPHA_LIST];}
+	BucketList & GetBuckets(BucketListType type) {return m_Buckets[type];}
 
 	/*void PrintStats(int verbose_level) {
 		printf("\nMappings...\n");
 private:
 	void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha);
 
+	void RenderCutoutBuckets(const MT_Transform& cameratrans,
+		RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
 	void RenderSolidBuckets(const MT_Transform& cameratrans, 
 		RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
 	void RenderAlphaBuckets(const MT_Transform& cameratrans, 

File blender/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp

 				int alphablend,
 				bool alpha,
 				bool zsort,
+				bool zmask,
 				bool light,
 				bool image,
 				struct GameSettings* game)
 	m_alphablend = alphablend;
 	m_alpha = alpha;
 	m_zsort = zsort;
+	m_zmask = zmask;
 	m_light = light;
 	m_polymatid = m_newpolymatid++;
 	m_flag = 0;
 		m_alphablend(0),
 		m_alpha(false),
 		m_zsort(false),
+		m_zmask(false),
 		m_light(false),
 		m_materialindex(0),
 		m_polymatid(0),
 									 int tileyrep,
 									 int alphablend,
 									 bool alpha,
-									 bool zsort)
+									 bool zsort,
+									 bool zmask)
 		: m_texturename(texname),
 		m_materialname(matname),
 		m_tile(tile),
 		m_alphablend(alphablend),
 		m_alpha(alpha),
 		m_zsort(zsort),
+		m_zmask(zmask),
 		m_materialindex(materialindex),
 		m_polymatid(m_newpolymatid++),
 		m_flag(0),
 				this->m_alphablend	==		lhs.m_alphablend &&
 				this->m_alpha		==		lhs.m_alpha &&
 				this->m_zsort		==		lhs.m_zsort &&
+				this->m_zmask		==		lhs.m_zmask &&
 				this->m_light		==		lhs.m_light &&
 				this->m_drawingmode	==		lhs.m_drawingmode &&
 				this->m_texturename.hash()	==		lhs.m_texturename.hash() &&
 	return m_zsort;
 }
 
+bool RAS_IPolyMaterial::IsZMask() const
+{
+	return m_zmask;
+}
+
 unsigned int RAS_IPolyMaterial::hash() const
 {
 	return m_texturename.hash();

File blender/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h

 	int						m_alphablend;
 	bool					m_alpha;
 	bool					m_zsort;
+	bool					m_zmask;
 	bool					m_light;
 	int						m_materialindex;
 	
 					  int tileyrep,
 					  int transp,
 					  bool alpha,
-					  bool zsort);
+					  bool zsort,
+					  bool zmask);
 	void Initialize(const STR_String& texname,
 					const STR_String& matname,
 					int materialindex,
 					int transp,
 					bool alpha,
 					bool zsort,
+					bool zmask,
 					bool light,
 					bool image,
 					struct GameSettings* game);
 	//int					GetLightLayer() const;
 	bool				IsAlpha() const;
 	bool				IsZSort() const;
+	bool 				IsZMask() const;
 	unsigned int		hash() const;
 	int					GetDrawingMode() const;
 	const STR_String&	GetMaterialName() const;

File blender/source/gameengine/Rasterizer/RAS_IRasterizer.h

 	 * Sets wireframe mode.
 	 */
 	virtual void    SetLines(bool enable)=0;
+
+	/**
+	 * Disables writing to framebuffer colors
+	 */
+	virtual void SetColorMask(bool enable)=0;
 	/**
 	 */
 	virtual double	GetTime()=0;

File blender/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp

 	return m_material;
 }
 
+bool RAS_MaterialBucket::IsZMask() const
+{
+	return (m_material->IsZMask());
+}
+
 bool RAS_MaterialBucket::IsAlpha() const
 {	
 	return (m_material->IsAlpha());

File blender/source/gameengine/Rasterizer/RAS_MaterialBucket.h

 	RAS_IPolyMaterial*		GetPolyMaterial() const;
 	bool					IsAlpha() const;
 	bool					IsZSort() const;
+	bool					IsZMask() const;
 		
 	/* Rendering */
 	bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,

File blender/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp

 	return m_camortho;
 }
 
+void RAS_OpenGLRasterizer::SetColorMask(bool enable)
+{
+	if (enable)
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	else
+		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+}
+
 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
 {
 	if (enable)

File blender/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h

 
 	virtual void	SetCullFace(bool enable);
 	virtual void	SetLines(bool enable);
+	virtual void    SetColorMask(bool enable);
 
 	virtual MT_Matrix4x4 GetFrustumMatrix(
 							float left,