3 * \brief Bump mapping fragment shader, uses external function applyTexture().
8 const int MAX_NUMBER_OF_LIGHTS = 10;
10 smooth in vec3 ecVertex;
11 smooth in vec4 texCoord0;
12 smooth in vec3 tcView;
13 smooth in vec3 tcSource[MAX_NUMBER_OF_LIGHTS];
20 vec4 halfVector; // used as vec3, expected as normalized
21 vec4 spotDirection; // used as vec3, expected as normalized
26 layout(std140) uniform LightBlock {
27 Light lights[MAX_NUMBER_OF_LIGHTS];
38 layout(std140) uniform MaterialBlock {
43 uniform vec4 globalAmbientLight;
44 uniform mat4 colorMatrix;
45 uniform sampler2D texture1; // normal map
50 // --- declarations ---
53 void applyLighting(out vec4 emissionAmbientDiffuse, out vec4 specular);
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);
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);
61 vec4 applyTexture(const in vec4 texCoord, const in vec4 emissionAmbientDiffuse, const in vec4 specular);
64 // --- implementations ---
69 // apply lighting model
70 vec4 emissionAmbientDiffuse, specular;
71 applyLighting(emissionAmbientDiffuse, specular);
73 // apply texture and determine color (to be defined in separate shader)
74 vec4 color = applyTexture(texCoord0, emissionAmbientDiffuse, specular);
76 // transform color by color matrix
77 vec4 transformedColor = colorMatrix * vec4(color.rgb, 1.);
78 transformedColor /= transformedColor.a; // perspective division
80 // set final fragment color
81 fragColor = clamp(vec4(transformedColor.rgb, color.a), 0., 1.);
85 void applyLighting(out vec4 emissionAmbientDiffuse, out vec4 specular) {
87 // normalized view direction
88 vec3 v = normalize(tcView);
90 // determine normal from normal map
91 vec3 n = normalize(texture(texture1, texCoord0.st).rgb * 2. - 1.);
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);
102 spotLight(i, v, n, ambient, diffuse, specular);
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;
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) {
117 // normalized light source direction and half vector
118 vec3 s = normalize(tcSource[idx]);
119 vec3 h = normalize(v + s);
122 ambient += lights[idx].ambient;
125 float sDotN = max(0., dot(s, n));
126 diffuse += lights[idx].diffuse * sDotN;
129 float hDotN = dot(h, n);
131 specular += lights[idx].specular * pow(hDotN, material.shininess);
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) {
139 // normalized light source direction and half vector
140 vec3 s = normalize(tcSource[idx]);
141 vec3 h = normalize(v + s);
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) {
148 // spot attenuation from center to edges
149 float attenuation = pow(dirDotS, lights[idx].spotExponent);
152 ambient += attenuation * lights[idx].ambient;
155 float sDotN = max(0., dot(s, n));
156 diffuse += attenuation * lights[idx].diffuse * sDotN;
159 float hDotN = dot(h, n);
161 specular += attenuation * lights[idx].specular * pow(hDotN, material.shininess);