source: Dev/trunk/src/client/dojox/gfx3d/lighting.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 9.0 KB
Line 
1define([
2        "dojo/_base/lang",
3        "dojo/_base/Color",     // dojo.Color
4        "dojo/_base/declare",   // declare
5        "dojox/gfx/_base",
6        "./_base"
7],function(lang,Color,declare,gfx,gfx3d) {
8
9        var lite = gfx3d.lighting = {
10                // color utilities
11                black: function(){
12                        return {r: 0, g: 0, b: 0, a: 1};
13                },
14                white: function(){
15                        return {r: 1, g: 1, b: 1, a: 1};
16                },
17                toStdColor: function(c){
18                        c = gfx.normalizeColor(c);
19                        return {r: c.r / 255, g: c.g / 255, b: c.b / 255, a: c.a};
20                },
21                fromStdColor: function(c){
22                        return new Color([Math.round(255 * c.r), Math.round(255 * c.g), Math.round(255 * c.b), c.a]);
23                },
24                scaleColor: function(s, c){
25                        return {r: s * c.r, g: s * c.g, b: s * c.b, a: s * c.a};
26                },
27                addColor: function(a, b){
28                        return {r: a.r + b.r, g: a.g + b.g, b: a.b + b.b, a: a.a + b.a};
29                },
30                multiplyColor: function(a, b){
31                        return {r: a.r * b.r, g: a.g * b.g, b: a.b * b.b, a: a.a * b.a};
32                },
33                saturateColor: function(c){
34                        return {
35                                r: c.r < 0 ? 0 : c.r > 1 ? 1 : c.r,
36                                g: c.g < 0 ? 0 : c.g > 1 ? 1 : c.g,
37                                b: c.b < 0 ? 0 : c.b > 1 ? 1 : c.b,
38                                a: c.a < 0 ? 0 : c.a > 1 ? 1 : c.a
39                        };
40                },
41                mixColor: function(c1, c2, s){
42                        return lite.addColor(lite.scaleColor(s, c1), lite.scaleColor(1 - s, c2));
43                },
44                diff2Color: function(c1, c2){
45                        var r = c1.r - c2.r;
46                        var g = c1.g - c2.g;
47                        var b = c1.b - c2.b;
48                        var a = c1.a - c2.a;
49                        return r * r + g * g + b * b + a * a;
50                },
51                length2Color: function(c){
52                        return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
53                },
54               
55                // vector utilities
56                //TODO: move vector utilities from this file to vector.js
57                dot: function(a, b){
58                        return a.x * b.x + a.y * b.y + a.z * b.z;
59                },
60                scale: function(s, v){
61                        return {x: s * v.x, y: s * v.y, z: s * v.z};
62                },
63                add: function(a, b){
64                        return {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z};
65                },
66                saturate: function(v){
67                        return Math.min(Math.max(v, 0), 1);
68                },
69                length: function(v){
70                        return Math.sqrt(gfx3d.lighting.dot(v, v));
71                },
72                normalize: function(v){
73                        return lite.scale(1 / lite.length(v), v);
74                },
75                faceforward: function(n, i){
76                        var p = gfx3d.lighting;
77                        var s = p.dot(i, n) < 0 ? 1 : -1;
78                        return p.scale(s, n);
79                },
80                reflect: function(i, n){
81                        var p = gfx3d.lighting;
82                        return p.add(i, p.scale(-2 * p.dot(i, n), n));
83                },
84               
85                // lighting utilities
86                diffuse: function(normal, lights){
87                        var c = lite.black();
88                        for(var i = 0; i < lights.length; ++i){
89                                var l = lights[i],
90                                        d = lite.dot(lite.normalize(l.direction), normal);
91                                c = lite.addColor(c, lite.scaleColor(d, l.color));
92                        }
93                        return lite.saturateColor(c);
94                },
95                specular: function(normal, v, roughness, lights){
96                        var c = lite.black();
97                        for(var i = 0; i < lights.length; ++i){
98                                var l = lights[i],
99                                        h = lite.normalize(lite.add(lite.normalize(l.direction), v)),
100                                        s = Math.pow(Math.max(0, lite.dot(normal, h)), 1 / roughness);
101                                c = lite.addColor(c, lite.scaleColor(s, l.color));
102                        }
103                        return lite.saturateColor(c);
104                },
105                phong: function(normal, v, size, lights){
106                        normal = lite.normalize(normal);
107                        var c = lite.black();
108                        for(var i = 0; i < lights.length; ++i){
109                                var l = lights[i],
110                                        r = lite.reflect(lite.scale(-1, lite.normalize(v)), normal),
111                                        s = Math.pow(Math.max(0, lite.dot(r, lite.normalize(l.direction))), size);
112                                c = lite.addColor(c, lite.scaleColor(s, l.color));
113                        }
114                        return lite.saturateColor(c);
115                }
116        };
117
118        // this lighting model is derived from RenderMan Interface Specification Version 3.2
119
120        declare("dojox.gfx3d.lighting.Model", null, {
121                constructor: function(incident, lights, ambient, specular){
122                        this.incident = lite.normalize(incident);
123                        this.lights = [];
124                        for(var i = 0; i < lights.length; ++i){
125                                var l = lights[i];
126                                this.lights.push({direction: lite.normalize(l.direction), color: lite.toStdColor(l.color)});
127                        }
128                        this.ambient = lite.toStdColor(ambient.color ? ambient.color : "white");
129                        this.ambient = lite.scaleColor(ambient.intensity, this.ambient);
130                        this.ambient = lite.scaleColor(this.ambient.a, this.ambient);
131                        this.ambient.a = 1;
132                        this.specular = lite.toStdColor(specular ? specular : "white");
133                        this.specular = lite.scaleColor(this.specular.a, this.specular);
134                        this.specular.a = 1;
135                        this.npr_cool = {r: 0,   g: 0,   b: 0.4, a: 1};
136                        this.npr_warm = {r: 0.4, g: 0.4, b: 0.2, a: 1};
137                        this.npr_alpha = 0.2;
138                        this.npr_beta  = 0.6;
139                        this.npr_scale = 0.6;
140                },
141                constant: function(normal, finish, pigment){
142                        pigment   = lite.toStdColor(pigment);
143                        var alpha = pigment.a, color = lite.scaleColor(alpha, pigment);
144                        color.a   = alpha;
145                        return lite.fromStdColor(lite.saturateColor(color));
146                },
147                matte: function(normal, finish, pigment){
148                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
149                        pigment = lite.toStdColor(pigment);
150                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
151                        var ambient = lite.scaleColor(finish.Ka, this.ambient),
152                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
153                                diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
154                                color   = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)));
155                        color.a = pigment.a;
156                        return lite.fromStdColor(lite.saturateColor(color));
157                },
158                metal: function(normal, finish, pigment){
159                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
160                        pigment = lite.toStdColor(pigment);
161                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
162                        var v = lite.scale(-1, this.incident), specular, color,
163                                ambient = lite.scaleColor(finish.Ka, this.ambient),
164                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident));
165                        if("phong" in finish){
166                                specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
167                        }else{
168                                specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
169                        }
170                        color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, ambient), lite.multiplyColor(this.specular, specular)));
171                        color.a = pigment.a;
172                        return lite.fromStdColor(lite.saturateColor(color));
173                },
174                plastic: function(normal, finish, pigment){
175                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
176                        pigment = lite.toStdColor(pigment);
177                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
178                        var v = lite.scale(-1, this.incident), specular, color,
179                                ambient = lite.scaleColor(finish.Ka, this.ambient),
180                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
181                                diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights));
182                        if("phong" in finish){
183                                specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
184                        }else{
185                                specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
186                        }
187                        color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)), lite.multiplyColor(this.specular, specular)));
188                        color.a = pigment.a;
189                        return lite.fromStdColor(lite.saturateColor(color));
190                },
191                npr: function(normal, finish, pigment){
192                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
193                        pigment = lite.toStdColor(pigment);
194                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
195                        var ambient  = lite.scaleColor(finish.Ka, this.ambient),
196                                shadow   = lite.saturate(-4 * lite.dot(normal, this.incident)),
197                                diffuse  = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
198                                color = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse))),
199                                cool = lite.addColor(this.npr_cool, lite.scaleColor(this.npr_alpha, color)),
200                                warm = lite.addColor(this.npr_warm, lite.scaleColor(this.npr_beta,  color)),
201                                d = (1 + lite.dot(this.incident, normal)) / 2,
202                                color = lite.scaleColor(this.npr_scale, lite.addColor(color, lite.mixColor(cool, warm, d)));
203                        color.a = pigment.a;
204                        return lite.fromStdColor(lite.saturateColor(color));
205                }
206        });
207
208
209        // POV-Ray basic finishes
210       
211        gfx3d.lighting.finish = {
212       
213                // Default
214               
215                defaults: {Ka: 0.1, Kd: 0.6, Ks: 0.0, roughness: 0.05},
216               
217                dull:     {Ka: 0.1, Kd: 0.6, Ks: 0.5, roughness: 0.15},
218                shiny:    {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.001},
219                glossy:   {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.0001},
220               
221                phong_dull:   {Ka: 0.1, Kd: 0.6, Ks: 0.5, phong: 0.5, phong_size: 1},
222                phong_shiny:  {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 200},
223                phong_glossy: {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 300},
224       
225                luminous: {Ka: 1.0, Kd: 0.0, Ks: 0.0, roughness: 0.05},
226       
227                // Metals
228       
229                // very soft and dull
230                metalA: {Ka: 0.35, Kd: 0.3, Ks: 0.8, roughness: 1/20},
231                // fairly soft and dull
232                metalB: {Ka: 0.30, Kd: 0.4, Ks: 0.7, roughness: 1/60},
233                // medium reflectivity, holds color well
234                metalC: {Ka: 0.25, Kd: 0.5, Ks: 0.8, roughness: 1/80},
235                // highly hard and polished, high reflectivity
236                metalD: {Ka: 0.15, Kd: 0.6, Ks: 0.8, roughness: 1/100},
237                // very highly polished and reflective
238                metalE: {Ka: 0.10, Kd: 0.7, Ks: 0.8, roughness: 1/120}
239        };
240
241        return lite;
242});
Note: See TracBrowser for help on using the repository browser.