瀏覽代碼

SceneMeshes now keep their own list of ShaderPasses, which are applied as options to materials but can provide additional render passes independent of the material, added support for global override materials in the new renderer, added wireframe support to renderer (non-ES2, will be ifdefed out in strict ES2 builds), readded wireframe overlay support as a separate shader pass, readded wireframe mode support in entity editor, added an lineSmooth option to GL renderer (non-ES2 as well)

Ivan Safrin 10 年之前
父節點
當前提交
a2134331c8

二進制
assets/default/default.pak


+ 9 - 0
assets/default/default/UnlitWireframe.frag

@@ -0,0 +1,9 @@
+#ifdef GLES2
+	precision mediump float;
+#endif
+
+uniform vec4 wireframeColor;
+
+void main() {
+	gl_FragColor = wireframeColor;
+}

+ 10 - 6
assets/default/default/default.mat

@@ -8,20 +8,24 @@
 		<shader type="glsl" name="UnlitUntextured" numPointLights="0" numSpotLights="0">		
 			<vp source="default/UnlitUntextured.vert"/>
 			<fp source="default/UnlitUntextured.frag"/>
-		</shader>		
+		</shader>
+		<shader type="glsl" name="UnlitWireframe" numPointLights="0" numSpotLights="0">		
+			<vp source="default/UnlitUntextured.vert"/>
+			<fp source="default/UnlitWireframe.frag"/>
+		</shader>	
 	</shaders>	
 	<materials>	
 		<material name="Unlit">
 			<shader name="Unlit">
-				<textures>
-				</textures>				
 			</shader>
 		</material>
 		<material name="UnlitUntextured">
 			<shader name="UnlitUntextured">
-				<textures>
-				</textures>				
 			</shader>
-		</material>		
+		</material>	
+		<material name="UnlitWireframe">
+			<shader name="UnlitWireframe" wireframe="true">
+			</shader>
+		</material>				
 	</materials>
 </polycode>

+ 3 - 1
include/polycode/core/PolyGPUDrawBuffer.h

