uniform int u_num_lights; struct light_t { int type; vec3 diffuse; vec3 specular; vec3 ambient; vec3 pos; vec3 dir; float power; float radius; float innerCone; float outerCone; // falloff float constant; float linear; float quadratic; }; #define MAX_LIGHTS 16 const int LIGHT_DIRECTIONAL = 0; const int LIGHT_POINT = 1; const int LIGHT_SPOT = 2; uniform light_t u_lights[MAX_LIGHTS]; #ifdef SHADING_PHONG vec3 shading_phong(light_t l) { vec3 lightDir; float attenuation = 1.0; if (l.type == LIGHT_DIRECTIONAL) { lightDir = normalize(-l.dir); } else if (l.type == LIGHT_POINT || l.type == LIGHT_SPOT) { vec3 toLight = l.pos - v_position_ws; lightDir = normalize(toLight); float distance = length(toLight); /* fast-reject based on radius */ if (l.radius != 0.0 && distance > l.radius) { return vec3(0,0,0); } attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance)); if (l.type == LIGHT_SPOT) { float angle = dot(l.dir, -lightDir); if (angle > l.outerCone) { float intensity = (angle-l.outerCone)/(l.innerCone-l.outerCone); attenuation *= clamp(intensity, 0.0, 1.0); } else { attenuation = 0.0; } } } // fast-rejection for faraway vertices if (attenuation <= 0.01) { return vec3(0,0,0); } vec3 n = normalize(v_normal_ws); float diffuse = max(dot(n, lightDir), 0.0); vec3 halfVec = normalize(lightDir + u_cam_dir); float specular = pow(max(dot(n, halfVec), 0.0), l.power); return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular); } #endif #ifdef SHADING_VERTEXLIT vec3 shading_vertexlit(light_t l) { vec3 lightDir; float attenuation = 1.0; if (l.type == LIGHT_DIRECTIONAL) { lightDir = normalize(-l.dir); } else if (l.type == LIGHT_POINT || l.type == LIGHT_SPOT) { vec3 toLight = l.pos - v_position_ws; lightDir = normalize(toLight); float distance = length(toLight); /* fast-reject based on radius */ if (l.radius != 0.0 && distance > l.radius) { return vec3(0,0,0); } attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance)); if (l.type == LIGHT_SPOT) { float angle = dot(l.dir, -lightDir); if (angle > l.outerCone) { float intensity = (angle-l.outerCone)/(l.innerCone-l.outerCone); attenuation *= clamp(intensity, 0.0, 1.0); } else { attenuation = 0.0; } } } // fast-rejection for faraway vertices if (attenuation <= 0.01) { return vec3(0,0,0); } vec3 n = normalize(v_normal_ws); float diffuse = max(dot(n, lightDir), 0.0); vec3 halfVec = normalize(lightDir + u_cam_dir); float specular = pow(max(dot(n, halfVec), 0.0), l.power); return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular); } #endif vec3 lighting() { vec3 lit = vec3(0,0,0); #ifndef SHADING_NONE #ifdef SHADING_PHONG for (int i=0; i