Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PhongShader.cs
1using System;
2using System.Numerics;
3using System.Text;
4using SkiaSharp;
5
7{
12 public class PhongShader : I3DShader
13 {
14 private readonly PhongLightSource[] sources;
15 private readonly PhongLightSource source;
16 private readonly PhongIntensity ambient;
17 private readonly PhongMaterial material;
18 private Vector3 sourcePosition;
19 private readonly float sourceDiffuseRed;
20 private readonly float sourceDiffuseGreen;
21 private readonly float sourceDiffuseBlue;
22 private readonly float sourceDiffuseAlpha;
23 private readonly float sourceSpecularRed;
24 private readonly float sourceSpecularGreen;
25 private readonly float sourceSpecularBlue;
26 private readonly float sourceSpecularAlpha;
27 private readonly float ambientRed;
28 private readonly float ambientGreen;
29 private readonly float ambientBlue;
30 private readonly float ambientAlpha;
31 private readonly float ambientReflectionConstant;
32 private readonly float diffuseReflectionConstant;
33 private readonly float specularReflectionConstant;
34 private readonly float shininess;
35 private readonly int nrSources;
36 private readonly bool hasSpecularReflectionConstant;
37 private readonly bool singleSource;
38 private readonly bool opaque;
39
48 params PhongLightSource[] LightSources)
49 {
50 this.material = Material;
51 this.ambient = Ambient;
52 this.sources = LightSources;
53
54 this.ambientReflectionConstant = Material.AmbientReflectionConstant;
55 this.diffuseReflectionConstant = Material.DiffuseReflectionConstant;
56 this.specularReflectionConstant = Material.SpecularReflectionConstant;
57 this.hasSpecularReflectionConstant = this.specularReflectionConstant != 0;
58 this.shininess = Material.Shininess;
59
60 this.nrSources = LightSources.Length;
61 this.singleSource = this.nrSources == 1;
62
63 if (this.singleSource)
64 {
65 this.source = LightSources[0];
66 this.sourcePosition = this.source.Position;
67
68 PhongIntensity I = this.source.Diffuse;
69
70 this.sourceDiffuseRed = I.Red;
71 this.sourceDiffuseGreen = I.Green;
72 this.sourceDiffuseBlue = I.Blue;
73 this.sourceDiffuseAlpha = I.Alpha;
74
75 I = this.source.Specular;
76
77 this.sourceSpecularRed = I.Red;
78 this.sourceSpecularGreen = I.Green;
79 this.sourceSpecularBlue = I.Blue;
80 this.sourceSpecularAlpha = I.Alpha;
81 }
82
83 this.ambientRed = this.ambientReflectionConstant * Ambient.Red;
84 this.ambientGreen = this.ambientReflectionConstant * Ambient.Green;
85 this.ambientBlue = this.ambientReflectionConstant * Ambient.Blue;
86 this.ambientAlpha = this.ambientReflectionConstant * Ambient.Alpha;
87
88 if (this.ambientAlpha < 255 ||
89 this.sourceDiffuseAlpha < 255 ||
90 this.sourceSpecularAlpha < 255)
91 {
92 this.opaque = false;
93 }
94 else
95 {
96 this.opaque = true;
97
98 foreach (PhongLightSource Source in this.sources)
99 {
100 if (!Source.Opaque)
101 {
102 this.opaque = false;
103 break;
104 }
105 }
106 }
107 }
108
112 public PhongLightSource[] Sources => this.sources;
113
117 public PhongIntensity Ambient => this.ambient;
118
122 public PhongMaterial Material => this.material;
123
133 public SKColor GetColor(float X, float Y, float Z, Vector3 Normal, Canvas3D Canvas)
134 {
135 Vector3 L;
136 Vector3 R;
137 Vector3 V;
138 Vector3 P = new Vector3(X, Y, Z);
139 float d, d2;
140 float Red;
141 float Green;
142 float Blue;
143 float Alpha;
144
145 if (this.singleSource)
146 {
147 L = Vector3.Normalize(this.sourcePosition - P);
148 d = Vector3.Dot(L, Normal);
149
150 Red = this.ambientRed;
151 Green = this.ambientGreen;
152 Blue = this.ambientBlue;
153 Alpha = this.ambientAlpha;
154
155 if (d >= 0)
156 {
157 d *= this.diffuseReflectionConstant;
158
159 if (this.hasSpecularReflectionConstant)
160 {
161 R = 2 * d * Normal - L;
162 V = Vector3.Normalize(Canvas.ViewerPosition - P);
163 d2 = Math.Abs(Vector3.Dot(R, V));
164 d2 = this.specularReflectionConstant * (float)Math.Pow(d2, this.shininess);
165
166 Red += d2 * this.sourceSpecularRed;
167 Green += d2 * this.sourceSpecularGreen;
168 Blue += d2 * this.sourceSpecularBlue;
169 Alpha += d2 * this.sourceSpecularAlpha;
170 }
171
172 Red += d * this.sourceDiffuseRed;
173 Green += d * this.sourceDiffuseGreen;
174 Blue += d * this.sourceDiffuseBlue;
175 Alpha += d * this.sourceDiffuseAlpha;
176 }
177 }
178 else
179 {
180 PhongLightSource Source;
181 PhongIntensity Specular;
182 PhongIntensity Diffuse;
183 int j;
184
185 Red = Green = Blue = Alpha = 0;
186
187 if (this.hasSpecularReflectionConstant)
188 V = Vector3.Normalize(Canvas.ViewerPosition - P);
189 else
190 V = Vector3.Zero;
191
192 for (j = 0; j < this.nrSources; j++)
193 {
194 Source = this.sources[j];
195 Specular = Source.Specular;
196 Diffuse = Source.Diffuse;
197
198 L = Vector3.Normalize(Source.Position - P);
199 d = Vector3.Dot(L, Normal);
200
201 Red += this.ambientRed;
202 Green += this.ambientGreen;
203 Blue += this.ambientBlue;
204 Alpha += this.ambientAlpha;
205
206 if (d >= 0)
207 {
208 d *= this.diffuseReflectionConstant;
209
210 if (this.hasSpecularReflectionConstant)
211 {
212 R = 2 * d * Normal - L;
213 d2 = Math.Abs(Vector3.Dot(R, V));
214 d2 = this.specularReflectionConstant * (float)Math.Pow(d2, this.shininess);
215
216 Red += d2 * Specular.Red;
217 Green += d2 * Specular.Green;
218 Blue += d2 * Specular.Blue;
219 Alpha += d2 * Specular.Alpha;
220 }
221
222 Red += d * Diffuse.Red;
223 Green += d * Diffuse.Green;
224 Blue += d * Diffuse.Blue;
225 Alpha += d * Diffuse.Alpha;
226 }
227 }
228 }
229
230 byte R2, G2, B2, A2;
231 int Rest = 0;
232 int k;
233
234 if (Red < 0)
235 R2 = 0;
236 else if (Red > 255)
237 {
238 Rest = (int)(Red - 254.5f);
239 R2 = 255;
240 }
241 else
242 R2 = (byte)(Red + 0.5f);
243
244 if (Green < 0)
245 G2 = 0;
246 else if (Green > 255)
247 {
248 Rest += (int)(Green - 254.5f);
249 G2 = 255;
250 }
251 else
252 G2 = (byte)(Green + 0.5f);
253
254 if (Blue < 0)
255 B2 = 0;
256 else if (Blue > 255)
257 {
258 Rest += (int)(Blue - 254.5f);
259 B2 = 255;
260 }
261 else
262 B2 = (byte)(Blue + 0.5f);
263
264 if (Alpha < 0)
265 A2 = 0;
266 else if (Alpha > 255)
267 A2 = 255;
268 else
269 A2 = (byte)(Alpha + 0.5f);
270
271 if (Rest > 0)
272 {
273 Rest /= 2;
274
275 if (R2 < 255)
276 {
277 k = R2 + Rest;
278 if (k > 255)
279 R2 = 255;
280 else
281 R2 = (byte)k;
282 }
283
284 if (G2 < 255)
285 {
286 k = G2 + Rest;
287 if (k > 255)
288 G2 = 255;
289 else
290 G2 = (byte)k;
291 }
292
293 if (B2 < 255)
294 {
295 k = B2 + Rest;
296 if (k > 255)
297 B2 = 255;
298 else
299 B2 = (byte)k;
300 }
301 }
302
303 return new SKColor(R2, G2, B2, A2);
304 }
305
316 public void GetColors(float[] X, float[] Y, float[] Z, Vector3[] Normals, int N,
317 SKColor[] Colors, Canvas3D Canvas)
318 {
319 int i;
320 Vector3 L;
321 Vector3 R;
322 Vector3 V;
323 Vector3 P = new Vector3();
324 Vector3 Normal;
325 float d, d2;
326 float Red;
327 float Green;
328 float Blue;
329 float Alpha;
330 byte R2, G2, B2, A2;
331 int Rest;
332 int k;
333
334 if (this.singleSource)
335 {
336 for (i = 0; i < N; i++)
337 {
338 P.X = X[i];
339 P.Y = Y[i];
340 P.Z = Z[i];
341 Normal = Normals[i];
342
343 L = Vector3.Normalize(this.sourcePosition - P);
344 d = Vector3.Dot(L, Normal);
345
346 Red = this.ambientRed;
347 Green = this.ambientGreen;
348 Blue = this.ambientBlue;
349 Alpha = this.ambientAlpha;
350
351 if (d >= 0)
352 {
353 d *= this.diffuseReflectionConstant;
354
355 if (this.hasSpecularReflectionConstant)
356 {
357 R = 2 * d * Normal - L;
358 V = Vector3.Normalize(Canvas.ViewerPosition - P);
359 d2 = Math.Abs(Vector3.Dot(R, V));
360 d2 = this.specularReflectionConstant * (float)Math.Pow(d2, this.shininess);
361
362 Red += d2 * this.sourceSpecularRed;
363 Green += d2 * this.sourceSpecularGreen;
364 Blue += d2 * this.sourceSpecularBlue;
365 Alpha += d2 * this.sourceSpecularAlpha;
366 }
367
368 Red += d * this.sourceDiffuseRed;
369 Green += d * this.sourceDiffuseGreen;
370 Blue += d * this.sourceDiffuseBlue;
371 Alpha += d * this.sourceDiffuseAlpha;
372 }
373
374 Rest = 0;
375
376 if (Red < 0)
377 R2 = 0;
378 else if (Red > 255)
379 {
380 Rest = (int)(Red - 254.5f);
381 R2 = 255;
382 }
383 else
384 R2 = (byte)(Red + 0.5f);
385
386 if (Green < 0)
387 G2 = 0;
388 else if (Green > 255)
389 {
390 Rest += (int)(Green - 254.5f);
391 G2 = 255;
392 }
393 else
394 G2 = (byte)(Green + 0.5f);
395
396 if (Blue < 0)
397 B2 = 0;
398 else if (Blue > 255)
399 {
400 Rest += (int)(Blue - 254.5f);
401 B2 = 255;
402 }
403 else
404 B2 = (byte)(Blue + 0.5f);
405
406 if (Alpha < 0)
407 A2 = 0;
408 else if (Alpha > 255)
409 A2 = 255;
410 else
411 A2 = (byte)(Alpha + 0.5f);
412
413 if (Rest > 0)
414 {
415 Rest /= 2;
416
417 if (R2 < 255)
418 {
419 k = R2 + Rest;
420 if (k > 255)
421 R2 = 255;
422 else
423 R2 = (byte)k;
424 }
425
426 if (G2 < 255)
427 {
428 k = G2 + Rest;
429 if (k > 255)
430 G2 = 255;
431 else
432 G2 = (byte)k;
433 }
434
435 if (B2 < 255)
436 {
437 k = B2 + Rest;
438 if (k > 255)
439 B2 = 255;
440 else
441 B2 = (byte)k;
442 }
443 }
444
445 Colors[i] = new SKColor(R2, G2, B2, A2);
446 }
447 }
448 else
449 {
450 PhongLightSource Source;
451 PhongIntensity Specular;
452 PhongIntensity Diffuse;
453 int j;
454
455 for (i = 0; i < N; i++)
456 {
457 P.X = X[i];
458 P.Y = Y[i];
459 P.Z = Z[i];
460 Normal = Normals[i];
461
462 Red = Green = Blue = Alpha = 0;
463
464 if (this.hasSpecularReflectionConstant)
465 V = Vector3.Normalize(Canvas.ViewerPosition - P);
466 else
467 V = Vector3.Zero;
468
469 for (j = 0; j < this.nrSources; j++)
470 {
471 Source = this.sources[j];
472 Specular = Source.Specular;
473 Diffuse = Source.Diffuse;
474
475 L = Vector3.Normalize(Source.Position - P);
476 d = Vector3.Dot(L, Normal);
477
478 Red += this.ambientRed;
479 Green += this.ambientGreen;
480 Blue += this.ambientBlue;
481 Alpha += this.ambientAlpha;
482
483 if (d >= 0)
484 {
485 d *= this.diffuseReflectionConstant;
486
487 if (this.hasSpecularReflectionConstant)
488 {
489 R = 2 * d * Normal - L;
490 d2 = Math.Abs(Vector3.Dot(R, V));
491 d2 = this.specularReflectionConstant * (float)Math.Pow(d2, this.shininess);
492
493 Red += d2 * Specular.Red;
494 Green += d2 * Specular.Green;
495 Blue += d2 * Specular.Blue;
496 Alpha += d2 * Specular.Alpha;
497 }
498
499 Red += d * Diffuse.Red;
500 Green += d * Diffuse.Green;
501 Blue += d * Diffuse.Blue;
502 Alpha += d * Diffuse.Alpha;
503 }
504 }
505
506 Rest = 0;
507
508 if (Red < 0)
509 R2 = 0;
510 else if (Red > 255)
511 {
512 Rest = (int)(Red - 254.5f);
513 R2 = 255;
514 }
515 else
516 R2 = (byte)(Red + 0.5f);
517
518 if (Green < 0)
519 G2 = 0;
520 else if (Green > 255)
521 {
522 Rest += (int)(Green - 254.5f);
523 G2 = 255;
524 }
525 else
526 G2 = (byte)(Green + 0.5f);
527
528 if (Blue < 0)
529 B2 = 0;
530 else if (Blue > 255)
531 {
532 Rest += (int)(Blue - 254.5f);
533 B2 = 255;
534 }
535 else
536 B2 = (byte)(Blue + 0.5f);
537
538 if (Alpha < 0)
539 A2 = 0;
540 else if (Alpha > 255)
541 A2 = 255;
542 else
543 A2 = (byte)(Alpha + 0.5f);
544
545 if (Rest > 0)
546 {
547 Rest /= 2;
548
549 if (R2 < 255)
550 {
551 k = R2 + Rest;
552 if (k > 255)
553 R2 = 255;
554 else
555 R2 = (byte)k;
556 }
557
558 if (G2 < 255)
559 {
560 k = G2 + Rest;
561 if (k > 255)
562 G2 = 255;
563 else
564 G2 = (byte)k;
565 }
566
567 if (B2 < 255)
568 {
569 k = B2 + Rest;
570 if (k > 255)
571 B2 = 255;
572 else
573 B2 = (byte)k;
574 }
575 }
576
577 Colors[i] = new SKColor(R2, G2, B2, A2);
578 }
579 }
580 }
581
585 public bool Opaque => this.opaque;
586
587 }
588}
Vector3 ViewerPosition
Viewer position
Definition: Canvas3D.cs:371
Contains information about the intensity of a light component, as used in the Phong reflection model....
Contains information about a light source, as used in the Phong reflection model. https://en....
bool Opaque
If shader is 100% opaque.
Vector3 Position
Position of light source..
PhongIntensity Diffuse
Diffuse intensity.
PhongIntensity Specular
Specular intensity.
Contains information about a material, as used in the Phong reflection model. https://en....
float AmbientReflectionConstant
Ratio of reflection of the ambient term present in all points in the scene rendered.
float DiffuseReflectionConstant
Ratio of reflection of the diffuse term of incoming light.
float Shininess
Shininess coefficient.
float SpecularReflectionConstant
Ratio of reflection of the specular term of incoming light.
The Phong Shader uses the Phong Reflection model to generate colors. https://en.wikipedia....
Definition: PhongShader.cs:13
PhongShader(PhongMaterial Material, PhongIntensity Ambient, params PhongLightSource[] LightSources)
The Phong Shader uses the Phong Reflection model to generate colors. https://en.wikipedia....
Definition: PhongShader.cs:47
PhongMaterial Material
Material settings.
Definition: PhongShader.cs:122
void GetColors(float[] X, float[] Y, float[] Z, Vector3[] Normals, int N, SKColor[] Colors, Canvas3D Canvas)
Gets an array of colors.
Definition: PhongShader.cs:316
SKColor GetColor(float X, float Y, float Z, Vector3 Normal, Canvas3D Canvas)
Gets a color for a position.
Definition: PhongShader.cs:133
PhongIntensity Ambient
Ambient settings
Definition: PhongShader.cs:117
PhongLightSource[] Sources
Light Sources
Definition: PhongShader.cs:112
bool Opaque
If shader is 100% opaque.
Definition: PhongShader.cs:585
Interface for 3D shaders.
Definition: I3DShader.cs:11