11.2 - Surface Colors¶
Light reflects from a surface into a camera which allows us to “see” objects. The previous chapter discussed three types of light reflection: ambient, diffuse, and specular reflection and it was assumed that a single color could describe a surface’s properties. However, each type of reflection interacts with a surface in slightly different ways and using a single color for an object can’t capture the true nature of these different types of reflection.
Researchers took various types of physical objects and precisely measured light reflection for ambient, diffuse, and specular reflection. Some of their results are listed below. Instead of storing a single color for a surface, a specific color for each type of light reflection is stored. This provides more realistic visual results. In your fragment shader calculations you would use the appropriate color for each type of light reflection.
Examples of Surface Colors [1]¶
Material | Ambient color | Diffuse color | Specular color | Shininess |
---|---|---|---|---|
Brass | 0.329412
0.223529
0.027451
1.0
|
0.780392
0.568627
0.113725
1.0
|
0.992157
0.941176
0.807843
1.0
|
27.8974 |
Bronze | 0.2125
0.1275
0.054
1.0
|
0.714
0.4284
0.18144
1.0
|
0.393548
0.271906
0.166721
1.0
|
25.6 |
Polished Bronze | 0.25
0.148
0.06475
1.0
|
0.4
0.2368
0.1036
1.0
|
0.774597
0.458561
0.200621
1.0
|
76.8 |
Chrome | 0.25
0.25
0.25
1.0
|
0.4
0.4
0.4
1.0
|
0.774597
0.774597
0.774597
1.0
|
76.8 |
Copper | 0.19125
0.0735
0.0225
1.0
|
0.7038
0.27048
0.0828
1.0
|
0.256777
0.137622
0.086014
1.0
|
12.8 |
Polished Copper | 0.2295
0.08825
0.0275
1.0
|
0.5508
0.2118
0.066
1.0
|
0.580594
0.223257
0.0695701
1.0
|
51.2 |
Gold | 0.24725
0.1995
0.0745
1.0
|
0.75164
0.60648
0.22648
1.0
|
0.628281
0.555802
0.366065
1.0
|
51.2 |
Polished Gold | 0.24725
0.2245
0.0645
1.0
|
0.34615
0.3143
0.0903
1.0
|
0.797357
0.723991
0.208006
1.0
|
83.2 |
Pewter | 0.105882
0.058824
0.113725
1.0
|
0.427451
0.470588
0.541176
1.0
|
0.333333
0.333333
0.521569
1.0
|
9.84615 |
Silver | 0.19225
0.19225
0.19225
1.0
|
0.50754
0.50754
0.50754
1.0
|
0.508273
0.508273
0.508273
1.0
|
51.2 |
Polished Silver | 0.23125
0.23125
0.23125
1.0
|
0.2775
0.2775
0.2775
1.0
|
0.773911
0.773911
0.773911
1.0
|
89.6 |
Emerald | 0.0215
0.1745
0.0215
0.55
|
0.07568
0.61424
0.07568
0.55
|
0.633
0.727811
0.633
0.55
|
76.8 |
Jade | 0.135
0.2225
0.1575
0.95
|
0.54
0.89
0.63
0.95
|
0.316228
0.316228
0.316228
0.95
|
12.8 |
Obsidian | 0.05375
0.05
0.06625
0.82
|
0.18275
0.17
0.22525
0.82
|
0.332741
0.328634
0.346435
0.82
|
38.4 |
Pearl | 0.25
0.20725
0.20725
0.922
|
1.0
0.829
0.829
0.922
|
0.296648
0.296648
0.296648
0.922
|
11.264 |
Ruby | 0.1745
0.01175
0.01175
0.55
|
0.61424
0.04136
0.04136
0.55
|
0.727811
0.626959
0.626959
0.55
|
76.8 |
Turquoise | 0.1
0.18725
0.1745
0.8
|
0.396
0.74151
0.69102
0.8
|
0.297254
0.30829
0.306678
0.8
|
12.8 |
Black Plastic | 0.0
0.0
0.0
1.0
|
0.01
0.01
0.01
1.0
|
0.50
0.50
0.50
1.0
|
32 |
Black Rubber | 0.02
0.02
0.02
1.0
|
0.01
0.01
0.01
1.0
|
0.4
0.4
0.4
1.0
|
10 |
A WebGL Example Program¶
In the following WebGL program the left canvas is rendered using a single color for the model. The specific color is the “diffuse color” listed in the above chart. The fragment shader used for the left rendering is described in lesson 10.6. The canvas on the right is rendered using the distinct colors list in the above chart.
Experiment with Surface Colors
Single Diffuse Color Ambient, Diffuse, & Specular Colorslight position(3.0, 0.0, 5.0) | light color (1.00, 1.00, 1.00) | |
X: -5.0 +5.0 | Red: | 0.0 1.0 |
Y: -5.0 +5.0 | Green: | 0.0 1.0 |
Z: -5.0 +5.0 | Blue: | 0.0 1.0 |
ambient intensities (0.30, 0.30, 0.30) |
|
Red: | 0.0 1.0 |
Green: | 0.0 1.0 |
Blue: | 0.0 1.0 |
Change all intensities at once. |
Brass Bronze Gold Jade Black Plastic |
Open this webgl demo program in a new tab or window
Fragment Shader¶
Here is the fragment shader used to render the right canvas above. The specific changes are discussion in the comments below.
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 | // Fragment shader program
precision mediump int;
precision mediump float;
// Light model
uniform vec3 u_Light_position;
uniform vec3 u_Light_color;
uniform vec4 u_Ambient_intensities;
uniform vec4 u_Model_ambient;
uniform vec4 u_Model_diffuse;
uniform vec4 u_Model_specular;
uniform float u_Model_shininess;
// Data coming from the vertex shader
varying vec3 v_Vertex;
varying vec3 v_Normal;
void main() {
vec4 ambient_color;
vec4 specular_color;
vec4 diffuse_color;
vec3 to_light;
vec3 fragment_normal;
vec3 reflection;
vec3 to_camera;
float cos_angle;
vec4 color;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// AMBIENT calculations
ambient_color = u_Ambient_intensities * u_Model_ambient;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// General calculations needed for both specular and diffuse lighting
// Calculate a vector from the fragment location to the light source
to_light = u_Light_position - v_Vertex;
to_light = normalize( to_light );
// The fragment's normal vector is being interpolated across the
// geometric primitive which can make it un-normalized. So normalize it.
fragment_normal = normalize( v_Normal);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// DIFFUSE calculations
// Calculate the cosine of the angle between the vertex's normal
// vector and the vector going to the light.
cos_angle = dot(fragment_normal, to_light);
cos_angle = clamp(cos_angle, 0.0, 1.0);
// Scale the color of this fragment based on its angle to the light.
diffuse_color = u_Model_diffuse * vec4(u_Light_color, 1.0) * cos_angle;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// SPECULAR calculations
// Calculate the reflection vector
reflection = 2.0 * dot(fragment_normal,to_light) * fragment_normal
- to_light;
reflection = normalize( reflection );
// Calculate a vector from the fragment location to the camera.
// The camera is at the origin, so just negate the fragment location
to_camera = -1.0 * v_Vertex;
to_camera = normalize( to_camera );
// Calculate the cosine of the angle between the reflection vector
// and the vector going to the camera.
cos_angle = dot(reflection, to_camera);
cos_angle = clamp(cos_angle, 0.0, 1.0);
cos_angle = pow(cos_angle, u_Model_shininess);
// If this fragment gets a specular reflection, use the light's color,
// otherwise use the objects's color
specular_color = vec4(u_Light_color, 1.0) * u_Model_specular * cos_angle;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// COMBINED light model
color = ambient_color + diffuse_color + specular_color;
color = clamp(color, 0.0, 1.0);
gl_FragColor = color;
}
|
Line(s) | Description |
---|---|
10-13 | The model color values are uniform ’s. |
33 | The model’s ambient color reduces the total ambient reflection. |
55 | The model’s diffuse color is used to calculate the diffuse reflection. |
78 | The model’s specular color is multiplied times the light’s color to calculate the color of the reflected light ray. |
Conclusion¶
More realistic light reflection calculations can be made if you know the specific color values for each type of reflected light. However,
- This only applies to objects with uniform, “solid” color surfaces. Notice that most of the above examples are gems or precious metals, which have a uniform color over their entire surface. Most real-world objects do not have uniform surfaces.
- Special equipment is required to measure the precise colors values for a particular type of surface and light reflection. Access to such special equipment is not common.
- Using a single diffuse color for all lighting calculations provides reasonable results when you do not have access to more accurate data.
Glossary¶
- ambient color
- The amount of color reflected from a surface by indirect light.
- diffuse color
- The amount of color reflected in all directions from a surface by direct light.
- specular color
- The amount of color reflected directly into the camera from a surface by direct light.
Self Assessment¶
- one RGBA (red, green, blue, alpha) value.
- Incorrect. This works fine for simple renderings, but not for realistic lighting.
- two RGBA (red, green, blue, alpha) values: one for reflection and one for absorption.
- Incorrect.
- three RGBA (red, green, blue, alpha) values: one for ambient reflection, one for diffuse reflection, and one specular reflection.
- Correct.
- four RGBA (red, green, blue, alpha) values: one for red light, one for green light, one for blue light, and one for transparent light.
- Incorrect. Besides, light can’t be transparent.
Q-245: To get the most realistic light modeling possible, the color of a surface should be represented by …
- False
- Correct. The lighting calculations are unchanged. The data for the calculations changes.
- True
- Incorrect.
Q-246: Using three distinct RGBA values to represent the color of a surface fundamentally changes how reflected light calculations are performed.
[1] | The original source of this information was “http://www.sgi.com/software/opengl/advanced98/notes/node119.html” but the hyperlink is no longer valid. The information have been replicated at various web sites such as http://sci.tamucc.edu/~sking/Courses/COSC4328/Assignments/Materials.html. |