4421e9c2d52a6a6a1a782cad3d36bdae134e3a8a
[occt.git] / src / Graphic3d / Graphic3d_BSDF.cxx
1 // Created on: 2015-01-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Graphic3d_BSDF.hxx>
17
18 #include <algorithm>
19
20 // =======================================================================
21 // function : Serialize
22 // purpose  :
23 // =======================================================================
24 Graphic3d_Vec4 Graphic3d_Fresnel::Serialize() const
25 {
26   Graphic3d_Vec4 aData = Graphic3d_Vec4 (myFresnelData, 0.f);
27
28   if (myFresnelType != Graphic3d_FM_SCHLICK)
29   {
30     aData.x() = -static_cast<float> (myFresnelType);
31   }
32
33   return aData;
34 }
35
36 // =======================================================================
37 // function : fresnelNormal
38 // purpose  :
39 // =======================================================================
40 inline float fresnelNormal (float theN,
41                             float theK)
42 {
43   return ((theN - 1.f) * (theN - 1.f) + theK * theK) /
44          ((theN + 1.f) * (theN + 1.f) + theK * theK);
45 }
46
47 // =======================================================================
48 // function : CreateConductor
49 // purpose  :
50 // =======================================================================
51 Graphic3d_Fresnel Graphic3d_Fresnel::CreateConductor (const Graphic3d_Vec3& theRefractionIndex,
52                                                       const Graphic3d_Vec3& theAbsorptionIndex)
53 {
54   const Graphic3d_Vec3 aFresnel (fresnelNormal (theRefractionIndex.x(), theAbsorptionIndex.x()),
55                                  fresnelNormal (theRefractionIndex.y(), theAbsorptionIndex.y()),
56                                  fresnelNormal (theRefractionIndex.z(), theAbsorptionIndex.z()));
57
58   return Graphic3d_Fresnel (Graphic3d_FM_SCHLICK, aFresnel);
59 }
60
61 // =======================================================================
62 // function : Graphic3d_BSDF
63 // purpose  :
64 // =======================================================================
65 Graphic3d_BSDF::Graphic3d_BSDF()
66 {
67   FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
68   FresnelBase = Graphic3d_Fresnel::CreateConstant (1.f);
69 }
70
71 // =======================================================================
72 // function : operator==
73 // purpose  :
74 // =======================================================================
75 bool Graphic3d_BSDF::operator== (const Graphic3d_BSDF& theOther) const
76 {
77   return Kc          == theOther.Kc
78       && Kd          == theOther.Kd
79       && Kt          == theOther.Kt
80       && Ks          == theOther.Ks
81       && Le          == theOther.Le
82       && Absorption  == theOther.Absorption
83       && FresnelCoat == theOther.FresnelCoat
84       && FresnelBase == theOther.FresnelBase;
85 }
86
87 // =======================================================================
88 // function : Normalize
89 // purpose  :
90 // =======================================================================
91 void Graphic3d_BSDF::Normalize()
92 {
93   float aMax = 0.f;
94
95   for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
96   {
97     aMax = std::max (aMax, Kd[aChannelID] + Ks[aChannelID] + Kt[aChannelID]);
98   }
99
100   if (aMax > 1.f)
101   {
102     for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
103     {
104       Kd[aChannelID] /= aMax;
105       Ks[aChannelID] /= aMax;
106       Kt[aChannelID] /= aMax;
107     }
108   }
109 }
110
111 // =======================================================================
112 // function : CreateDiffuse
113 // purpose  :
114 // =======================================================================
115 Graphic3d_BSDF Graphic3d_BSDF::CreateDiffuse (const Graphic3d_Vec3& theWeight)
116 {
117   Graphic3d_BSDF aBSDF;
118
119   aBSDF.Kd = theWeight;
120
121   return aBSDF;
122 }
123
124 // =======================================================================
125 // function : CreateMetallic
126 // purpose  :
127 // =======================================================================
128 Graphic3d_BSDF Graphic3d_BSDF::CreateMetallic (const Graphic3d_Vec3& theWeight, const Graphic3d_Fresnel& theFresnel, const float theRoughness)
129 {
130   Graphic3d_BSDF aBSDF;
131
132   aBSDF.FresnelBase = theFresnel;
133
134   // Selecting between specular and glossy
135   // BRDF depending on the given roughness
136   aBSDF.Ks = Graphic3d_Vec4 (theWeight, theRoughness);
137
138   return aBSDF;
139 }
140
141 // =======================================================================
142 // function : CreateTransparent
143 // purpose  :
144 // =======================================================================
145 Graphic3d_BSDF Graphic3d_BSDF::CreateTransparent (const Graphic3d_Vec3& theWeight,
146                                                   const Graphic3d_Vec3& theAbsorptionColor,
147                                                   const float           theAbsorptionCoeff)
148 {
149   Graphic3d_BSDF aBSDF;
150
151   // Create Fresnel parameters for the coat layer;
152   // set it to 0 value to simulate ideal refractor
153   aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
154
155   aBSDF.Kt = theWeight;
156
157   // Link reflection and transmission coefficients
158   aBSDF.Kc.r() = aBSDF.Kt.r();
159   aBSDF.Kc.g() = aBSDF.Kt.g();
160   aBSDF.Kc.b() = aBSDF.Kt.b();
161
162   aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
163                                      theAbsorptionCoeff);
164
165   return aBSDF;
166 }
167
168 // =======================================================================
169 // function : CreateGlass
170 // purpose  :
171 // =======================================================================
172 Graphic3d_BSDF Graphic3d_BSDF::CreateGlass (const Graphic3d_Vec3& theWeight,
173                                             const Graphic3d_Vec3& theAbsorptionColor,
174                                             const float           theAbsorptionCoeff,
175                                             const float           theRefractionIndex)
176 {
177   Graphic3d_BSDF aBSDF;
178
179   // Create Fresnel parameters for the coat layer
180   aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateDielectric (theRefractionIndex);
181
182   aBSDF.Kt = theWeight;
183
184   aBSDF.Kc.r() = aBSDF.Kt.r();
185   aBSDF.Kc.g() = aBSDF.Kt.g();
186   aBSDF.Kc.b() = aBSDF.Kt.b();
187
188   aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
189                                      theAbsorptionCoeff);
190
191   return aBSDF;
192 }