VectSharp  2.2.1
A light library for C# vector graphics
Materials.cs
1 /*
2  VectSharp - A light library for C# vector graphics.
3  Copyright (C) 2020-2022 Giorgio Bianchini
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, version 3.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 using System;
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.Linq;
22 using System.Runtime.InteropServices.ComTypes;
23 using System.Security.Cryptography.X509Certificates;
24 using System.Text;
25 
26 namespace VectSharp.ThreeD
27 {
28  /// <summary>
29  /// Represents a material used to the determine the appearance of <see cref="Triangle3DElement"/>.
30  /// </summary>
31  public interface IMaterial
32  {
33  /// <summary>
34  /// Obtains the <see cref="Colour"/> at the specified point.
35  /// </summary>
36  /// <param name="point">The point whose colour should be determined.</param>
37  /// <param name="surfaceNormal">The normal to the surface at the specified <paramref name="point"/>.</param>
38  /// <param name="camera">The camera being used to render the scene.</param>
39  /// <param name="lights">A list of light sources that are present in the scene.</param>
40  /// <param name="obstructions">A list of values indicating how obstructed each light source is.</param>
41  /// <returns>The <see cref="Colour"/> of the specified point.</returns>
42  Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList<ILightSource> lights, IList<double> obstructions);
43  }
44 
45  /// <summary>
46  /// Represents a material that always has the same colour, regardless of light.
47  /// </summary>
48  public class ColourMaterial : IMaterial
49  {
50  /// <summary>
51  /// The colour of the material.
52  /// </summary>
53  public Colour Colour { get; }
54 
55  /// <summary>
56  /// Creates a new <see cref="ColourMaterial"/> instance.
57  /// </summary>
58  /// <param name="colour">The colour of the material.</param>
59  public ColourMaterial(Colour colour)
60  {
61  this.Colour = colour;
62  }
63 
64  /// <inheritdoc/>
65  public Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList<ILightSource> lights, IList<double> obstructions)
66  {
67  return Colour;
68  }
69  }
70 
71  /// <summary>
72  /// Represents a material that uses a Phong reflection model to determine the colour of the material based on the light sources that hit it.
73  /// </summary>
74  public class PhongMaterial : IMaterial
75  {
76  /// <summary>
77  /// The base colour of the material.
78  /// </summary>
79  public Colour Colour { get; }
80 
81  private (double L, double a, double b) LabColour;
82  private (double H, double S, double L) LabBlackHSL;
83  private (double H, double S, double L) LabWhiteHSL;
84  private double IntensityExponent;
85  private double TotalLength;
86 
87  /// <summary>
88  /// A coefficient determining how much ambient light is reflected by the material.
89  /// </summary>
90  public double AmbientReflectionCoefficient { get; set; } = 1;
91 
92  /// <summary>
93  /// A coefficient determining how much directional light is reflected by the material.
94  /// </summary>
95  public double DiffuseReflectionCoefficient { get; set; } = 1;
96 
97  /// <summary>
98  /// A coefficient determining the intensity of specular highlights.
99  /// </summary>
100  public double SpecularReflectionCoefficient { get; set; } = 1;
101 
102  /// <summary>
103  /// A coefficient determining the extent of specular highlights.
104  /// </summary>
105  public double SpecularShininess { get; set; } = 1;
106 
107  /// <summary>
108  /// Creates a new <see cref="PhongMaterial"/> instance.
109  /// </summary>
110  /// <param name="colour">The base colour of the material.</param>
111  public PhongMaterial(Colour colour)
112  {
113  this.Colour = colour;
114  this.LabColour = colour.ToLab();
115  this.LabBlackHSL = Colour.FromLab(0, LabColour.a, LabColour.b).ToHSL();
116  this.LabWhiteHSL = Colour.FromLab(1, LabColour.a, LabColour.b).ToHSL();
117  this.TotalLength = 1 + LabBlackHSL.L + (1 - LabWhiteHSL.L);
118  this.IntensityExponent = Math.Log((LabBlackHSL.L + LabColour.L) / TotalLength) / Math.Log(0.5);
119  }
120 
121  private Colour GetScaledColour(double intensity)
122  {
123  intensity = Math.Max(Math.Min(intensity, 1), 0);
124 
125  double pos = Math.Pow(intensity, IntensityExponent) * TotalLength;
126 
127  if (pos <= LabBlackHSL.L)
128  {
129  return Colour.FromHSL(LabBlackHSL.H, LabBlackHSL.S, pos).WithAlpha(Colour.A);
130  }
131  else if (pos >= 1 + LabBlackHSL.L)
132  {
133  return Colour.FromHSL(LabWhiteHSL.H, LabWhiteHSL.S, LabWhiteHSL.L + pos - 1 - LabBlackHSL.L).WithAlpha(Colour.A);
134  }
135  else
136  {
137  return Colour.FromLab(pos - LabBlackHSL.L, LabColour.a, LabColour.b).WithAlpha(Colour.A);
138  }
139  }
140 
141  /// <inheritdoc/>
142  public Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList<ILightSource> lights, IList<double> obstructions)
143  {
144  double intensity = 0;
145 
146  for (int i = 0; i < lights.Count; i++)
147  {
148  (double lightIntensity, NormalizedVector3D lightDirection) = lights[i].GetLightAt(point);
149  lightIntensity *= 1 - obstructions[i];
150 
151  if (double.IsNaN(lightDirection.X))
152  {
153  intensity += lightIntensity * AmbientReflectionCoefficient;
154  }
155  else
156  {
157  double dotProd = lightDirection * surfaceNormal;
158 
159  intensity += lightIntensity * Math.Max(0, dotProd) * DiffuseReflectionCoefficient;
160 
161  if (dotProd > 0)
162  {
163  NormalizedVector3D mirroredDirection = (lightDirection - 2 * dotProd * surfaceNormal).Normalize();
164 
165  NormalizedVector3D cameraDirection = (camera.ViewPoint - point).Normalize();
166 
167  double dotProd2 = mirroredDirection * cameraDirection;
168 
169  if (dotProd2 >= 0)
170  {
171  intensity += lightIntensity * Math.Pow(dotProd2, SpecularShininess) * SpecularReflectionCoefficient;
172  }
173  }
174  }
175  }
176 
177  return GetScaledColour(intensity);
178  }
179  }
180 }
VectSharp.ThreeD.IMaterial
Represents a material used to the determine the appearance of Triangle3DElement.
Definition: Materials.cs:32
VectSharp.ThreeD.ColourMaterial
Represents a material that always has the same colour, regardless of light.
Definition: Materials.cs:49
VectSharp.ThreeD.PhongMaterial
Represents a material that uses a Phong reflection model to determine the colour of the material base...
Definition: Materials.cs:75
VectSharp.Colour
Represents an RGB colour.
Definition: Colour.cs:26
VectSharp.ThreeD.PhongMaterial.AmbientReflectionCoefficient
double AmbientReflectionCoefficient
A coefficient determining how much ambient light is reflected by the material.
Definition: Materials.cs:90
VectSharp.ThreeD.ColourMaterial.ColourMaterial
ColourMaterial(Colour colour)
Creates a new ColourMaterial instance.
Definition: Materials.cs:59
VectSharp.Colour.A
double A
Alpha component of the colour. Range: [0, 1].
Definition: Colour.cs:45
VectSharp.ThreeD.PhongMaterial.GetColour
Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList< ILightSource > lights, IList< double > obstructions)
Obtains the Colour at the specified point.
Definition: Materials.cs:142
VectSharp.ThreeD.ColourMaterial.GetColour
Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList< ILightSource > lights, IList< double > obstructions)
Obtains the Colour at the specified point.
Definition: Materials.cs:65
VectSharp.Colour.WithAlpha
static Colour WithAlpha(Colour original, double alpha)
Create a new Colour with the same RGB components as the original Colour, but with the specified alph...
Definition: Colour.cs:330
VectSharp.ThreeD
Definition: Lights.cs:23
VectSharp.ThreeD.ColourMaterial.Colour
Colour Colour
The colour of the material.
Definition: Materials.cs:53
VectSharp.ThreeD.PhongMaterial.SpecularShininess
double SpecularShininess
A coefficient determining the extent of specular highlights.
Definition: Materials.cs:105
VectSharp.ThreeD.IMaterial.GetColour
Colour GetColour(Point3D point, NormalizedVector3D surfaceNormal, Camera camera, IList< ILightSource > lights, IList< double > obstructions)
Obtains the Colour at the specified point.
VectSharp.Colour.FromHSL
static Colour FromHSL(double h, double s, double l)
Creates a Colour from HSL coordinates.
Definition: Colour.cs:575
VectSharp.ThreeD.PhongMaterial.SpecularReflectionCoefficient
double SpecularReflectionCoefficient
A coefficient determining the intensity of specular highlights.
Definition: Materials.cs:100
VectSharp.ThreeD.PhongMaterial.PhongMaterial
PhongMaterial(Colour colour)
Creates a new PhongMaterial instance.
Definition: Materials.cs:111
VectSharp.ThreeD.PhongMaterial.Colour
Colour Colour
The base colour of the material.
Definition: Materials.cs:79
VectSharp.ThreeD.PhongMaterial.DiffuseReflectionCoefficient
double DiffuseReflectionCoefficient
A coefficient determining how much directional light is reflected by the material.
Definition: Materials.cs:95
VectSharp.Colour.FromLab
static Colour FromLab(double L, double a, double b)
Creates a Colour from CIE Lab coordinates (under Illuminant D65).
Definition: Colour.cs:497