2023-08-10 21:53:51 +00:00
|
|
|
uniform mat4 model, view;
|
|
|
|
uniform sampler2D u_texture2d;
|
|
|
|
uniform vec3 u_coefficients_sh[9];
|
|
|
|
uniform bool u_textured = true;
|
|
|
|
uniform bool u_lit = false;
|
|
|
|
uniform bool u_matcaps = false;
|
|
|
|
uniform vec4 u_diffuse = vec4(1.0,1.0,1.0,1.0);
|
|
|
|
|
2023-12-01 15:05:38 +00:00
|
|
|
// lightmapping
|
|
|
|
uniform sampler2D u_lightmap;
|
|
|
|
uniform bool u_texlit;
|
|
|
|
uniform bool u_texmod = true;
|
|
|
|
uniform float u_litboost = 1.0;
|
|
|
|
|
2023-08-10 21:53:51 +00:00
|
|
|
in vec3 v_position;
|
2023-09-23 18:53:25 +00:00
|
|
|
in vec3 v_position_ws;
|
2023-09-23 15:22:48 +00:00
|
|
|
#ifdef RIM
|
2023-09-19 04:50:53 +00:00
|
|
|
uniform mat4 M; // RIM
|
|
|
|
uniform vec3 u_rimcolor = vec3(0.2,0.2,0.2);
|
|
|
|
uniform vec3 u_rimrange = vec3(0.11,0.98,0.5);
|
2023-09-21 10:10:36 +00:00
|
|
|
uniform vec3 u_rimpivot = vec3(0,0,0);
|
|
|
|
uniform bool u_rimambient = true;
|
2023-08-10 21:53:51 +00:00
|
|
|
#endif
|
|
|
|
in vec3 v_normal, v_normal_ws;
|
2023-12-01 15:05:38 +00:00
|
|
|
in vec2 v_texcoord, v_texcoord2;
|
2023-08-10 21:53:51 +00:00
|
|
|
in vec4 v_color;
|
|
|
|
out vec4 fragcolor;
|
|
|
|
|
2023-09-10 14:46:07 +00:00
|
|
|
|
2023-08-10 21:53:51 +00:00
|
|
|
{{include-shadowmap}}
|
|
|
|
in vec4 vpeye;
|
|
|
|
in vec4 vneye;
|
|
|
|
in vec4 sc;
|
|
|
|
vec4 shadowing() {
|
2023-09-10 14:46:07 +00:00
|
|
|
return shadowmap(vpeye, vneye, v_texcoord, sc);
|
2023-08-10 21:53:51 +00:00
|
|
|
}
|
|
|
|
|
2023-09-23 18:53:25 +00:00
|
|
|
uniform vec3 u_cam_pos;
|
|
|
|
uniform vec3 u_cam_dir;
|
|
|
|
|
2023-09-23 15:22:48 +00:00
|
|
|
uniform int u_num_lights;
|
|
|
|
|
|
|
|
struct light_t {
|
|
|
|
int type;
|
2023-09-23 18:53:25 +00:00
|
|
|
vec3 diffuse;
|
|
|
|
vec3 specular;
|
|
|
|
vec3 ambient;
|
2023-09-23 15:22:48 +00:00
|
|
|
vec3 pos;
|
|
|
|
vec3 dir;
|
2023-09-23 20:00:22 +00:00
|
|
|
float power;
|
2023-09-23 18:53:25 +00:00
|
|
|
float innerCone;
|
|
|
|
float outerCone;
|
|
|
|
|
|
|
|
// falloff
|
|
|
|
float constant;
|
|
|
|
float linear;
|
|
|
|
float quadratic;
|
2023-09-23 15:22:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#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];
|
|
|
|
|
2023-09-23 18:53:25 +00:00
|
|
|
#ifdef SHADING_PHONG
|
|
|
|
vec3 shading_phong(light_t l) {
|
2023-09-23 15:22:48 +00:00
|
|
|
vec3 lightDir;
|
|
|
|
float attenuation = 1.0;
|
|
|
|
|
|
|
|
if (l.type == LIGHT_DIRECTIONAL) {
|
|
|
|
lightDir = normalize(-l.dir);
|
2023-09-25 04:10:36 +00:00
|
|
|
} else if (l.type == LIGHT_POINT || l.type == LIGHT_SPOT) {
|
2023-09-23 18:53:25 +00:00
|
|
|
vec3 toLight = l.pos - v_position_ws;
|
|
|
|
lightDir = normalize(toLight);
|
|
|
|
float distance = length(toLight);
|
|
|
|
attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance));
|
2023-09-25 04:10:36 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-09-23 18:53:25 +00:00
|
|
|
}
|
2023-09-23 15:22:48 +00:00
|
|
|
}
|
|
|
|
|
2023-09-23 20:00:22 +00:00
|
|
|
// 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);
|
2023-09-23 18:53:25 +00:00
|
|
|
|
|
|
|
vec3 halfVec = normalize(lightDir + u_cam_dir);
|
2023-09-23 20:00:22 +00:00
|
|
|
float specular = pow(max(dot(n, halfVec), 0.0), l.power);
|
2023-09-23 15:22:48 +00:00
|
|
|
|
2023-09-23 18:53:25 +00:00
|
|
|
return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular);
|
|
|
|
}
|
|
|
|
#endif
|
2023-09-23 15:22:48 +00:00
|
|
|
|
2023-09-23 18:53:25 +00:00
|
|
|
vec3 lighting() {
|
|
|
|
vec3 lit = vec3(0,0,0);
|
|
|
|
#ifndef SHADING_NONE
|
|
|
|
for (int i=0; i<u_num_lights; i++) {
|
|
|
|
#ifdef SHADING_PHONG
|
|
|
|
lit += shading_phong(u_lights[i]);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return lit;
|
2023-09-23 15:22:48 +00:00
|
|
|
}
|
2023-09-10 14:46:07 +00:00
|
|
|
|
2023-12-01 15:05:38 +00:00
|
|
|
vec3 sh_lighting(vec3 n) {
|
|
|
|
vec3 SHLightResult[9];
|
|
|
|
SHLightResult[0] = 0.282095f * u_coefficients_sh[0];
|
|
|
|
SHLightResult[1] = -0.488603f * u_coefficients_sh[1] * n.y;
|
|
|
|
SHLightResult[2] = 0.488603f * u_coefficients_sh[2] * n.z;
|
|
|
|
SHLightResult[3] = -0.488603f * u_coefficients_sh[3] * n.x;
|
|
|
|
SHLightResult[4] = 1.092548f * u_coefficients_sh[4] * n.x * n.y;
|
|
|
|
SHLightResult[5] = -1.092548f * u_coefficients_sh[5] * n.y * n.z;
|
|
|
|
SHLightResult[6] = 0.315392f * u_coefficients_sh[6] * (3.0f * n.z * n.z - 1.0f);
|
|
|
|
SHLightResult[7] = -1.092548f * u_coefficients_sh[7] * n.x * n.z;
|
|
|
|
SHLightResult[8] = 0.546274f * u_coefficients_sh[8] * (n.x * n.x - n.y * n.y);
|
|
|
|
vec3 result = vec3(0.0);
|
|
|
|
for (int i = 0; i < 9; ++i)
|
|
|
|
result += SHLightResult[i];
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LIGHTMAP_BAKING
|
|
|
|
void main() {
|
|
|
|
vec3 n = normalize(v_normal_ws);
|
|
|
|
vec4 diffuse;
|
|
|
|
|
|
|
|
if(u_textured) {
|
|
|
|
diffuse = texture(u_texture2d, v_texcoord);
|
|
|
|
} else {
|
|
|
|
diffuse = u_diffuse; // * v_color;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u_texlit) {
|
|
|
|
vec4 litsample = texture(u_lightmap, v_texcoord);
|
|
|
|
diffuse *= litsample;
|
|
|
|
}
|
|
|
|
|
|
|
|
fragcolor = vec4(diffuse.rgb*u_litboost, 1.0);
|
|
|
|
}
|
|
|
|
#else
|
2023-08-10 21:53:51 +00:00
|
|
|
void main() {
|
2023-09-23 20:00:22 +00:00
|
|
|
vec3 n = normalize(v_normal_ws);
|
2023-09-23 15:22:48 +00:00
|
|
|
|
|
|
|
vec4 lit = vec4(1.0, 1.0, 1.0, 1.0);
|
|
|
|
// SH lighting
|
2023-12-01 15:05:38 +00:00
|
|
|
if (!u_texlit) {
|
|
|
|
vec3 result = sh_lighting(n);
|
2023-09-23 15:22:48 +00:00
|
|
|
if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) lit = vec4(result, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// analytical lights (phong shading)
|
2023-09-23 18:53:25 +00:00
|
|
|
lit += vec4(lighting(), 0.0);
|
2023-09-23 15:22:48 +00:00
|
|
|
|
|
|
|
// base
|
|
|
|
vec4 diffuse;
|
|
|
|
|
|
|
|
if(u_matcaps) {
|
|
|
|
vec2 muv = vec2(view * vec4(v_normal_ws, 0))*0.5+vec2(0.5,0.5); // normal (model space) to view space
|
|
|
|
diffuse = texture(u_texture2d, vec2(muv.x, 1.0-muv.y));
|
2023-08-10 21:53:51 +00:00
|
|
|
} else if(u_textured) {
|
|
|
|
diffuse = texture(u_texture2d, v_texcoord);
|
2023-12-01 11:01:03 +00:00
|
|
|
} else {
|
|
|
|
diffuse = u_diffuse; // * v_color;
|
2023-09-23 15:22:48 +00:00
|
|
|
}
|
2023-12-01 15:05:38 +00:00
|
|
|
|
|
|
|
if (u_texlit) {
|
|
|
|
vec4 litsample = texture(u_lightmap, v_texcoord);
|
|
|
|
|
|
|
|
if (u_texmod) {
|
|
|
|
diffuse *= litsample;
|
|
|
|
} else {
|
|
|
|
diffuse += litsample;
|
|
|
|
}
|
|
|
|
|
|
|
|
diffuse.rgb += sh_lighting(n);
|
|
|
|
}
|
2023-09-23 15:22:48 +00:00
|
|
|
|
|
|
|
// lighting mix
|
|
|
|
fragcolor = diffuse * lit * shadowing();
|
|
|
|
|
|
|
|
// rimlight
|
|
|
|
#ifdef RIM
|
2023-12-01 11:01:03 +00:00
|
|
|
{
|
|
|
|
vec3 n = normalize(mat3(M) * v_normal); // convert normal to view space
|
|
|
|
vec3 p = (M * vec4(v_position,1.0)).xyz; // convert position to view space
|
|
|
|
vec3 v = vec3(0,-1,0);
|
|
|
|
if (!u_rimambient) {
|
|
|
|
v = normalize(u_rimpivot-p);
|
|
|
|
}
|
|
|
|
float rim = 1.0 - max(dot(v,n), 0.0);
|
|
|
|
vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z));
|
|
|
|
fragcolor += vec4(col, 1.0);}
|
2023-09-23 15:22:48 +00:00
|
|
|
#endif
|
2023-12-01 15:05:38 +00:00
|
|
|
}
|
|
|
|
#endif
|