// // The maximum number of lights per-object. Decrease this value if you need some extra performance. // // If you change this, then you must enter 'CelShading.program' and change the '$numLights' // variable to match this definition. #define NUM_LIGHTS 6 // // Vertex program float4 main_vp( float4 iPos : POSITION, float3 iNorm : NORMAL, float2 iUV : TEXCOORD0, out float3 oPos : TEXCOORD0, out float3 oNorm : TEXCOORD1, out float2 oUV : TEXCOORD2, uniform float4x4 worldViewProj ) : POSITION { oPos = iPos.xyz; oNorm = iNorm; oUV = iUV; return mul(worldViewProj, iPos); } // // Colored surface fragment program float4 main_fp( float3 iPos : TEXCOORD0, float3 iNorm : TEXCOORD1, float3 iUV : TEXCOORD2, uniform float3 eyePosition, uniform float4 ambientColor, uniform float4 diffuseColor, uniform float4 specularColor, uniform float4 emissiveColor, uniform float shininess, uniform float3 ambientLight, // Light params uniform float4 lightDiffuse[NUM_LIGHTS], uniform float4 lightSpecular[NUM_LIGHTS], uniform float4 lightPosition[NUM_LIGHTS], uniform float4 lightAttenuation[NUM_LIGHTS], // Texture params uniform sampler1D diffuseRamp : register(s0), uniform sampler1D specRamp : register(s1) ) : COLOR { float4 surfaceColor = float4(ambientLight,1)*ambientColor; float4 specularSurface = 0; for (int i = 0; i < NUM_LIGHTS; i++) { float3 norm = normalize(iNorm); // // Calculate light vector and distance float3 lightVec = 0; if (lightPosition[i].w == 1) lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w; else lightVec = lightPosition[i].xyz; float lightDist = length(lightVec); lightVec = normalize(lightVec); // // Calculate the direction in-between the light direction and the camera's direction. float3 eyeVec = normalize(eyePosition - iPos); float3 halfDir = normalize(lightVec + eyeVec); // // Calculate luminosity based on light attenuation float luminosity = 1.f; if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1) luminosity = 1.f / ( lightAttenuation[i].y + lightAttenuation[i].z*lightDist + lightAttenuation[i].w*(lightDist*lightDist) ); // // Get diffuse component based on the dot product of the normal and the light direction, // multiplied by the luminosity component. float diffComponent = max(dot(norm, lightVec), 0)*luminosity; // // Get specular component based on the dot product of the normal and the half-camera-light // direction, multiplied by the luminosity component. float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity; float diffuse = tex1D(diffuseRamp, diffComponent).r; float specular = tex1D(specRamp, specComponent).r; surfaceColor += diffuse*diffuseColor*lightDiffuse[i]; specularSurface += specular*lightSpecular[i]*specularColor; } return emissiveColor + surfaceColor + specularSurface; } // // Decal + Specular Mapping fragment program float4 mainDecal_fp( float3 iPos : TEXCOORD0, float3 iNorm : TEXCOORD1, float3 iUV : TEXCOORD2, uniform float3 eyePosition, uniform float4 ambientColor, uniform float4 diffuseColor, uniform float4 specularColor, uniform float4 emissiveColor, uniform float shininess, uniform float3 ambientLight, // Light params uniform float4 lightDiffuse[NUM_LIGHTS], uniform float4 lightSpecular[NUM_LIGHTS], uniform float4 lightPosition[NUM_LIGHTS], uniform float4 lightAttenuation[NUM_LIGHTS], // Texture params uniform sampler1D diffuseRamp : register(s0), uniform sampler1D specRamp : register(s1), uniform sampler2D decalTex : register(s2)) : COLOR { float4 surfaceColor = float4(ambientLight,1)*ambientColor; float4 specularSurface = 0; float4 texColor = tex2D(decalTex, iUV); for (int i = 0; i < NUM_LIGHTS; i++) { float3 norm = normalize(iNorm); // // Calculate light vector and distance float3 lightVec = 0; if (lightPosition[i].w == 1) lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w; else lightVec = lightPosition[i].xyz; float lightDist = length(lightVec); lightVec = normalize(lightVec); // // Calculate the direction in-between the light direction and the camera's direction. float3 eyeVec = normalize(eyePosition - iPos); float3 halfDir = normalize(lightVec + eyeVec); // // Calculate luminosity based on light attenuation float luminosity = 1.f; if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1) luminosity = 1.f / ( lightAttenuation[i].y + lightAttenuation[i].z*lightDist + lightAttenuation[i].w*(lightDist*lightDist) ); // // Get diffuse component based on the dot product of the normal and the light direction, // multiplied by the luminosity component. float diffComponent = max(dot(norm, lightVec), 0)*luminosity; // // Get specular component based on the dot product of the normal and the half-camera-light // direction, multiplied by the luminosity component. float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity; float diffuse = tex1D(diffuseRamp, diffComponent).r; float specular = tex1D(specRamp, specComponent).r; surfaceColor += diffuse*diffuseColor*lightDiffuse[i]; specularSurface += specular*lightSpecular[i]*specularColor; } return texColor*(emissiveColor + surfaceColor) + specularSurface; } // // Decal + Specular Mapping fragment program float4 mainDecalSpec_fp( float3 iPos : TEXCOORD0, float3 iNorm : TEXCOORD1, float3 iUV : TEXCOORD2, uniform float3 eyePosition, uniform float4 ambientColor, uniform float4 diffuseColor, uniform float4 specularColor, uniform float4 emissiveColor, uniform float shininess, uniform float3 ambientLight, // Light params uniform float4 lightDiffuse[NUM_LIGHTS], uniform float4 lightSpecular[NUM_LIGHTS], uniform float4 lightPosition[NUM_LIGHTS], uniform float4 lightAttenuation[NUM_LIGHTS], // Texture params uniform sampler1D diffuseRamp : register(s0), uniform sampler1D specRamp : register(s1), uniform sampler2D decalTex : register(s2), uniform sampler2D specMap : register(s3)) : COLOR { float4 surfaceColor = float4(ambientLight,1)*ambientColor; float4 specularSurface = 0; float4 texColor = tex2D(decalTex, iUV); float4 specMapColor = tex2D(specMap, iUV); for (int i = 0; i < NUM_LIGHTS; i++) { float3 norm = normalize(iNorm); // // Calculate light vector and distance float3 lightVec = 0; if (lightPosition[i].w == 1) lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w; else lightVec = lightPosition[i].xyz; float lightDist = length(lightVec); lightVec = normalize(lightVec); // // Calculate the direction in-between the light direction and the camera's direction. float3 eyeVec = normalize(eyePosition - iPos); float3 halfDir = normalize(lightVec + eyeVec); // // Calculate luminosity based on light attenuation float luminosity = 1.f; if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1) luminosity = 1.f / ( lightAttenuation[i].y + lightAttenuation[i].z*lightDist + lightAttenuation[i].w*(lightDist*lightDist) ); // // Get diffuse component based on the dot product of the normal and the light direction, // multiplied by the luminosity component. float diffComponent = max(dot(norm, lightVec), 0)*luminosity; // // Get specular component based on the dot product of the normal and the half-camera-light // direction, multiplied by the luminosity component. float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity; float diffuse = tex1D(diffuseRamp, diffComponent).r; float specular = tex1D(specRamp, specComponent).r; surfaceColor += diffuse*diffuseColor*lightDiffuse[i]; specularSurface += specular*lightSpecular[i]*specularColor; } return texColor*(emissiveColor + surfaceColor) + specMapColor*specularSurface; }