rev |
line source |
nuclear@0
|
1 #version 110
|
nuclear@0
|
2
|
nuclear@0
|
3 #define SQ(x) ((x) * (x))
|
nuclear@0
|
4 #define PI 3.141592653
|
nuclear@0
|
5
|
nuclear@0
|
6 /* -- Lambert's cosine law
|
nuclear@0
|
7 * J. H. Lambert, Photometria sive de mensura de gratibus luminis, colorum et umbrae.
|
nuclear@0
|
8 * Eberhard Klett, 1760.
|
nuclear@0
|
9 */
|
nuclear@0
|
10 float lambert(vec3 norm, vec3 ldir)
|
nuclear@0
|
11 {
|
nuclear@0
|
12 return max(dot(norm, ldir), 0.0);
|
nuclear@0
|
13 }
|
nuclear@0
|
14
|
nuclear@0
|
15 /* -- Phong specular model
|
nuclear@0
|
16 * B. T. Phong, "Illumination for Computer Generated Pictures"
|
nuclear@0
|
17 * Communications of the ACM, 1975.
|
nuclear@0
|
18 */
|
nuclear@0
|
19 float phong(vec3 view, vec3 norm, vec3 ldir, float spow)
|
nuclear@0
|
20 {
|
nuclear@0
|
21 vec3 lref = reflect(-ldir, norm);
|
nuclear@0
|
22 return pow(max(dot(lref, view), 0.0), spow);
|
nuclear@0
|
23 }
|
nuclear@0
|
24
|
nuclear@0
|
25 /* -- Blinn-Phong specular model
|
nuclear@0
|
26 * J. F. Blinn, "Models of Light Reflection for Computer Synthesized Pictures"
|
nuclear@0
|
27 * in Proceedings of SIGGRAPH 1977
|
nuclear@0
|
28 */
|
nuclear@0
|
29 float blinn(vec3 norm, vec3 hvec, float spow)
|
nuclear@0
|
30 {
|
nuclear@0
|
31 return pow(max(dot(norm, hvec), 0.0), spow);
|
nuclear@0
|
32 }
|
nuclear@0
|
33
|
nuclear@0
|
34 /* -- Cook & Torrance model.
|
nuclear@0
|
35 * R. L. Cook and K. E. Torrance, "A Reflectance Model for Computer Graphics"
|
nuclear@0
|
36 * in Proceedings of SIGGRAPH 1981.
|
nuclear@0
|
37 */
|
nuclear@0
|
38 float cook_torrance(vec3 view, vec3 norm, vec3 ldir, vec3 hvec, float rough, float ior)
|
nuclear@0
|
39 {
|
nuclear@0
|
40 float m = max(rough, 0.0001);
|
nuclear@0
|
41
|
nuclear@0
|
42 // various useful dot products
|
nuclear@0
|
43 float ndoth = max(dot(norm, hvec), 0.0);
|
nuclear@0
|
44 float ndotv = max(dot(norm, view), 0.0);
|
nuclear@0
|
45 float ndotl = dot(norm, ldir);
|
nuclear@0
|
46 float vdoth = max(dot(view, hvec), 0.0);
|
nuclear@0
|
47 float ndoth_sq = SQ(ndoth);
|
nuclear@0
|
48
|
nuclear@0
|
49 // geometric term (shadowing/masking)
|
nuclear@0
|
50 float geom_a = (2.0 * ndoth * ndotv) / vdoth;
|
nuclear@0
|
51 float geom_b = (2.0 * ndoth * ndotl) / vdoth;
|
nuclear@0
|
52 float geom = min(1.0, min(geom_a, geom_b));
|
nuclear@0
|
53
|
nuclear@0
|
54 // beckmann microfacet distribution term
|
nuclear@0
|
55 float sin2_ang = 1.0 - ndoth_sq; // sin^2(a) = 1 - cos^2(a)
|
nuclear@0
|
56 float tan2_ang = sin2_ang / ndoth_sq; // tan^2(a) = sin^2(a) / cos^2(a)
|
nuclear@0
|
57 float d_mf = exp(-tan2_ang / SQ(m)) / (SQ(m) * SQ(ndoth_sq));
|
nuclear@0
|
58
|
nuclear@0
|
59 // fresnel term
|
nuclear@0
|
60 float c = vdoth;
|
nuclear@0
|
61 float g = sqrt(SQ(ior) + SQ(c) - 1.0);
|
nuclear@0
|
62 float ftmp = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
|
nuclear@0
|
63 float fres = 0.5 * (SQ(g - c) / SQ(g + c)) * (1.0 + SQ(ftmp));
|
nuclear@0
|
64
|
nuclear@0
|
65 return (fres / PI) * (d_mf / ndotl) * (geom / ndotv);
|
nuclear@0
|
66 }
|
nuclear@0
|
67
|
nuclear@0
|
68 /* -- Oren & Nayar model
|
nuclear@0
|
69 * M. Oren and S. K. Nayar, "Generalization of Lambert's Reflectance Model"
|
nuclear@0
|
70 * in Proceedings of SIGGRAPH 1994.
|
nuclear@0
|
71 */
|
nuclear@0
|
72 float oren_nayar(vec3 view, vec3 norm, vec3 ldir, float rough)
|
nuclear@0
|
73 {
|
nuclear@0
|
74 float vdotn = max(dot(view, norm), 0.0);
|
nuclear@0
|
75 float ldotn = max(dot(ldir, norm), 0.0);
|
nuclear@0
|
76
|
nuclear@0
|
77 float theta_r = acos(vdotn);
|
nuclear@0
|
78 float theta_i = acos(ldotn);
|
nuclear@0
|
79 float cos_pr_minus_pi = dot(normalize(view - norm * vdotn), normalize(ldir - norm * ldotn));
|
nuclear@0
|
80 float alpha = max(theta_r, theta_i);
|
nuclear@0
|
81 float beta = min(theta_r, theta_i);
|
nuclear@0
|
82
|
nuclear@0
|
83 float sigma_sq = SQ(rough);
|
nuclear@0
|
84 float a = 1.0 - 0.5 * sigma_sq / (sigma_sq + 0.33);
|
nuclear@0
|
85 float b = 0.45 * sigma_sq / (sigma_sq + 0.09);
|
nuclear@0
|
86
|
nuclear@0
|
87 if(cos_pr_minus_pi >= 0.0) {
|
nuclear@0
|
88 b *= cos_pr_minus_pi * sin(alpha) * tan(beta);
|
nuclear@0
|
89 } else {
|
nuclear@0
|
90 b = 0.0;
|
nuclear@0
|
91 }
|
nuclear@0
|
92
|
nuclear@0
|
93 return ldotn * (a + b);
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 /* TODO: need tangent/bitangent
|
nuclear@0
|
97 float ward(vec3 view, vec3 norm, vec3 ldir, vec3 hvec, vec3 tang, vec3 bitan, float ax, float ay)
|
nuclear@0
|
98 {
|
nuclear@0
|
99 float vdotn = dot(view, norm);
|
nuclear@0
|
100 float ldotn = dot(light, norm);
|
nuclear@0
|
101 }
|
nuclear@0
|
102 */
|