scg3  0.6
bump_frag.glsl
Go to the documentation of this file.
1 /**
2  * \file bump_frag.glsl
3  * \brief Bump mapping fragment shader, uses external function applyTexture().
4  */
5 
6 #version 150
7 
8 const int MAX_NUMBER_OF_LIGHTS = 10;
9 
10 smooth in vec3 ecVertex;
11 smooth in vec4 texCoord0;
12 smooth in vec3 tcView;
13 smooth in vec3 tcSource[MAX_NUMBER_OF_LIGHTS];
14 
15 struct Light {
16  vec4 position;
17  vec4 ambient;
18  vec4 diffuse;
19  vec4 specular;
20  vec4 halfVector; // used as vec3, expected as normalized
21  vec4 spotDirection; // used as vec3, expected as normalized
22  float spotCosCutoff;
23  float spotExponent;
24 };
25 
26 layout(std140) uniform LightBlock {
27  Light lights[MAX_NUMBER_OF_LIGHTS];
28 };
29 
30 struct Material {
31  vec4 emission;
32  vec4 ambient;
33  vec4 diffuse;
34  vec4 specular;
35  float shininess;
36 };
37 
38 layout(std140) uniform MaterialBlock {
39  Material material;
40 };
41 
42 uniform int nLights;
43 uniform vec4 globalAmbientLight;
44 uniform mat4 colorMatrix;
45 uniform sampler2D texture1; // normal map
46 
47 out vec4 fragColor;
48 
49 
50 // --- declarations ---
51 
52 
53 void applyLighting(out vec4 emissionAmbientDiffuse, out vec4 specular);
54 
55 void pointOrDirectionalLight(const in int idx, const in vec3 v, const in vec3 n,
56  inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);
57 
58 void spotLight(const in int idx, const in vec3 v, const in vec3 n,
59  inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);
60 
61 vec4 applyTexture(const in vec4 texCoord, const in vec4 emissionAmbientDiffuse, const in vec4 specular);
62 
63 
64 // --- implementations ---
65 
66 
67 void main(void) {
68 
69  // apply lighting model
70  vec4 emissionAmbientDiffuse, specular;
71  applyLighting(emissionAmbientDiffuse, specular);
72 
73  // apply texture and determine color (to be defined in separate shader)
74  vec4 color = applyTexture(texCoord0, emissionAmbientDiffuse, specular);
75 
76  // transform color by color matrix
77  vec4 transformedColor = colorMatrix * vec4(color.rgb, 1.);
78  transformedColor /= transformedColor.a; // perspective division
79 
80  // set final fragment color
81  fragColor = clamp(vec4(transformedColor.rgb, color.a), 0., 1.);
82 }
83 
84 
85 void applyLighting(out vec4 emissionAmbientDiffuse, out vec4 specular) {
86 
87  // normalized view direction
88  vec3 v = normalize(tcView);
89 
90  // determine normal from normal map
91  vec3 n = normalize(texture(texture1, texCoord0.st).rgb * 2. - 1.);
92 
93  // add contributions of light sources
94  vec4 ambient = vec4(0., 0., 0., 0.);
95  vec4 diffuse = vec4(0., 0., 0., 0.);
96  specular = vec4(0., 0., 0., 0.);
97  for (int i = 0; i < nLights; ++i) {
98  if (lights[i].spotCosCutoff < 0.001) {
99  pointOrDirectionalLight(i, v, n, ambient, diffuse, specular);
100  }
101  else {
102  spotLight(i, v, n, ambient, diffuse, specular);
103  }
104  }
105 
106  // multiply with material parameters, add emission and global ambient light
107  emissionAmbientDiffuse = material.emission
108  + material.ambient * (globalAmbientLight + ambient)
109  + material.diffuse * diffuse;
110  specular *= material.specular;
111 }
112 
113 
114 void pointOrDirectionalLight(const in int idx, const in vec3 v, const in vec3 n,
115  inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
116 
117  // normalized light source direction and half vector
118  vec3 s = normalize(tcSource[idx]);
119  vec3 h = normalize(v + s);
120 
121  // ambient
122  ambient += lights[idx].ambient;
123 
124  // diffuse
125  float sDotN = max(0., dot(s, n));
126  diffuse += lights[idx].diffuse * sDotN;
127 
128  // specular
129  float hDotN = dot(h, n);
130  if (hDotN > 0.) {
131  specular += lights[idx].specular * pow(hDotN, material.shininess);
132  }
133 }
134 
135 
136 void spotLight(const in int idx, const in vec3 v, const in vec3 n,
137  inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
138 
139  // normalized light source direction and half vector
140  vec3 s = normalize(tcSource[idx]);
141  vec3 h = normalize(v + s);
142 
143  // check if surface point is inside spotlight cone
144  float dirDotS = dot(lights[idx].spotDirection.xyz,
145  normalize(ecVertex - lights[idx].position.xyz));
146  if (dirDotS >= lights[idx].spotCosCutoff) {
147 
148  // spot attenuation from center to edges
149  float attenuation = pow(dirDotS, lights[idx].spotExponent);
150 
151  // ambient
152  ambient += attenuation * lights[idx].ambient;
153 
154  // diffuse
155  float sDotN = max(0., dot(s, n));
156  diffuse += attenuation * lights[idx].diffuse * sDotN;
157 
158  // specular
159  float hDotN = dot(h, n);
160  if (hDotN > 0.) {
161  specular += attenuation * lights[idx].specular * pow(hDotN, material.shininess);
162  }
163  }
164 }