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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#version 330 core
// Uniforms for shape information
in vec3 worldSpace_pos;
in vec3 worldSpace_norm;
in vec2 tex_coord;
in float visibility;
uniform vec3 skyColor;
// Object Material Data
uniform int colorSource; // 0 = solid color (objColor), 1 = texture color (objTexture), 2 = per-vertex color (vertColor)
uniform vec3 objColor;
uniform sampler2D objTexture;
in vec3 vertColor;
uniform float shininess;
// Camera uniform
uniform vec3 worldSpace_camPos;
// Global Data
uniform vec3 coeffs; // vec3(ka, kd, ks)
// Light Data
uniform int lightType[16]; // 0 = point light, 1 = directional light
uniform vec3 lightColor[16];
uniform vec3 lightFunction[16]; // Attenuation coefficients
uniform vec3 worldSpace_lightPos[16]; //Light Positions
uniform vec3 worldSpace_lightDir[16]; //Light Directions
uniform int numLights; // Max number of lights = 8
out vec4 fragColor;
vec3 getToLight(int lightIndex) {
int LIGHT_POINT = 0;
int LIGHT_DIRECTIONAL = 1;
if (lightType[lightIndex] == LIGHT_POINT) {
return normalize(worldSpace_lightPos[lightIndex] - worldSpace_pos);
}
else if (lightType[lightIndex] == LIGHT_DIRECTIONAL) {
return normalize(-worldSpace_lightDir[lightIndex]);
}
return vec3(0);
}
float attenuationFactor(int lightIndex) {
int LIGHT_POINT = 0;
if (lightType[lightIndex] == LIGHT_POINT) {
vec3 coeffs = lightFunction[lightIndex];
float d = length(worldSpace_lightPos[lightIndex] - worldSpace_pos);
return 1.0 / (coeffs.x + coeffs.y * d + coeffs.z * d * d);
}
return 1;
}
float computeDiffuseIntensity(vec3 worldSpace_toLight) {
// Dot product to get diffuse intensity
return max(dot(worldSpace_toLight, normalize(worldSpace_norm)), 0);
}
float computeSpecularIntensity(vec3 worldSpace_toLight, vec3 worldSpace_toEye) {
// Guard against pow weirdness when exponent is 0
if (shininess == 0) {
return 0;
}
//reflect toLight
vec3 worldSpace_toLightReflected = reflect(-worldSpace_toLight, normalize(worldSpace_norm));
//Compute specular intensity using toEye, reflected light, and shininess
return pow(max(dot(worldSpace_toLightReflected, worldSpace_toEye), 0), shininess);
}
void main() {
// Declare ambient, diffuse, and specular terms
vec3 ambi = vec3(coeffs.x);
vec3 diff = vec3(0.0);
vec3 spec = vec3(0.0);
// Compute worldSpace_toEye Vector for specular intensity computation;
vec3 worldSpace_toEye = normalize(worldSpace_camPos - worldSpace_pos);
// Compute per-light diffuse and specular contribution
for(int i = 0; i<numLights; i+= 1){
// get direction vector to light based on light type
vec3 worldSpace_toLight = getToLight(i);
float diffuse_intensity = computeDiffuseIntensity(worldSpace_toLight);
float specular_intensity = computeSpecularIntensity(worldSpace_toLight, worldSpace_toEye);
float att = attenuationFactor(i);
diff = diff + diffuse_intensity * lightColor[i] * att;
spec = spec + specular_intensity * lightColor[i] * att;
}
// Apply global coefficients and object color to the diffuse and specular components
diff = diff * vec3(coeffs.y);
spec = spec * vec3(coeffs.z);
// Color generated only from light intensities and colors
vec3 tempColor = clamp(ambi + diff + spec, 0, 1);
// Apply correct object color
if (colorSource == 0 ) {
fragColor = vec4(tempColor * objColor, 1.0);
}
else if (colorSource == 1){
fragColor = vec4(tempColor * vec3(texture(objTexture, tex_coord)), 1.0);
}
else if (colorSource == 2) {
fragColor = vec4(tempColor * vertColor, 1.0);
}
else{
fragColor = vec4(tempColor, 1.0);
}
// mix actual color with fog color
// fragColor = mix(vec4(.77f, .85f, .99f, 1.f), fragColor, visibility);
}
|