@@ -38,6 +38,7 @@ namespace Polycode {
         bool alphaTest;
         bool backfaceCull;
         bool depthOnly;
+        bool forceMaterial;
         unsigned int blendingMode;
         Polycode::Rectangle scissorBox;
         bool enableScissor;
@@ -54,7 +55,7 @@ namespace Polycode {
         GPUDrawOptions options;
         Matrix4 modelMatrix;
         Material *material;
-        ShaderBinding *shaderBinding;
+        std::vector<ShaderPass> shaderPasses;
         IndexDataArray *indexArray;
     };
     
@@ -71,6 +72,7 @@ namespace Polycode {
         bool clearDepthBuffer;
         bool clearColorBuffer;
         Vector2 backingResolutionScale;
+        Material *globalMaterial;
         
         Polycode::Rectangle viewport;
         std::vector<GPUDrawCall> drawCalls;

+ 23 - 8
include/polycode/core/PolyMaterial.h

@@ -32,17 +32,33 @@ namespace Polycode {
 	class Shader;
 	class ShaderBinding;
 	class ShaderRenderTarget;
+    
+    class _PolyExport ShaderPass {
+        public:
+            ShaderPass();
+            ShaderPass(Shader *shader);
+            Shader *shader;
+            bool wireframe;
+            unsigned short blendingMode;
+            ShaderBinding* shaderBinding;
+    };
 
 	class _PolyExport Material : public Resource {
 		public:
 			explicit Material(const String& name);
 			virtual ~Material();
-			
+
+			void addShaderPass(const ShaderPass &pass);
+			void addShaderPassAtIndex(const ShaderPass &pass, unsigned int shaderIndex);
+        
+            /* DEPRECATED! Use addShaderPass! */
 			void addShader(Shader *shader,ShaderBinding *shaderBinding);
+            /* DEPRECATED! Use addShaderPassAtIndex! */
 			void addShaderAtIndex(Shader *shader,ShaderBinding *shaderBinding, int shaderIndex);			
-			unsigned int getNumShaders() const;
+			unsigned int getNumShaderPasses() const;
 			
-			void removeShader(int shaderIndex);
+        
+			void removeShaderPass(int shaderIndex);
 			
 			void addShaderRenderTarget(ShaderRenderTarget *newTarget);
 			int getNumShaderRenderTargets();
@@ -54,8 +70,10 @@ namespace Polycode {
 			void handleEvent(Event *event);
 						
 			const String& getName() const;
-			Shader *getShader(unsigned int index) const;
+			ShaderPass getShaderPass(unsigned int index) const;
 			ShaderBinding *getShaderBinding(unsigned int index) const;
+			Shader *getShader(unsigned int index) const;
+        
 			void loadMaterial(const String& fileName);
 			
 			void setName(const String &name);
@@ -67,14 +85,11 @@ namespace Polycode {
 			void *shaderModule;
 			
 			int blendingMode;
-        
-            bool wireframe;
 			bool screenMaterial;
 			
 		protected:
 		
-			std::vector<Shader*> materialShaders;
-			std::vector<ShaderBinding*> shaderBindings;
+			std::vector<ShaderPass> shaderPasses;
 			std::vector<ShaderRenderTarget*> renderTargets;
 					
 			String name;

+ 4 - 0
include/polycode/core/PolyOpenGLGraphicsInterface.h

@@ -85,9 +85,13 @@ namespace Polycode {
         void enableBackfaceCulling(bool val);
         void setLineSize(Number lineSize);
         
+        void setWireframeMode(bool val);
+        
         void enableScissor(bool val);
         void setScissorBox(const Polycode::Rectangle &box);
         
+        bool lineSmooth;
+        
 	protected:
 		
         GLuint currentShaderID;

+ 2 - 0
include/polycode/core/PolyRenderer.h

@@ -67,6 +67,8 @@ namespace Polycode {
             virtual void enableScissor(bool val) = 0;
             virtual void setScissorBox(const Polycode::Rectangle &box) = 0;
         
+            virtual void setWireframeMode(bool val) = 0;
+        
             virtual void beginDrawCall() = 0;
             virtual void endDrawCall() = 0;
     };

+ 13 - 10
include/polycode/core/PolySceneMesh.h

@@ -74,11 +74,12 @@ namespace Polycode {
 			
 			void Render(GPUDrawBuffer *buffer);
 			
-            /**
-             * Returns the local material binding options for this mesh.
-             */
-			ShaderBinding *getLocalShaderOptions();
-			
+
+			ShaderPass getShaderPass(unsigned int index);
+            unsigned int getNumShaderPasses();
+            void addShaderPass(ShaderPass pass);
+            void removeShaderPass(int shaderIndex);
+        
 			/**
 			* Returns the Mesh instance of the actual mesh.
 			*/
@@ -193,11 +194,11 @@ namespace Polycode {
             /**
              * The Renderer has an ability to set an override material that is set for all rendered entities. If forceMaterial is set to true, this entity will always use its assigned material, even if an override material is set.
              */
-            bool forceMaterial;
+            void setForceMaterial(bool forceMaterial);
+            bool getForceMaterial();
         
             virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly) const;
-            virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const;
-        
+            virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const;        
             
             /**
              * Normally, translucent textures do not affect the depth buffer, but if this flag is set to true, this entity's alpha channel is written to the depth buffer at a preset threshold. This flag is set to false by default.
@@ -208,7 +209,6 @@ namespace Polycode {
              * If this flag is set to false, backface culling is disabled when rendering this entity, rendering both sides of each face. Set to true by default.
              */
             bool backfaceCulled;
-        
             bool sendBoneMatricesToMaterial;
 			
 		protected:
@@ -217,9 +217,12 @@ namespace Polycode {
 			Mesh *mesh;
 			Material *material;
 			Skeleton *skeleton;
-			ShaderBinding *localShaderOptions;
+        
+            std::vector<ShaderPass> shaderPasses;
+        
             String fileName;
             std::vector<Matrix4> materialBoneMatrices;
+                    
         
             VertexDataArray skeletalVertexPositions;
             VertexDataArray skeletalVertexNormals;

+ 3 - 2
include/polycode/modules/ui/PolyUIElement.h

@@ -58,7 +58,7 @@ namespace Polycode {
 			void focusPreviousChild();
 			bool isFocusable();
 			void focusSelf();
-									
+        
 			virtual void onLoseFocus() {}
 			virtual void onGainFocus() {}
 			
@@ -100,6 +100,7 @@ namespace Polycode {
 			void setImageCoordinates(Number x, Number y, Number width, Number height, Number imageScale = 1.0);
 			Number getImageWidth() const;
 			Number getImageHeight() const;
+            void setMaterial(Material *material);
         
 			Texture *getTexture();			
 		protected:
@@ -108,7 +109,7 @@ namespace Polycode {
 			Number imageHeight;
         
             Material *material;
-            ShaderBinding *localShaderOptions;
+            std::vector<ShaderPass> shaderPasses;
 			
 			Mesh *rectMesh;
 			Texture *texture;

+ 4 - 1
src/core/PolyCocoaCore.mm

@@ -129,7 +129,10 @@ CocoaCore::CocoaCore(PolycodeView *view, int _xRes, int _yRes, bool fullScreen,
 	initTime = mach_absolute_time();					
 
     renderer = new Renderer();
-    renderer->setGraphicsInterface(this, new OpenGLGraphicsInterface());
+    
+    OpenGLGraphicsInterface *interface = new OpenGLGraphicsInterface();
+    interface->lineSmooth = true;
+    renderer->setGraphicsInterface(this, interface);
     services->setRenderer(renderer);
     setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);
     

+ 1 - 0
src/core/PolyEntity.cpp

@@ -57,6 +57,7 @@ void Entity::initEntity() {
 	parentEntity = NULL;
 	matrixDirty = true;
 	billboardMode = false;
+    drawCall.options.forceMaterial = false;
 	drawCall.options.depthOnly = false;
 	drawCall.options.blendingMode = Entity::defaultBlendingMode;    
 	depthWrite = true;

+ 66 - 46
src/core/PolyMaterial.cpp

@@ -30,13 +30,31 @@
 
 using namespace Polycode;
 
+ShaderPass::ShaderPass() :
+    shader(NULL),
+    wireframe(false),
+    shaderBinding(NULL),
+    blendingMode(Renderer::BLEND_MODE_NONE)
+{
+    
+}
+
+ShaderPass::ShaderPass(Shader *shader) :
+    shader(shader),
+    wireframe(false),
+    shaderBinding(NULL),
+    blendingMode(Renderer::BLEND_MODE_NONE)
+{
+    
+}
+
+
 Material::Material(const String& name) : Resource(Resource::RESOURCE_MATERIAL) {
 	this->name = name;
 	fp16RenderTargets = false;
 	shaderModule = NULL;
 	blendingMode = Renderer::BLEND_MODE_NORMAL;
 	screenMaterial = false;
-    wireframe = false;
 }
 
 Material::~Material() {
@@ -53,6 +71,8 @@ void Material::setName(const String &name) {
 }
 
 void Material::clearShaders() {
+    
+    // SMARTPTR_TODO: add here
 	// do not delete shaders here, they're shared
 /*	
 	for(int i=0; i < materialShaders.size(); i++)	{
@@ -60,15 +80,11 @@ void Material::clearShaders() {
 	}
 	*/
 	
-	for(int i=0; i < materialShaders.size(); i++)	{
-		materialShaders[i]->removeAllHandlersForListener(this);
+	for(int i=0; i < shaderPasses.size(); i++)	{
+		shaderPasses[i].shader->removeAllHandlersForListener(this);
+        delete shaderPasses[i].shaderBinding;
 	}	
-	materialShaders.clear();
-
-	for(int i=0; i < shaderBindings.size(); i++)	{
-		delete shaderBindings[i];
-	}
-	shaderBindings.clear();
+	shaderPasses.clear();
 	
 	for(int i=0; i < renderTargets.size(); i++)	{
 		delete renderTargets[i];
@@ -158,64 +174,68 @@ void Material::handleEvent(Event *event) {
      */
 }
 
-void Material::removeShader(int shaderIndex) {
-	if(shaderIndex >= 0 && shaderIndex < materialShaders.size()) {
-		materialShaders.erase(materialShaders.begin() + shaderIndex);
-		shaderBindings.erase(shaderBindings.begin() + shaderIndex);		
+void Material::removeShaderPass(int shaderIndex) {
+	if(shaderIndex >= 0 && shaderIndex < shaderPasses.size()) {
+        delete shaderPasses[shaderIndex].shaderBinding;
+		shaderPasses.erase(shaderPasses.begin() + shaderIndex);
 	}
 }
 
 void Material::addShaderAtIndex(Shader *shader,ShaderBinding *shaderBinding, int shaderIndex) {
-        // RENDERER_TODO
+    ShaderPass newPass;
+    newPass.shader = shader;
+    newPass.shaderBinding = shaderBinding;
+	shaderPasses.insert(shaderPasses.begin()+shaderIndex, newPass);
+	shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);
+}
 
-	materialShaders.insert(materialShaders.begin()+shaderIndex, shader);
-	shaderBindings.insert(shaderBindings.begin()+shaderIndex, shaderBinding);
-	
-	shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);	
-	
-    /*
-	for(int i=0; i < shader->expectedParams.size(); i++) {
-		if(!shaderBinding->getLocalParamByName(shader->expectedParams[i].name)) {
-			shaderBinding->addParam(shader->expectedParams[i].type, shader->expectedParams[i].name);
-		}
-	}
-     */
+void Material::addShaderPass(const ShaderPass &pass) {
+    shaderPasses.push_back(pass);
+    pass.shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);
 }
-			
-void Material::addShader(Shader *shader,ShaderBinding *shaderBinding) {
 
-	materialShaders.push_back(shader);
-	shaderBindings.push_back(shaderBinding);
+void Material::addShaderPassAtIndex(const ShaderPass &pass, unsigned int shaderIndex) {
+    shaderPasses.insert(shaderPasses.begin()+shaderIndex, pass);
+    pass.shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);
+}
+
+
+void Material::addShader(Shader *shader,ShaderBinding *shaderBinding) {
+    ShaderPass newPass;
+    newPass.shader = shader;
+    newPass.shaderBinding = shaderBinding;
+	shaderPasses.push_back(newPass);
 	shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);
-    /*
-	for(int i=0; i < shader->expectedParams.size(); i++) {
-		if(!shaderBinding->getLocalParamByName(shader->expectedParams[i].name)) {
-			shaderBinding->addParam(shader->expectedParams[i].type, shader->expectedParams[i].name);
-		}
-	}	
-     */
 }
 
 
-unsigned int Material::getNumShaders() const {
-	return materialShaders.size();
+unsigned int Material::getNumShaderPasses() const {
+	return shaderPasses.size();
 }
 
 const String& Material::getName() const {
 	return name;
 }
 
+ShaderPass Material::getShaderPass(unsigned int index) const {
+	if(index < shaderPasses.size()) {
+		return shaderPasses[index];
+    } else {
+        return ShaderPass();
+    }
+}
+
 Shader *Material::getShader(unsigned int index) const {
-	if(index < materialShaders.size()) { 
-		return materialShaders[index];
-	} else {
-		return NULL;
-	}
+    if(index < shaderPasses.size()) {
+        return shaderPasses[index].shader;
+    } else {
+        return NULL;
+    }
 }
 
 ShaderBinding *Material::getShaderBinding(unsigned int index) const {
-	if(index < shaderBindings.size()) {
-		return shaderBindings[index]; 
+	if(index < shaderPasses.size()) {
+		return shaderPasses[index].shaderBinding;
 	} else {
 		return NULL;
 	}

+ 21 - 23
src/core/PolyMaterialManager.cpp

@@ -435,11 +435,8 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 
 	String mname = nodeElement->Attribute("name");
 	TiXmlNode* pChild, *pChild2,*pChild3;
-	Shader *materialShader;
-	ShaderBinding *newShaderBinding;
 	
-	vector<Shader*> materialShaders;
-	vector<ShaderBinding*> newShaderBindings;
+	vector<ShaderPass> shaderPasses;
 	vector<ShaderRenderTarget*> renderTargets;
 
 	Material *newMaterial = new Material(mname);
@@ -451,10 +448,6 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 			newMaterial->screenMaterial = true;
 		}
 	}
-    
-	if(nodeElement->Attribute("wireframe")) {
-		newMaterial->wireframe = String(nodeElement->Attribute("wireframe")) == "true";
-	}
 	
 	if(nodeElement->Attribute("blendingMode")) {
 		newMaterial->blendingMode = atoi(nodeElement->Attribute("blendingMode"));
@@ -515,15 +508,23 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 		if (!pChild3Element) continue; // Skip comment nodes
 		
 		if(strcmp(pChild3->Value(), "shader") == 0) {
-			materialShader = setShaderFromXMLNode(resourcePool, pChild3);
-			if(materialShader) {
-                newShaderBinding = new ShaderBinding();
-				materialShaders.push_back(materialShader);
-				newShaderBindings.push_back(newShaderBinding);
+            
+            ShaderPass shaderPass;
+            
+			shaderPass.shader = setShaderFromXMLNode(resourcePool, pChild3);
+            
+            TiXmlElement *nodeElement = pChild3->ToElement();
+            if(nodeElement->Attribute("wireframe")) {
+                shaderPass.wireframe = String(nodeElement->Attribute("wireframe")) == "true";
+            }
+            
+			if(shaderPass.shader) {
+                shaderPass.shaderBinding = new ShaderBinding();
+				shaderPasses.push_back(shaderPass);
 				for (pChild = pChild3->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) {
 					TiXmlElement *pChildElement = pChild->ToElement();
 					if (!pChildElement) continue; // Skip comment nodes
-
+                    
 					if(strcmp(pChild->Value(), "params") == 0) {
 						for (pChild2 = pChild->FirstChild(); pChild2 != 0; pChild2 = pChild2->NextSibling()) {
 							TiXmlElement *pChild2Element = pChild2->ToElement();
@@ -534,8 +535,8 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 
 
                                     String pvalue =  pChild2Element->Attribute("value");
-                                    int type = materialShader->getExpectedParamType(pname);
-                                    LocalShaderParam *param = newShaderBinding->addParam(type, pname);
+                                    int type = shaderPass.shader->getExpectedParamType(pname);
+                                    LocalShaderParam *param = shaderPass.shaderBinding->addParam(type, pname);
                                     if(param) {
                                         param->setParamValueFromString(type, pvalue);
                                     }
@@ -569,7 +570,7 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 									newBinding->mode = RenderTargetBinding::MODE_OUT;								
 								}
 																
-								newShaderBinding->addRenderTargetBinding(newBinding);
+								shaderPass.shaderBinding->addRenderTargetBinding(newBinding);
 								
 								for(int l=0; l < renderTargets.size(); l++) {
 									if(renderTargets[l]->id == newBinding->id) {
@@ -596,7 +597,7 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 									tname =  pChild2Element->Attribute("name");
 								}
 								Texture *texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile(pChild2Element->GetText());
-                                newShaderBinding->setTextureForParam(tname, texture);
+                                shaderPass.shaderBinding->setTextureForParam(tname, texture);
 							}
 							
 							if(strcmp(pChild2->Value(), "cubemap") == 0){
@@ -616,11 +617,8 @@ Material *MaterialManager::materialFromXMLNode(ResourcePool *resourcePool, TiXml
 	}
 	
 
-	for(int i=0; i< materialShaders.size(); i++) {
-		newMaterial->addShader(materialShaders[i],newShaderBindings[i]);
-	}
-	for(int i=0; i< renderTargets.size(); i++) {
-		newMaterial->addShaderRenderTarget(renderTargets[i]);
+	for(int i=0; i< shaderPasses.size(); i++) {
+		newMaterial->addShaderPass(shaderPasses[i]);
 	}
 	
 	return newMaterial;

+ 1 - 0
src/core/PolyMesh.cpp

@@ -879,6 +879,7 @@ unsigned int Mesh::getIndexCount() {
     return indexArray.data.size();
 }
 
+
 void Mesh::createTorus(Number radius, Number tubeRadius, int segmentsW, int segmentsH, Number tilingValue) {
 
     segmentsH++;

+ 16 - 1
src/core/PolyOpenGLGraphicsInterface.cpp

@@ -28,7 +28,7 @@
 using namespace Polycode;
 
 OpenGLGraphicsInterface::OpenGLGraphicsInterface() {
-
+    lineSmooth = false;
 }
 
 OpenGLGraphicsInterface::~OpenGLGraphicsInterface() {
@@ -155,6 +155,11 @@ void OpenGLGraphicsInterface::setBlendingMode(unsigned int blendingMode) {
 
 void OpenGLGraphicsInterface::beginDrawCall() {
     textureIndex = 0;
+#ifndef STRICT_OPENGLES2
+    if(lineSmooth) {
+        glEnable(GL_LINE_SMOOTH);
+    }
+#endif
 }
 
 void OpenGLGraphicsInterface::endDrawCall() {
@@ -203,6 +208,16 @@ void OpenGLGraphicsInterface::setScissorBox(const Polycode::Rectangle &box) {
     
 }
 
+void OpenGLGraphicsInterface::setWireframeMode(bool val) {
+#ifndef STRICT_OPENGLES2
+    if(val) {
+        glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
+    } else {
+        glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
+    }
+#endif
+}
+
 GLenum OpenGLGraphicsInterface::getGLDrawMode(int polycodeMode) {
     switch(polycodeMode) {
         case Mesh::POINT_MESH:

+ 46 - 28
src/core/PolyRenderer.cpp

@@ -98,27 +98,44 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
         
         modelMatrixParam->setMatrix4(buffer->drawCalls[i].modelMatrix);
         
-        if(buffer->drawCalls[i].material) {
-            
+        Material *material = buffer->drawCalls[i].material;
+        if(buffer->globalMaterial && !buffer->drawCalls[i].options.forceMaterial) {
+            material = buffer->globalMaterial;
+        }
+        
+        if(material) {
             
-            if(buffer->drawCalls[i].options.blendingMode == Renderer::BLEND_MODE_MATERIAL) {
-                graphicsInterface->setBlendingMode(buffer->drawCalls[i].material->blendingMode);
+            if(buffer->drawCalls[i].options.blendingMode == Renderer::BLEND_MODE_MATERIAL || buffer->globalMaterial) {
+                graphicsInterface->setBlendingMode(material->blendingMode);
             } else {
                 graphicsInterface->setBlendingMode(buffer->drawCalls[i].options.blendingMode);
             }
             
-            ShaderBinding *localShaderBinding = buffer->drawCalls[i].shaderBinding;
             
-            for(int s=0; s < buffer->drawCalls[i].material->getNumShaders(); s++) {
+            for(int s=0; s < buffer->drawCalls[i].shaderPasses.size(); s++) {
         
                 ++currentDebugFrameInfo.drawCallsProcessed;
                 graphicsInterface->beginDrawCall();
                 
-                Shader *shader = buffer->drawCalls[i].material->getShader(s);
-                graphicsInterface->useShader(shader);
+                ShaderPass shaderPass;
+                if(s < material->getNumShaderPasses()) {
+                    shaderPass = material->getShaderPass(s);
+                } else {
+                    shaderPass = buffer->drawCalls[i].shaderPasses[s];
+                    graphicsInterface->setBlendingMode(shaderPass.blendingMode);
+                }
+                ShaderBinding *localShaderBinding = buffer->drawCalls[i].shaderPasses[s].shaderBinding;
+
+                if(!shaderPass.shader || !localShaderBinding) {
+                    continue;
+                }
                 
-                ShaderBinding *materialShaderBinding = buffer->drawCalls[i].material->getShaderBinding(s);
+                graphicsInterface->useShader(shaderPass.shader);
 
+
+                graphicsInterface->setWireframeMode(shaderPass.wireframe);
+                
+                ShaderBinding *materialShaderBinding = material->getShaderBinding(s);
                 
                 // set shader uniforms
                 
@@ -130,27 +147,28 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
         // TODO: can't cache the param here, need a better system (move to material binding?)
                         
 //                        if(!localParam->param) {
-                            localParam->param = shader->getParamPointer(localParam->name);
+                            localParam->param = shaderPass.shader->getParamPointer(localParam->name);
   //                      }
                         if(localParam->param) {
-                            graphicsInterface->setParamInShader(shader, localParam->param, localParam);
+                            graphicsInterface->setParamInShader(shaderPass.shader, localParam->param, localParam);
                         }
                     }
                     
                 }
    
-                for(int p=0; p < materialShaderBinding->getNumLocalParams(); p++) {
-                    
-                    LocalShaderParam *localParam = materialShaderBinding->getLocalParam(p);
-                    if(localParam) {
-                        if(!localParam->param) {
-                            localParam->param = shader->getParamPointer(localParam->name);
-                        }
-                        if(localParam->param) {
-                            graphicsInterface->setParamInShader(shader, localParam->param, localParam);
+                if(materialShaderBinding) {
+                    for(int p=0; p < materialShaderBinding->getNumLocalParams(); p++) {                        
+                        LocalShaderParam *localParam = materialShaderBinding->getLocalParam(p);
+                        if(localParam) {
+                            if(!localParam->param) {
+                                localParam->param = shaderPass.shader->getParamPointer(localParam->name);
+                            }
+                            if(localParam->param) {
+                                graphicsInterface->setParamInShader(shaderPass.shader, localParam->param, localParam);
+                            }
                         }
-                    }
 
+                    }
                 }
                 
                 for(int p=0; p < localShaderBinding->getNumLocalParams(); p++) {
@@ -158,10 +176,10 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                     LocalShaderParam *localParam = localShaderBinding->getLocalParam(p);
                     if(localParam) {
                         if(!localParam->param) {
-                            localParam->param = shader->getParamPointer(localParam->name);
+                            localParam->param = shaderPass.shader->getParamPointer(localParam->name);
                         }
                         if(localParam->param) {
-                            graphicsInterface->setParamInShader(shader, localParam->param, localParam);
+                            graphicsInterface->setParamInShader(shaderPass.shader, localParam->param, localParam);
                         }
                     }
                     
@@ -175,12 +193,12 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                         if(attributeBinding->enabled) {
                             
                             if(!attributeBinding->attribute) {
-                                attributeBinding->attribute = shader->getAttribPointer(attributeBinding->name);
+                                attributeBinding->attribute = shaderPass.shader->getAttribPointer(attributeBinding->name);
                             }
                             if(attributeBinding->attribute) {
                                 
                                 if(attributeBinding->vertexData->data.size() / attributeBinding->vertexData->countPerVertex >= buffer->drawCalls[i].numVertices) {
-                                    graphicsInterface->setAttributeInShader(shader, attributeBinding->attribute, attributeBinding);
+                                    graphicsInterface->setAttributeInShader(shaderPass.shader, attributeBinding->attribute, attributeBinding);
                                 }
                             } else {
                                 attributeBinding->enabled = false;
@@ -197,9 +215,9 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                 }
                 
                 
-                for(int a=0; a < shader->expectedAttributes.size(); a++) {
-                    ProgramAttribute attribute = shader->expectedAttributes[a];
-                    graphicsInterface->disableAttribute(shader, attribute);
+                for(int a=0; a < shaderPass.shader->expectedAttributes.size(); a++) {
+                    ProgramAttribute attribute = shaderPass.shader->expectedAttributes[a];
+                    graphicsInterface->disableAttribute(shaderPass.shader, attribute);
                 }
                 
                 graphicsInterface->endDrawCall();

+ 1 - 5
src/core/PolyScene.cpp

@@ -226,12 +226,8 @@ void Scene::Render(Camera *targetCamera, Texture *targetFramebuffer) {
     drawBuffer->clearColorBuffer = useClearColor;
     drawBuffer->clearDepthBuffer = useClearDepth;
     drawBuffer->targetFramebuffer = targetFramebuffer;
-    
     drawBuffer->viewport = targetCamera->getViewport();
-///    drawBuffer->projectionMatrix = targetCamera->
-
-   // renderer->setOverrideMaterial(overrideMaterial);
-	
+    drawBuffer->globalMaterial = overrideMaterial;
 		
 	//make these the closest
 	

+ 7 - 0
src/core/PolySceneEntityInstance.cpp

@@ -212,7 +212,10 @@ void SceneEntityInstance::applySceneMesh(ObjectEntry *entry, SceneMesh *sceneMes
                                             }
                                              */
                                         } else {
+                                            // RENDERER_TODO
+                                            /*
                                             sceneMesh->getLocalShaderOptions()->setTextureForParam(nameEntry->stringVal, CoreServices::getInstance()->getMaterialManager()->createTextureFromFile(textureEntry->stringVal));
+                                             */
                                         }
                                     }
                                 }
@@ -230,10 +233,14 @@ void SceneEntityInstance::applySceneMesh(ObjectEntry *entry, SceneMesh *sceneMes
                                         Shader *materialShader = sceneMesh->getMaterial()->getShader(i);
                                         if(materialShader) {
                                             int type = materialShader->getExpectedParamType(nameEntry->stringVal);
+                                            
+                                            // RENDERER_TODO
+                                            /*
                                             LocalShaderParam *param = sceneMesh->getLocalShaderOptions()->addParam(type, nameEntry->stringVal);
                                             if(param) {
                                                 param->setParamValueFromString(type, valueEntry->stringVal);
                                             }
+                                             */
                                         }
                                     }
                                     

+ 3 - 3
src/core/PolySceneImage.cpp

@@ -38,7 +38,7 @@ SceneImage* SceneImage::SceneImageWithTexture(Texture *texture) {
 SceneImage::SceneImage(const String& fileName) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
     
     // RENDERER_TODO
-    Texture *texture = localShaderOptions->loadTextureForParam("diffuse", fileName);
+    Texture *texture = getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", fileName);
 
 	imageWidth = texture->getWidth();
 	imageHeight = texture->getHeight();
@@ -52,7 +52,7 @@ SceneImage::SceneImage(Image *image) : ScenePrimitive(ScenePrimitive::TYPE_VPLAN
     // RENDERER_TODO
 	//loadTextureFromImage(image);
     Texture *texture = Services()->getMaterialManager()->createTextureFromImage(image);
-    localShaderOptions->setTextureForParam("diffuse", texture);
+    getShaderPass(0).shaderBinding->setTextureForParam("diffuse", texture);
 
 	imageWidth = texture->getWidth();
 	imageHeight = texture->getHeight();
@@ -63,7 +63,7 @@ SceneImage::SceneImage(Image *image) : ScenePrimitive(ScenePrimitive::TYPE_VPLAN
 }
 
 SceneImage::SceneImage(Texture *texture) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1)  {
-    localShaderOptions->setTextureForParam("diffuse", texture);
+    getShaderPass(0).shaderBinding->setTextureForParam("diffuse", texture);
 
 	imageWidth = texture->getWidth();
 	imageHeight = texture->getHeight();

+ 1 - 1
src/core/PolySceneLabel.cpp

@@ -121,7 +121,7 @@ void SceneLabel::updateFromLabel() {
 	
     setLocalBoundingBox(label->getWidth()*labelScale / CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX(), label->getHeight()*labelScale/ CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX(), 0.001);
     
-    localShaderOptions->setTextureForParam("diffuse", texture);
+    getShaderPass(0).shaderBinding->setTextureForParam("diffuse", texture);
     
 }
 

+ 65 - 28
src/core/PolySceneMesh.cpp

@@ -43,7 +43,7 @@ SceneMesh *SceneMesh::SceneMeshWithType(int meshType) {
 	return new SceneMesh(meshType);
 }
 
-SceneMesh::SceneMesh(const String& fileName) : Entity(), material(NULL), skeleton(NULL), localShaderOptions(NULL), mesh(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
+SceneMesh::SceneMesh(const String& fileName) : Entity(), material(NULL), skeleton(NULL), mesh(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
     loadFromFile(fileName);
 	useVertexBuffer = false;
 	lineSmooth = false;
@@ -53,14 +53,13 @@ SceneMesh::SceneMesh(const String& fileName) : Entity(), material(NULL), skeleto
 	pointSize = 1.0;
 	pointSmooth = false;
 	useGeometryHitDetection = false;
-    forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
     sendBoneMatricesToMaterial = false;
     setMaterialByName("UnlitUntextured");
 }
 
-SceneMesh::SceneMesh(Mesh *mesh) : Entity(), material(NULL), skeleton(NULL), localShaderOptions(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
+SceneMesh::SceneMesh(Mesh *mesh) : Entity(), material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
 	this->mesh = mesh;
 	setLocalBoundingBox(mesh->calculateBBox());
 	useVertexBuffer = false;
@@ -71,14 +70,13 @@ SceneMesh::SceneMesh(Mesh *mesh) : Entity(), material(NULL), skeleton(NULL), loc
 	pointSize = 1.0;
 	pointSmooth = false;
 	useGeometryHitDetection = false;
-    forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
     sendBoneMatricesToMaterial = false;
     setMaterialByName("UnlitUntextured");
 }
 
-SceneMesh::SceneMesh(int meshType) : material(NULL), skeleton(NULL), localShaderOptions(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
+SceneMesh::SceneMesh(int meshType) : material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
 	mesh = new Mesh(meshType);
 	setLocalBoundingBox(mesh->calculateBBox());
 	useVertexBuffer = false;	
@@ -87,7 +85,6 @@ SceneMesh::SceneMesh(int meshType) : material(NULL), skeleton(NULL), localShader
 	ownsSkeleton = true;	
 	lineWidth = 1.0;
 	useGeometryHitDetection = false;
-    forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
     sendBoneMatricesToMaterial = false;
@@ -107,10 +104,12 @@ void SceneMesh::setMesh(Mesh *mesh) {
 }
 
 void SceneMesh::rebuildAttributes() {
-    if(localShaderOptions) {
-        localShaderOptions->getAttributeBindingByName("texCoord")->vertexData = &mesh->vertexTexCoordArray;
-        localShaderOptions->getAttributeBindingByName("position")->vertexData = &mesh->vertexPositionArray;
-        localShaderOptions->getAttributeBindingByName("normal")->vertexData = &mesh->vertexNormalArray;
+    for(int i=0; i < shaderPasses.size(); i++) {
+        if(shaderPasses[i].shaderBinding) {
+            shaderPasses[i].shaderBinding->getAttributeBindingByName("texCoord")->vertexData = &mesh->vertexTexCoordArray;
+            shaderPasses[i].shaderBinding->getAttributeBindingByName("position")->vertexData = &mesh->vertexPositionArray;
+            shaderPasses[i].shaderBinding->getAttributeBindingByName("normal")->vertexData = &mesh->vertexNormalArray;
+        }
     }
 }
 
@@ -118,8 +117,11 @@ SceneMesh::~SceneMesh() {
 	if(ownsSkeleton)
 		delete skeleton;
 	if(ownsMesh)
-		delete mesh;	
-	delete localShaderOptions;
+		delete mesh;
+    
+    for(int i=0; i < shaderPasses.size(); i++)  {
+        delete shaderPasses[i].shaderBinding;
+    }
 }
 
 Entity *SceneMesh::Clone(bool deepClone, bool ignoreEditorOnly) const {
@@ -128,6 +130,14 @@ Entity *SceneMesh::Clone(bool deepClone, bool ignoreEditorOnly) const {
     return newEntity;
 }
 
+void SceneMesh::setForceMaterial(bool forceMaterial) {
+    drawCall.options.forceMaterial = forceMaterial;
+}
+
+bool SceneMesh::getForceMaterial() {
+    return drawCall.options.forceMaterial;
+}
+
 void SceneMesh::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const {
     Entity::applyClone(clone, deepClone, ignoreEditorOnly);
     SceneMesh *_clone = (SceneMesh*) clone;
@@ -141,7 +151,6 @@ void SceneMesh::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly)
 	_clone->backfaceCulled = backfaceCulled;
     _clone->ownsSkeleton = ownsSkeleton;
     _clone->useGeometryHitDetection = useGeometryHitDetection;
-    _clone->forceMaterial = forceMaterial;
     _clone->setFilename(fileName);
     
     Mesh *newMesh = mesh->Copy();
@@ -149,7 +158,10 @@ void SceneMesh::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly)
     
     _clone->setMaterial(material);
     if(material) {
-        localShaderOptions->copyTo(_clone->getLocalShaderOptions());
+        
+        for(int i=0; i < shaderPasses.size(); i++) {
+            shaderPasses[i].shaderBinding->copyTo(_clone->getShaderPass(i).shaderBinding);
+        }
     }
 }
 
@@ -175,10 +187,11 @@ Mesh *SceneMesh::getMesh() {
 }
 
 void SceneMesh::clearMaterial() {
-	if(localShaderOptions)
-		delete localShaderOptions;
-	localShaderOptions = NULL;
-	this->material = NULL;
+    for(int i=0; i < shaderPasses.size(); i++)  {
+        delete shaderPasses[i].shaderBinding;
+    }
+    shaderPasses.clear();
+    this->material = NULL;
 }
 
 void SceneMesh::setMaterial(Material *material) {
@@ -189,18 +202,23 @@ void SceneMesh::setMaterial(Material *material) {
 	if(!material)
 		return;
 		
-	if(material->getNumShaders() == 0)
+	if(material->getNumShaderPasses() == 0)
 			return;
 		
 	this->material = material;
-    localShaderOptions = new ShaderBinding();
     
-    localShaderOptions->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
+    for(int i=0; i < material->getNumShaderPasses(); i++)  {
+        ShaderPass shaderPass = material->getShaderPass(i);
+        shaderPass.shaderBinding = new ShaderBinding();
+        
+        shaderPass.shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
+        shaderPass.shaderBinding->addAttributeBinding("texCoord", &mesh->vertexTexCoordArray);
+        shaderPass.shaderBinding->addAttributeBinding("position", &mesh->vertexPositionArray);
+        shaderPass.shaderBinding->addAttributeBinding("normal", &mesh->vertexNormalArray);
+        
+        shaderPasses.push_back(shaderPass);
+    }
     
-    localShaderOptions->addAttributeBinding("texCoord", &mesh->vertexTexCoordArray);
-    localShaderOptions->addAttributeBinding("position", &mesh->vertexPositionArray);
-    localShaderOptions->addAttributeBinding("normal", &mesh->vertexNormalArray);
-	
 }
 
 void SceneMesh::setMaterialByName(const String& materialName, ResourcePool *resourcePool) {
@@ -214,8 +232,20 @@ void SceneMesh::setMaterialByName(const String& materialName, ResourcePool *reso
     setMaterial(material);
 }
 
-ShaderBinding *SceneMesh::getLocalShaderOptions() {
-	return localShaderOptions;
+ShaderPass SceneMesh::getShaderPass(unsigned int index) {
+    if(index >= shaderPasses.size()) {
+        printf("WARNING: ACCESSING NON EXISTING SHADER PASS!\n");
+        return ShaderPass();
+    }
+    return shaderPasses[index];
+}
+
+unsigned int SceneMesh::getNumShaderPasses() {
+    return shaderPasses.size();
+}
+
+void SceneMesh::addShaderPass(ShaderPass pass) {
+    shaderPasses.push_back(pass);
 }
 
 Skeleton *SceneMesh::loadSkeleton(const String& fileName) {
@@ -344,6 +374,13 @@ bool SceneMesh::customHitDetection(const Ray &ray) {
 }
 
 
+void SceneMesh::removeShaderPass(int shaderIndex) {
+    if(shaderIndex >= 0 && shaderIndex < shaderPasses.size()) {
+        delete shaderPasses[shaderIndex].shaderBinding;
+        shaderPasses.erase(shaderPasses.begin() + shaderIndex);
+    }
+}
+
 void SceneMesh::Render(GPUDrawBuffer *buffer) {
     
     drawCall.options.alphaTest = alphaTest;
@@ -366,7 +403,7 @@ void SceneMesh::Render(GPUDrawBuffer *buffer) {
     
     
     drawCall.material = material;
-    drawCall.shaderBinding = localShaderOptions;
+    drawCall.shaderPasses = shaderPasses;
     
     buffer->drawCalls.push_back(drawCall);
     

+ 2 - 2
src/core/PolySceneSprite.cpp

@@ -131,7 +131,7 @@ void SceneSprite::setSpriteSet(SpriteSet *spriteSet) {
     this->spriteSet = spriteSet;
     spriteSet->addEventListener(this, Event::CHANGE_EVENT);
     
-    localShaderOptions->setTextureForParam("diffuse", spriteSet->getTexture());
+    getShaderPass(0).shaderBinding->setTextureForParam("diffuse", spriteSet->getTexture());
     currentSprite = NULL;
     currentSpriteState = NULL;
 }
@@ -218,7 +218,7 @@ void SceneSprite::Update() {
     setLocalBoundingBox(bBox.x / currentSpriteState->getPixelsPerUnit(), bBox.y / currentSpriteState->getPixelsPerUnit(), 0.001);
     
     spriteBoundingBox = currentSpriteState->getLargestFrameBoundingBox();    
-    localShaderOptions->setTextureForParam("diffuse", spriteSet->getTexture());
+    getShaderPass(0).shaderBinding->setTextureForParam("diffuse", spriteSet->getTexture());
     
     if(paused) {
         return;

+ 11 - 1
src/ide/EditorGrid.cpp

@@ -102,6 +102,9 @@ EditorGrid::EditorGrid() : Entity() {
     Mesh *gridMesh = new Mesh(Mesh::LINE_MESH);
     
     grid = new SceneMesh(gridMesh);
+    grid->setForceMaterial(true);
+    grid->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    
     grid->setColor(0.3, 0.3, 0.3, 1.0);
     grid->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
     addChild(grid);
@@ -110,15 +113,22 @@ EditorGrid::EditorGrid() : Entity() {
     addChild(yLine);
     yLine->setColor(0.0, 0.8, 0.0, 1.0);
     yLine->visible = false;
+    yLine->setForceMaterial(true);
     
     xLine = new SceneLine(Vector3(), Vector3());
     addChild(xLine);
     xLine->setColor(0.8, 0.0, 0.0, 1.0);
+    xLine->setForceMaterial(true);
     
     zLine = new SceneLine(Vector3(), Vector3());
     addChild(zLine);
     zLine->setColor(0.0, 0.0, 0.8, 1.0);
-
+    zLine->setForceMaterial(true);
+    
+    xLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    yLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    zLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    
     gridSize = 1.0;
     gridLen = 16;
     

+ 4 - 5
src/ide/EntityEditorPropertyView.cpp

@@ -133,15 +133,14 @@ void EntityEditorPropertyView::updateShaderOptions() {
     shaderOptionsSheet->enabled = false;
     
     if(sceneMesh) {
-        if(sceneMesh->getMaterial() && sceneMesh->getLocalShaderOptions()) {
+        if(sceneMesh->getMaterial() && sceneMesh->getNumShaderPasses() > 0) {
             
             // can't edit the textures manually on a scene label or sprite
             if(!sceneLabel && !sceneSprite) {
-            shaderTexturesSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
+            shaderTexturesSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getShaderPass(0).shaderBinding);
                 shaderTexturesSheet->enabled = true;
-            }
-            
-            shaderOptionsSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
+            }            
+            shaderOptionsSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getShaderPass(0).shaderBinding);
         }
     }
 }

+ 49 - 17
src/ide/PolycodeEntityEditor.cpp

@@ -98,19 +98,22 @@ CurveDisplay::CurveDisplay(Scene *parentScene, SceneCurve *curve) : DummyTargetE
     controlPointLines = new SceneMesh(Mesh::LINE_MESH);
     controlPointLines->setColor(1.0, 1.0, 0.4, 1.0);
     addChild(controlPointLines);
-    
+    controlPointLines->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    controlPointLines->setForceMaterial(true);
    
     mainPoints = new SceneMesh(Mesh::POINT_MESH);
     mainPoints->setColor(0.0, 0.5, 1.0, 1.0);
     addChild(mainPoints);
     mainPoints->pointSize = 10.0;
     mainPoints->pointSmooth = true;
-
+    mainPoints->setForceMaterial(true);
+    
     controlPoints = new SceneMesh(Mesh::POINT_MESH);
     controlPoints->setColor(1.0, 0.7, 0.0, 1.0);
     addChild(controlPoints);
     controlPoints->pointSize = 8.0;
     controlPoints->pointSmooth = true;
+    controlPoints->setForceMaterial(true);
     
     renderControlPoints = false;
     
@@ -284,12 +287,16 @@ LightDisplay::LightDisplay(SceneLight *light) : Entity() {
     addChild(spotSpot);
     spotSpot->setColor(1.0, 0.8, 0.0, 1.0);
     spotSpot->enabled = false;
+    spotSpot->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    spotSpot->setForceMaterial(true);
     
     fovSceneMesh = new SceneMesh(Mesh::LINE_MESH);
     fovSceneMesh->setColor(1.0, 0.8, 0.0, 1.0);
     fovMesh = fovSceneMesh->getMesh();
     fovMesh->indexedMesh = true;
     addChild(fovSceneMesh);
+    fovSceneMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    fovSceneMesh->setForceMaterial(true);
     
     fovMesh->addVertex(0.0, 0.0, 0.0);
     
@@ -342,9 +349,11 @@ CameraDisplay::CameraDisplay(Camera *camera) : Entity() {
     editorOnly = true;
     
     fovSceneMesh = new SceneMesh(Mesh::LINE_MESH);
+    fovSceneMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     fovSceneMesh->setColor(1.0, 0.0, 1.0, 1.0);
     fovMesh = fovSceneMesh->getMesh();
     fovMesh->indexedMesh = true;
+    fovSceneMesh->setForceMaterial(true);
     
     fovMesh->addVertex(0.0, 0.0, 0.0);
     
@@ -714,7 +723,7 @@ EntityEditorMainView::EntityEditorMainView(PolycodeEditor *editor) {
     bBoxVis = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 1.0, 1.0, 1.0);
     bBoxVis->color = Color(0.3, 0.5, 1.0, 0.5);
     bBoxVis->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
-    mainScene->addChild(bBoxVis);
+    //mainScene->addChild(bBoxVis);
     
     editorMode = EDITOR_MODE_3D;
     
@@ -1001,13 +1010,11 @@ void EntityEditorMainView::createIcon(Entity *entity, String iconFile) {
     iconPrimitive->setMaterialByName("Unlit");
     iconPrimitive->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
 	Texture *tex = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile("entityEditor/"+iconFile);
-	if(iconPrimitive->getLocalShaderOptions()) {
-        iconPrimitive->getLocalShaderOptions()->setTextureForParam("diffuse", tex);
-	}
+    iconPrimitive->getShaderPass(0).shaderBinding->setTextureForParam("diffuse", tex);
     
     addChild(iconPrimitive);
     iconPrimitive->setUserData((void*)entity);
-    iconPrimitive->forceMaterial = true;
+    iconPrimitive->setForceMaterial(true);
     iconPrimitive->processInputEvents = true;
     iconPrimitive->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
     iconPrimitive->setUserData(entity);
@@ -1083,6 +1090,8 @@ void EntityEditorMainView::setEditorProps(Entity *entity) {
     
     SceneCurve *sceneCurve = dynamic_cast<SceneCurve*>(entity);
     if(sceneCurve) {
+        sceneCurve->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+        sceneCurve->setForceMaterial(true);
         CurveDisplay *curveVis = new CurveDisplay(mainScene, sceneCurve);
         curveVis->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
         createIcon(entity, "curve_icon.png");
@@ -1552,7 +1561,14 @@ void EntityEditorMainView::handleEvent(Event *event) {
                 mainScene->setOverrideMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Default"));
             break;
             case 2:
-                mainScene->setOverrideMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitWireframe"));
+            {
+                Material *wireframeMaterial = (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitWireframe");
+                
+                if(!wireframeMaterial->getShaderPass(0).shaderBinding->getLocalParamByName("wireframeColor")) {
+                    wireframeMaterial->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_COLOR, "wireframeColor")->setColor(Color(1.0, 1.0, 1.0, 1.0));
+                }
+                mainScene->setOverrideMaterial(wireframeMaterial);
+            }
             break;
         }
     } else if(event->getDispatcher() == moveUpButton) {
@@ -1736,8 +1752,7 @@ Scene *EntityEditorMainView::getMainScene() {
 void EntityEditorMainView::doEntityDeselect(Entity *targetEntity) {
     SceneMesh *sceneMesh = dynamic_cast<SceneMesh*>(targetEntity);
     if(sceneMesh) {
-        // RENDERER_TODO
-        //sceneMesh->overlayWireframe = false;
+        setOverlayWireframeRecursive(sceneMesh, false);
     }
     
     if(targetEntity == dummyEntity) {
@@ -1764,8 +1779,24 @@ void EntityEditorMainView::doEntityDeselect(Entity *targetEntity) {
 void EntityEditorMainView::setOverlayWireframeRecursive(Entity *targetEntity, bool val) {
     SceneMesh *sceneMesh = dynamic_cast<SceneMesh*>(targetEntity);
     if(sceneMesh) {
-        // RENDERER_TODO
-            //sceneMesh->overlayWireframe = val;
+        Material *material = sceneMesh->getMaterial();
+        if(material) {
+            if(val) {
+                ShaderPass wireframePass;
+                wireframePass.shader = (Shader*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_SHADER, "UnlitWireframe");
+                wireframePass.wireframe = true;
+                wireframePass.shaderBinding = new ShaderBinding();
+                wireframePass.blendingMode = Renderer::BLEND_MODE_NORMAL;
+                wireframePass.shaderBinding->addAttributeBinding("position", &sceneMesh->getMesh()->vertexPositionArray);
+                wireframePass.shaderBinding->addParam(ProgramParam::PARAM_COLOR, "wireframeColor")->setColor(Color(0.5, 0.6, 1.0, 0.75));
+
+                
+                sceneMesh->addShaderPass(wireframePass);
+            } else {
+                sceneMesh->removeShaderPass(sceneMesh->getNumShaderPasses()-1);
+            }
+        }
+        
     }
     for(int i=0; i < targetEntity->getNumChildren(); i++) {
         setOverlayWireframeRecursive(targetEntity->getChildAtIndex(i), val);
@@ -1777,8 +1808,7 @@ void EntityEditorMainView::doEntitySelect(Entity *targetEntity) {
     SceneParticleEmitter *emitter = dynamic_cast<SceneParticleEmitter*>(targetEntity);
     
     if(sceneMesh && ! emitter) {
-                // RENDERER_TODO
-//        sceneMesh->overlayWireframe = true;
+        setOverlayWireframeRecursive(sceneMesh, true);
     }
     
     if(targetEntity == dummyEntity) {
@@ -2368,7 +2398,9 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry *
         if(sceneMesh->getMaterial()) {
             meshEntry->addChild("material", sceneMesh->getMaterial()->getResourceName());
             ObjectEntry *shaderOptions = meshEntry->addChild("shader_options");
-            saveShaderOptionsToEntry(shaderOptions, sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
+            
+            // RENDERER_TODO
+            //saveShaderOptionsToEntry(shaderOptions, sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
         }
     }
     
@@ -2413,8 +2445,8 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry *
 void PolycodeEntityEditor::saveShaderOptionsToEntry(ObjectEntry *entry, Material *material, ShaderBinding *binding) {
 
 	
-    if(material->getNumShaders() > 0) {
-        for(int s=0; s < material->getNumShaders(); s++) {
+    if(material->getNumShaderPasses() > 0) {
+        for(int s=0; s < material->getNumShaderPasses(); s++) {
             Shader *shader = material->getShader(s);
             
             ObjectEntry *shaderEntry = entry->addChild("shader");

+ 0 - 1
src/ide/PolycodeIDEApp.cpp

@@ -22,7 +22,6 @@
 
 #include "polycode/ide/PolycodeIDEApp.h"
 
-
 using namespace Polycode;
 
 UIGlobalMenu *globalMenu;

+ 4 - 4
src/ide/PolycodeMaterialEditor.cpp

@@ -719,8 +719,8 @@ MaterialPreviewBox::MaterialPreviewBox() : UIElement() {
 	
 	previewBg->setMaterialByName("Unlit");
 	Texture *tex = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile("materialEditor/material_grid.png");
-	if(previewBg->getLocalShaderOptions()) {
-        previewBg->getLocalShaderOptions()->setTextureForParam("diffuse", tex);
+	if(previewBg->getNumShaderPasses() > 0) {
+        previewBg->getShaderPass(0).shaderBinding->setTextureForParam("diffuse", tex);
 	}
 	previewScene->addChild(previewBg);
 	
@@ -1328,8 +1328,8 @@ void PolycodeMaterialEditor::saveMaterials(ObjectEntry *materialsEntry, std::vec
 			}
 		}
 		
-		if(material->getNumShaders() > 0) {
-			for(int s=0; s < material->getNumShaders(); s++) { 
+		if(material->getNumShaderPasses() > 0) {
+			for(int s=0; s < material->getNumShaderPasses(); s++) {
 				Shader *shader = material->getShader(s);
 				
 				ObjectEntry *shaderEntry = materialEntry->addChild("shader");

+ 5 - 5
src/ide/PolycodeProps.cpp

@@ -1243,8 +1243,8 @@ MaterialProp::MaterialProp(const String &caption) : PropProp(caption, "Material"
 	
 	previewBg->setMaterialByName("Unlit");
 	Texture *tex = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile("materialEditor/material_grid.png");
-	if(previewBg->getLocalShaderOptions()) {
-        previewBg->getLocalShaderOptions()->setTextureForParam("diffuse", tex);
+	if(previewBg->getNumShaderPasses()) {
+        previewBg->getShaderPass(0).shaderBinding->setTextureForParam("diffuse", tex);
 	}
 	previewScene->addChild(previewBg);
 	
@@ -1634,7 +1634,7 @@ void ShaderPassProp::handleEvent(Event *event) {
 		Shader *selectedShader = (Shader*)shaderComboBox->getSelectedItem()->data;
 		if(selectedShader) {
 			if(material->getShader(shaderIndex) != selectedShader) {
-				material->removeShader(shaderIndex);				
+				material->removeShaderPass(shaderIndex);
                 ShaderBinding *newShaderBinding = new ShaderBinding();
 				material->addShaderAtIndex(selectedShader, newShaderBinding, shaderIndex);
 				dispatchEvent(new Event(), Event::CHANGE_EVENT);
@@ -1925,7 +1925,7 @@ void ShaderPassesSheet::refreshPasses() {
 		return;
 	}
 
-	for(int i=0; i < material->getNumShaders(); i++) {
+	for(int i=0; i < material->getNumShaderPasses(); i++) {
 		ShaderPassProp *passProp = new ShaderPassProp(material, i);
 		passProp->addEventListener(this, Event::REMOVE_EVENT);
 		passProp->addEventListener(this, Event::CHANGE_EVENT);		
@@ -1940,7 +1940,7 @@ void ShaderPassesSheet::refreshPasses() {
 
 void ShaderPassesSheet::Update() {
 	if(removeIndex != -1) {
-		material->removeShader(removeIndex);
+		material->removeShaderPass(removeIndex);
 		refreshPasses();
 		removeIndex = -1;			
 	}

+ 7 - 7
src/ide/PolycodeSpriteEditor.cpp

@@ -33,7 +33,7 @@ SpriteSheetEditor::SpriteSheetEditor(SpriteSet *sprite) : UIElement() {
     this->sprite = sprite;
     willCreateFrame = false;
     zoomScale = 1.0;
-    enableScissor = true;
+    drawCall.options.enableScissor = true;
     
     previewBg = new UIImage("main/grid_dark.png");
     addChild(previewBg);
@@ -56,14 +56,14 @@ SpriteSheetEditor::SpriteSheetEditor(SpriteSet *sprite) : UIElement() {
     frameVisualizerMesh->setColor(1.0, 1.0, 1.0, 1.0);
     addChild(frameVisualizerMesh);
     frameVisualizerMesh->setAnchorPoint(-1.0, -1.0, 0.0);
-    frameVisualizerMesh->getLocalShaderOptions()->loadTextureForParam("diffuse", "main/stipple.png");
+    frameVisualizerMesh->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main/stipple.png");
     frameVisualizerMesh->lineWidth = 1; //CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX();
 
     frameVisualizerMeshSelected = new SceneMesh(Mesh::LINE_MESH);
     frameVisualizerMeshSelected->setColor(1.0, 1.0, 0.0, 1.0);
     addChild(frameVisualizerMeshSelected);
     frameVisualizerMeshSelected->setAnchorPoint(-1.0, -1.0, 0.0);
-    frameVisualizerMeshSelected->getLocalShaderOptions()->loadTextureForParam("diffuse", "main/stipple.png");
+    frameVisualizerMeshSelected->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main/stipple.png");
     frameVisualizerMeshSelected->lineWidth = 2;
     
     previewImage->setTexture(sprite->getTexture());
@@ -1131,7 +1131,7 @@ void SpriteStateEditBar::refreshBar() {
         return;
     }
     
-    barMesh->getLocalShaderOptions()->setTextureForParam("diffuse", spriteSet->getTexture());
+    barMesh->getShaderPass(0).shaderBinding->setTextureForParam("diffuse", spriteSet->getTexture());
     
     Mesh *mesh = barMesh->getMesh();
     mesh->clearMesh();
@@ -1339,7 +1339,7 @@ SpriteStateEditBar::SpriteStateEditBar(SpriteSet *spriteSet) : UIElement() {
     
     barMeshBg = new SceneMesh(Mesh::TRI_MESH);
     barBase->addChild(barMeshBg);
-    barMeshBg->getLocalShaderOptions()->loadTextureForParam("diffuse", "spriteEditor/sprite_frame_bg.png");
+    barMeshBg->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "spriteEditor/sprite_frame_bg.png");
     barMeshBg->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
     barMesh = new SceneMesh(Mesh::TRI_MESH);
@@ -1352,7 +1352,7 @@ SpriteStateEditBar::SpriteStateEditBar(SpriteSet *spriteSet) : UIElement() {
     frameGripsMesh = new SceneMesh(Mesh::TRI_MESH);
     barBase->addChild(frameGripsMesh);
     frameGripsMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
-    frameGripsMesh->getLocalShaderOptions()->loadTextureForParam("diffuse", "spriteEditor/frame_grip.png");
+    frameGripsMesh->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "spriteEditor/frame_grip.png");
     
     this->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_UP);
     this->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_DOWN);
@@ -1936,7 +1936,7 @@ SpritePreview::SpritePreview(SpriteSet *spriteSet) : UIElement() {
     
     boundingBoxPreview = new SceneMesh(Mesh::LINE_MESH);
     addChild(boundingBoxPreview);
-    boundingBoxPreview->getLocalShaderOptions()->loadTextureForParam("diffuse", "main/stipple_small.png");
+    boundingBoxPreview->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main/stipple_small.png");
     boundingBoxPreview->lineWidth = 1;
     
     

+ 35 - 14
src/ide/TransformGizmo.cpp

@@ -281,7 +281,9 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     yLine->setLocalBoundingBox(yLine->getMesh()->calculateBBox());
     yLine->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX() * 2.0);
 	transformAndScaleLines->addChild(yLine);
-
+    yLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    yLine->setForceMaterial(true);
+    
 	xLine = new SceneMesh(Mesh::LINE_MESH);
 	xLine->getMesh()->addVertex(0.0, 0.0, 0.0);
 	xLine->getMesh()->addVertex(1.0, 0.0, 0.0);
@@ -290,7 +292,9 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     xLine->setLocalBoundingBox(xLine->getMesh()->calculateBBox());
     xLine->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX() * 2.0);
 	transformAndScaleLines->addChild(xLine);
-
+    xLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    xLine->setForceMaterial(true);
+    
 	zLine = new SceneMesh(Mesh::LINE_MESH);
 	zLine->getMesh()->addVertex(0.0, 0.0, 0.0);
 	zLine->getMesh()->addVertex(0.0, 0.0, 1.0);
@@ -299,7 +303,9 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     zLine->setLocalBoundingBox(zLine->getMesh()->calculateBBox());
     zLine->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX() * 2.0);
 	transformAndScaleLines->addChild(zLine);
-	
+    zLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    zLine->setForceMaterial(true);
+    
 	// MOVE
 	
 	yArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
@@ -307,21 +313,24 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	yArrow->setPosition(0.0, 1.0, 0.0);
 	yArrow->depthTest = false;
 	trasnformDecorators->addChild(yArrow);
-	
+    yArrow->setForceMaterial(true);
+    
 	xArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	xArrow->setColor(1.0, 0.0, 0.0, 1.0);
 	xArrow->setPosition(1.0, 0.0, 0.0);
 	xArrow->Roll(-90);
 	xArrow->depthTest = false;
 	trasnformDecorators->addChild(xArrow);
-
+    xArrow->setForceMaterial(true);
+    
 	zArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	zArrow->setColor(0.0, 0.0, 1.0, 1.0);
 	zArrow->setPosition(0.0, 0.0, 1.0);
 	zArrow->Pitch(90);
 	zArrow->depthTest = false;	
 	trasnformDecorators->addChild(zArrow);
-
+    zArrow->setForceMaterial(true);
+    
 	// SCALE
 
 	yBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
@@ -329,21 +338,24 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	yBox->setPosition(0.0, 1.0, 0.0);
 	yBox->depthTest = false;
 	scaleDecorators->addChild(yBox);
-	
+    yBox->setForceMaterial(true);
+    
 	xBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
 	xBox->setColor(1.0, 0.0, 0.0, 1.0);
 	xBox->setPosition(1.0, 0.0, 0.0);
 	xBox->Roll(-90);
 	xBox->depthTest = false;
 	scaleDecorators->addChild(xBox);
-
+    xBox->setForceMaterial(true);
+    
 	zBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
 	zBox->setColor(0.0, 0.0, 1.0, 1.0);
 	zBox->setPosition(0.0, 0.0, 1.0);
 	zBox->Pitch(90);
 	zBox->depthTest = false;	
 	scaleDecorators->addChild(zBox);
-
+    zBox->setForceMaterial(true);
+    
 	// ROTATE
 
 	bgCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.6, 2.6, 32);
@@ -353,7 +365,9 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	bgCircle->billboardMode = true;
 	rotateDectorators->addChild(bgCircle);
     bgCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
-
+    bgCircle->setForceMaterial(true);
+    bgCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
+    
 	outerCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 3.0, 3.0, 32);
 	outerCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
@@ -361,8 +375,10 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	outerCircle->billboardMode = true;
 	rotateDectorators->addChild(outerCircle);
     outerCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX() * 2.0);
+    outerCircle->setForceMaterial(true);
+    outerCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-	pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.55, 2.55, 32);
+	pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.55, 2.55, 64);
 	pitchCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	pitchCircle->setColor(1.0, 0.0, 0.0, 1.0);
 	pitchCircle->depthTest = false;
@@ -370,8 +386,10 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators->addChild(pitchCircle);
 	pitchCircle->setMaterialByName("OneSidedLine");
     pitchCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX() * 2.0);
+    pitchCircle->setForceMaterial(true);
+    pitchCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-	yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.65, 2.65, 32);
+	yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.65, 2.65, 64);
 	yawCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	yawCircle->setColor(0.0, 1.0, 0.0, 1.0);
 	yawCircle->depthTest = false;
@@ -379,16 +397,19 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators->addChild(yawCircle);
 	yawCircle->setMaterialByName("OneSidedLine");
     yawCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX()* 2.0);
+    yawCircle->setForceMaterial(true);
+    yawCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-	rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.6, 2.6, 32);
+	rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.6, 2.6, 64);
 	rollCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	rollCircle->setColor(0.0, 0.0, 1.0, 1.0);
 	rollCircle->depthTest = false;
 	rotateDectorators->addChild(rollCircle);
 	rollCircle->setMaterialByName("OneSidedLine");
     rollCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX()* 2.0);
+    rollCircle->setForceMaterial(true);
+    rollCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-	
 	rotateDectorators->processInputEvents = true;
 	
 	//pitchGrip = new ScenePrimitive(ScenePrimitive::TYPE_TORUS, 1.55 * 0.5, 0.05, 16, 3);

+ 34 - 23
src/modules/ui/PolyUIElement.cpp

@@ -164,7 +164,6 @@ Label *UILabel::getLabel() {
 
 UIRect::UIRect(String fileName, Number width, Number height) : UIElement() {
 	texture = NULL;
-    localShaderOptions = NULL;
 	loadTexture(fileName);
     initRect(width, height);
     imageWidth = width;
@@ -173,7 +172,6 @@ UIRect::UIRect(String fileName, Number width, Number height) : UIElement() {
 
 UIRect::UIRect(String fileName) : UIElement() {
 	texture = NULL;
-    localShaderOptions = NULL;
 	loadTexture(fileName);
 	if(texture) {	
 		initRect(texture->getWidth(), texture->getHeight());
@@ -190,7 +188,6 @@ UIRect::UIRect(String fileName) : UIElement() {
 
 UIRect::UIRect(Number width, Number height) : UIElement() {
 	texture = NULL;
-    localShaderOptions = NULL;
 	initRect(width, height);
 	imageWidth = 0;
 	imageHeight = 0;
@@ -263,23 +260,17 @@ void UIRect::initRect(Number width, Number height) {
     rectMesh->addIndexedFace(0, 1, 2);
     rectMesh->addIndexedFace(0, 2, 3);
     
-    material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured");
-    localShaderOptions = new ShaderBinding();
+    setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured"));
     
-    localShaderOptions->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
-    
-    localShaderOptions->addAttributeBinding("texCoord", &rectMesh->vertexTexCoordArray);
-    localShaderOptions->addAttributeBinding("position", &rectMesh->vertexPositionArray);
-
     if(texture) {
-        material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit");
-        localShaderOptions->setTextureForParam("diffuse", texture);
+        setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit"));
+        shaderPasses[0].shaderBinding->setTextureForParam("diffuse", texture);
     }
 }
 
 UIRect::~UIRect() {
 	delete rectMesh;
-    delete localShaderOptions;
+    delete shaderPasses[0].shaderBinding;
 }
 
 void UIRect::loadTexture(String fileName) {
@@ -290,29 +281,49 @@ void UIRect::loadTexture(String fileName) {
 	texture = materialManager->createTextureFromFile(fileName, materialManager->clampDefault, false);
     
     if(!texture) {
-        material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured");
+        setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured"));
     } else {
-        material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit");
+        setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit"));
     }
     
-    if(localShaderOptions) {
-        localShaderOptions->setTextureForParam("diffuse", texture);
+    if(shaderPasses.size() > 0) {
+        shaderPasses[0].shaderBinding->setTextureForParam("diffuse", texture);
     }
 }
 
 void UIRect::setTexture(Texture *texture) {
     
     if(!texture) {
-        material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured");
+        setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured"));
     } else {
-        material =  (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit");
+        setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit"));
     }
     
 	this->texture = texture;
-    if(localShaderOptions) {
-        localShaderOptions->setTextureForParam("diffuse", texture);
+    if(shaderPasses[0].shaderBinding) {
+        shaderPasses[0].shaderBinding->setTextureForParam("diffuse", texture);
+    }
+}
+
+void UIRect::setMaterial(Material *material) {
+    
+    for(int i=0; i < shaderPasses.size(); i++) {
+        delete shaderPasses[i].shaderBinding;
     }
-}	
+    shaderPasses.clear();
+    
+    this->material = material;
+    
+    ShaderPass pass;
+    pass.shaderBinding = new ShaderBinding();
+    pass.shader = material->getShaderPass(0).shader;
+    shaderPasses.push_back(pass);
+    
+    shaderPasses[0].shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
+    shaderPasses[0].shaderBinding->addAttributeBinding("texCoord", &rectMesh->vertexTexCoordArray);
+    shaderPasses[0].shaderBinding->addAttributeBinding("position", &rectMesh->vertexPositionArray);
+    
+}
 
 Texture *UIRect::getTexture() {
 	return texture;
@@ -334,7 +345,7 @@ void UIRect::Render(GPUDrawBuffer *buffer) {
     }
     
     drawCall.material = material;
-    drawCall.shaderBinding = localShaderOptions;
+    drawCall.shaderPasses = shaderPasses;
     
     buffer->drawCalls.push_back(drawCall);
 }