// // Shader.vsh // myDungeon! // // Created by Gabriel Fernandes on 4/30/13. // Copyright (c) 2013 VISGRAF Laboratory. All rights reserved. // #define NLIGHTS XNLIGHT #define NLIGHTPROPS XNLPROPS attribute vec4 position; // vertex positions attribute vec3 normal; // Normals attribute vec3 uvChannel01; // UV Channel 01 varying highp vec4 colorVarying; // Color for fragment shader varying vec2 uvTexCoord01; // uv Texture coordinates... // I should use the standard bult-in types... for Model, Projection... uniform mat4 modelViewProjectionMatrix; // The full model*projection... for final vertex position uniform mat4 modelMatrix; // Clean model matrix.. no projection... for lights uniform mat3 normalMatrix; // Invert Transpose model matrix... for normals uniform highp float lights[NLIGHTS*NLIGHTPROPS]; // All light properties are here uniform highp float modelMaterial[4]; // Material properties... float applyAttDecay (int decayType, float currentDecay) { if (decayType == 1) { return currentDecay; } if (decayType == 2) { return (currentDecay * currentDecay); } return currentDecay; // Unknown option return default... (Linear) } float calcAttenuation (float lengthX, int lightNum) { bool useNear = bool(lights[lightNum*NLIGHTPROPS+7]/1.0); bool useFar = bool(lights[lightNum*NLIGHTPROPS+6]/1.0); float nAttX = lights[lightNum*NLIGHTPROPS+8]/1.0; float nAttY = lights[lightNum*NLIGHTPROPS+9]/1.0; float fAttX = lights[lightNum*NLIGHTPROPS+10]/1.0; float fAttY = lights[lightNum*NLIGHTPROPS+11]/1.0; vec2 nearAtt = vec2(nAttX,nAttY); vec2 farAtt = vec2(fAttX,fAttY); int attDecayType = int(lights[lightNum*NLIGHTPROPS+12]/1.0); //1 = Linear, 2 = Exponential... float sizeOfFar = farAtt[1] - farAtt[0]; float sizeOfNear = nearAtt[1] - nearAtt[0]; if (farAtt[0] < nearAtt[1]) { farAtt[0] = nearAtt[1]; farAtt[1] = farAtt[0] + sizeOfFar; } // The lenght can be in 3 places, Near/Far/InBetween // Where Am I? if (useNear) { if (lengthX <= nearAtt[0]) { return 0.0; } if (lengthX > nearAtt[0] && lengthX < nearAtt[1]) { float curPos = lengthX - nearAtt[0]; return applyAttDecay(attDecayType,curPos/sizeOfNear); // Growing light... } if (!useFar) { if (lengthX >= nearAtt[1]) { return 1.0; } } } if (useFar) { if (lengthX >= farAtt[1]) { return 0.0; } if (lengthX > farAtt[0] && lengthX < farAtt[1]) { float curPos = lengthX - farAtt[0]; return applyAttDecay(attDecayType,(1.0 - curPos/sizeOfFar)); // Dimming light.. } if (!useNear) { if (lengthX <= farAtt[0]) { return 1.0; } } } return 1.0; // in the middle or not using attenuation... } void main() { // normalMatrix is the light position in this modelspace to result the -normal vertex // vector as seen from the light. vec3 eyeNormal = normalize(normalMatrix * -normal); // Default grey color... vec4 totalDiffuse = vec4(0.0, 0.0, 0.0, 1.0); vec4 vPosTemp = modelMatrix * position; // The vertex4 position without projection/view vec3 vPos = vec3(vPosTemp[0], vPosTemp[1], vPosTemp[2]); // The vertex3 position without projection/view bool useDiffuseMap = bool(modelMaterial[3]/1.0); vec4 diffuseColor = vec4(modelMaterial[0]/1.0, modelMaterial[1]/1.0, modelMaterial[2]/1.0, 1.0); for (int i = 0; i < NLIGHTS; i++) { float r,g,b; r = lights[i*NLIGHTPROPS+0]/1.0; g = lights[i*NLIGHTPROPS+1]/1.0; b = lights[i*NLIGHTPROPS+2]/1.0; vec4 lColor = vec4(r,g,b,1.0); bool enabled = bool(lights[i*NLIGHTPROPS+4]/1.0); if (enabled) { float multiplier = lights[i*NLIGHTPROPS+3]/1.0; float lPosX = lights[i*NLIGHTPROPS+17]/1.0; float lPosY = lights[i*NLIGHTPROPS+18]/1.0; float lPosZ = lights[i*NLIGHTPROPS+19]/1.0; vec3 lPos = vec3(lPosX,lPosY,lPosZ); vec3 lDir = vPos - lPos; // Just crappy simple attenuation.. float lengthX = length(lDir); float attenX = calcAttenuation(lengthX,i); // How much light touches de vertex float nDotVPX = max(0.0, dot(eyeNormal, normalize(lDir))); if (nDotVPX > 0.9) { nDotVPX = nDotVPX * 2.0; // Adding some specular... } // Add it all up... for this light lColor = (lColor * multiplier) * nDotVPX * attenX; } else { lColor = vec4(0.0, 0.0, 0.0, 0.0); } // Add it to the total.. totalDiffuse = totalDiffuse + lColor; } uvTexCoord01 = vec2(uvChannel01[0]/1.0,uvChannel01[1]/1.0); if (useDiffuseMap) { colorVarying = totalDiffuse; } else { colorVarying = totalDiffuse * diffuseColor; } gl_Position = modelViewProjectionMatrix * position; }