Переглянути джерело

Fixed attributes not being bound correctly to global materials

Ivan Safrin 10 роки тому
батько
коміт
bbadf1de99

BIN
assets/default/default.pak


+ 125 - 0
assets/default/default/DefaultUntextured.frag

@@ -0,0 +1,125 @@
+varying vec2 texCoordVar;
+varying vec3 varNormal;
+varying vec4 varPosition;
+
+uniform vec4 diffuse_color;
+uniform vec4 specular_color;
+uniform vec4 entityColor;
+uniform float shininess;
+
+#define MAX_LIGHTS 8
+
+struct LightInfo {
+	vec3 position;
+	vec3 direction;
+	vec4 specular;
+	vec4 diffuse;
+
+	float spotExponent;
+	float spotCosCutoff;
+
+	float constantAttenuation;
+	float linearAttenuation;	
+	float quadraticAttenuation;
+};
+
+uniform LightInfo lights[MAX_LIGHTS];
+
+float calculateAttenuation(in int i, in float dist)
+{
+    return(1.0 / (lights[i].constantAttenuation +
+                  lights[i].linearAttenuation * dist +
+                  lights[i].quadraticAttenuation * dist * dist));
+}
+
+void pointLight(in int i, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	vec4 color = diffuse_color;
+	vec4 matspec = specular_color;
+	float shininess = shininess;
+	vec4 lightspec = lights[i].specular;
+	vec4 lpos = vec4(lights[i].position, 1.0);
+	vec4 s = pos-lpos; 
+	vec4 sn = -normalize(s);
+	
+	vec3 light = sn.xyz;
+	vec3 n = normalize(normal);
+	vec3 r = -reflect(light, n);
+	r = normalize(r);
+	vec3 v = -pos.xyz;
+	v = normalize(v);
+
+	float nDotL = dot(n, sn.xyz);
+	if(nDotL > 0.0) {
+		float dist = length(s);    
+		float attenuation = calculateAttenuation(i, dist);
+
+		diffuse  += color * max(0.0, nDotL) * lights[i].diffuse * attenuation;
+
+	  if (shininess != 0.0) {
+    	specular += lightspec * matspec * pow(max(0.0,dot(r, v)), shininess) * attenuation;
+	  }
+	}
+}
+
+
+void spotLight(in int i, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	vec4 color = diffuse_color;
+	vec4 matspec = specular_color;
+	float shininess = shininess;
+	vec4 lightspec = lights[i].specular;
+	vec4 lpos = vec4(lights[i].position, 1.0);
+	vec4 s = pos-lpos; 
+	vec4 sn = -normalize(s);
+
+	vec3 light = sn.xyz;
+	vec3 n = normalize(normal);
+	vec3 r = -reflect(light, n);
+	r = normalize(r);
+	vec3 v = -pos.xyz;
+	v = normalize(v);
+
+	float cos_outer_cone_angle = (1.0-lights[i].spotExponent) * lights[i].spotCosCutoff;
+	float cos_cur_angle = dot(-normalize(lights[i].direction), sn.xyz);
+	float cos_inner_cone_angle = lights[i].spotCosCutoff;
+
+	float cos_inner_minus_outer_angle = cos_inner_cone_angle - cos_outer_cone_angle;
+	float spot = 0.0;
+	spot = clamp((cos_cur_angle - cos_outer_cone_angle) / cos_inner_minus_outer_angle, 0.0, 1.0);
+	       
+	float nDotL = dot(n, sn.xyz);
+	if(nDotL > 0.0) {
+		float dist = length(s);    
+		float attenuation = calculateAttenuation(i, dist);
+		diffuse  += color * max(0.0, nDotL) * lights[i].diffuse * attenuation * spot;
+
+	  if (shininess != 0.0) {
+    	specular += lightspec * matspec * pow(max(0.0,dot(r, v)), shininess) * attenuation * spot;
+	  }
+	}
+}
+
+void doLights(in int numLights, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	for (int i = 0; i < numLights; i++) {
+		if (lights[i].spotCosCutoff == 180.0) {
+			pointLight(i, normal, pos, diffuse, specular);
+		} else {
+			spotLight(i, normal, pos, diffuse, specular);
+		}
+    }
+}
+
+
+void main()
+{
+	vec4 diffuse_val  = vec4(0.0);
+	vec4 specular_val = vec4(0.0);
+
+	doLights(MAX_LIGHTS, varNormal, varPosition, diffuse_val, specular_val);
+			
+    vec4 color = diffuse_val; 	           
+    color = clamp((color*entityColor) + specular_val, 0.0, 1.0);  
+
+	color.a = entityColor.a * diffuse_color.a;	
+	gl_FragColor = color;
+
+}

+ 8 - 0
assets/default/default/default.mat

@@ -5,6 +5,10 @@
 			<vp source="default/DefaultShader.vert"/>
 			<fp source="default/DefaultShader.frag"/>
 		</shader>
+		<shader type="glsl" name="DefaultUntexturedShader" numPointLights="6" numSpotLights="2">
+			<vp source="default/DefaultShader.vert"/>
+			<fp source="default/DefaultUntextured.frag"/>
+		</shader>		
 		<shader type="glsl" name="Unlit" numPointLights="0" numSpotLights="0">		
 			<vp source="default/Unlit.vert"/>
 			<fp source="default/Unlit.frag"/>
