136 lines
3.7 KiB
Plaintext
136 lines
3.7 KiB
Plaintext
|
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<u_num_lights; i++) {
|
||
|
lit += shading_phong(u_lights[i]);
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef SHADING_VERTEXLIT
|
||
|
for (int i=0; i<u_num_lights; i++) {
|
||
|
lit += shading_vertexlit(u_lights[i]);
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef SHADING_PBR
|
||
|
#endif
|
||
|
#endif
|
||
|
return lit;
|
||
|
}
|