summaryrefslogtreecommitdiff
path: root/cel.fs
blob: ef9cd6ab12d71552a8cd9a02c2930b7a0402fdad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#version 330 core

/* input from the vector shader */
in vec3 in_normal;
in vec2 in_texture_coordinate;
in vec3 in_fragment_position;

/* light uniforms */
uniform vec3 ambient_color;

struct point_light {
  vec3 position; /* view position */

  float constant;
  float linear;
  float quadratic;

  vec3 color;
};

struct directional_light {
  vec3 direction;
  vec3 color;
};

#define MAX_POINT_LIGHTS 8
#define MAX_DIRECTIONAL_LIGHTS 8

uniform point_light point_lights[MAX_POINT_LIGHTS];
uniform int n_point_lights;

uniform directional_light directional_lights[MAX_DIRECTIONAL_LIGHTS];
uniform int n_directional_lights;

/* texture uniforms */
uniform sampler2D tex;

/* view matrix */
uniform mat4 view;

out vec4 fragment_color;

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

/* compute phong cel-shader intensity */
float compute_light_intensity(vec3 normal, vec3 light_direction, vec3 view_direction) {
  /* diffuse light */
  float diffuse_intensity = max(dot(normal, light_direction), 0);
  diffuse_intensity = smoothstep(0, 0.01, diffuse_intensity);

  /* specular highlight */
  vec3 reflection_direction = reflect(-light_direction, normal);
  float specular_intensity = pow(max(dot(view_direction, reflection_direction), 0), 256);
  specular_intensity = smoothstep(0.005, 0.01, specular_intensity);

  return diffuse_intensity + specular_intensity;
}

/* compute directional light contribution */
vec3 compute_directional_light(directional_light light, vec3 normal, vec3 view_direction) {
  vec3 light_direction = -vec3(view * vec4(light.direction.xyz, 0.0));
  return light.color * compute_light_intensity(normal, light_direction, view_direction);
}

/* compute point light contribution */
vec3 compute_point_light(point_light light, vec3 normal, vec3 fragment_position, vec3 view_direction) {
  vec3 light_position = vec3(view * vec4(light.position.xyz, 1.0));
  vec3 light_direction = normalize(light_position - fragment_position);

  float light_intensity = compute_light_intensity(normal, light_direction, view_direction);

  /* attenuation */
  float distance = length(light_position - fragment_position);
  float attenuation = 1.0 / (light.constant +
                             light.linear * distance +
                             light.quadratic * distance * distance);

  return attenuation * light.color * light_intensity;
}

void main()
{
  vec3 normal = normalize(in_normal);
  vec3 view_direction = normalize(-in_fragment_position);
  
  vec3 point_light_contrib = vec3(0, 0, 0);
  for (int i=0; i<n_point_lights; i++) {
    point_light_contrib += compute_point_light(point_lights[i],
                                               normal,
                                               in_fragment_position,
                                               view_direction);
  }

  vec3 directional_light_contrib = vec3(0,0,0);
  for (int i=0; i<n_directional_lights; i++) {
    directional_light_contrib += compute_directional_light(directional_lights[i],
                                                           normal,
                                                           view_direction);
  }
  
  /* rim lighting */
  /*float rim_amount = 0.716;
  float rim_threshold = 0.5;
  float rim_norm = 1 - dot(normal, view_direction);
  rim_intensity = smoothstep(rim_amount - 0.01, rim_amount + 0.01, rim_intensity);
  vec3 rim_light = rim_intensity * ambient_color;*/

  vec4 total_light = vec4((ambient_color + point_light_contrib + directional_light_contrib).xyz, 1.0);
  fragment_color = total_light * texture(tex, in_texture_coordinate); 
}