@@ -27,6 +31,10 @@
 		</shader>	
 	</shaders>	
 	<materials>	
+		<material name="Default">
+			<shader name="DefaultUntexturedShader">
+			</shader>
+		</material>				
 		<material name="DefaultTextured">
 			<shader name="DefaultShader">
 			</shader>

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

@@ -249,7 +249,9 @@ namespace Polycode {
 			std::vector<RenderTargetBinding*> inTargetBindings;
 			std::vector<RenderTargetBinding*> outTargetBindings;
 			std::vector<RenderTargetBinding*> colorTargetBindings;
-			std::vector<RenderTargetBinding*> depthTargetBindings;			
+			std::vector<RenderTargetBinding*> depthTargetBindings;
+        
+            Shader *targetShader;
 	};
 
 }

+ 2 - 0
src/core/PolyMaterial.cpp

@@ -225,6 +225,7 @@ void Material::addShaderAtIndex(Shader *shader,ShaderBinding *shaderBinding, int
     ShaderPass newPass;
     newPass.shader = shader;
     newPass.shaderBinding = shaderBinding;
+    shaderBinding->targetShader = shader;
 	shaderPasses.insert(shaderPasses.begin()+shaderIndex, newPass);
 	shader->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);
 }
@@ -245,6 +246,7 @@ void Material::addShader(Shader *shader,ShaderBinding *shaderBinding) {
     ShaderPass newPass;
     newPass.shader = shader;
     newPass.shaderBinding = shaderBinding;
+    shaderBinding->targetShader = shader;
     addShaderPass(newPass);
 }
 

+ 16 - 2
src/core/PolyRenderer.cpp

@@ -214,18 +214,32 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                     
                 }
                 
+                bool rebindAttributes = false;
+                
+                if(localShaderBinding->targetShader != shaderPass.shader) {
+                    localShaderBinding->targetShader = shaderPass.shader;
+                    rebindAttributes = true;
+                }
+                
+                
                 for(int a=0; a < localShaderBinding->getNumAttributeBindings(); a++) {
                     
                     AttributeBinding *attributeBinding = localShaderBinding->getAttributeBinding(a);
                     
                     if(attributeBinding) {
-                        if(attributeBinding->enabled) {
+                        if(attributeBinding->enabled  || rebindAttributes) {
+                            
+                            if(rebindAttributes) {
+                                attributeBinding->attribute = NULL;
+                                attributeBinding->enabled = true;
+                            }
                             
                             if(!attributeBinding->attribute) {
                                 attributeBinding->attribute = shaderPass.shader->getAttribPointer(attributeBinding->name);
                             }
+                            
                             if(attributeBinding->attribute) {
-                                
+                                attributeBinding->enabled = true;
                                 if(attributeBinding->vertexData->data.size() / attributeBinding->vertexData->countPerVertex >= buffer->drawCalls[i].numVertices) {
                                     graphicsInterface->setAttributeInShader(shaderPass.shader, attributeBinding->attribute, attributeBinding);
                                 }

+ 2 - 1
src/core/PolySceneMesh.cpp

@@ -202,7 +202,8 @@ void SceneMesh::setMaterial(Material *material) {
     
     for(int i=0; i < material->getNumShaderPasses(); i++)  {
         ShaderPass shaderPass = material->getShaderPass(i);
-        shaderPass.shaderBinding = new ShaderBinding();        
+        shaderPass.shaderBinding = new ShaderBinding();
+        shaderPass.shaderBinding->targetShader = shaderPass.shader;
         shaderPass.shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
         shaderPass.setExpectedAttributes(mesh);
         shaderPasses.push_back(shaderPass);

+ 1 - 1
src/core/PolyShader.cpp

@@ -103,7 +103,7 @@ void ShaderProgram::reloadResource() {
 }
 
 
-ShaderBinding::ShaderBinding() {
+ShaderBinding::ShaderBinding() : targetShader(NULL) {
 }
 
 ShaderBinding::~ShaderBinding() {

+ 2 - 0
src/ide/PolycodeEntityEditor.cpp

@@ -1568,6 +1568,7 @@ void EntityEditorMainView::handleEvent(Event *event) {
             {
                 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));
                 }
@@ -1790,6 +1791,7 @@ void EntityEditorMainView::setOverlayWireframeRecursive(Entity *targetEntity, bo
                 wireframePass.shader = (Shader*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_SHADER, "UnlitWireframe");
                 wireframePass.wireframe = true;
                 wireframePass.shaderBinding = new ShaderBinding();
+                wireframePass.shaderBinding->targetShader = wireframePass.shader;
                 wireframePass.blendingMode = Renderer::BLEND_MODE_NORMAL;
                 wireframePass.setExpectedAttributes(sceneMesh->getMesh());
                 wireframePass.shaderBinding->addParam(ProgramParam::PARAM_COLOR, "wireframeColor")->setColor(Color(0.5, 0.6, 1.0, 0.75));

+ 1 - 0
src/modules/ui/PolyUIElement.cpp

@@ -322,6 +322,7 @@ void UIRect::setMaterial(Material *material) {
     
     ShaderPass pass;
     pass.shaderBinding = new ShaderBinding();
+    pass.shaderBinding->targetShader = pass.shader;
     pass.shader = material->getShaderPass(0).shader;
     shaderPasses.push_back(pass);