0031313: Foundation Classes - Dump improvement for classes
[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 <Graphic3d_PBRMaterial.hxx>
19
20 #include <algorithm>
21
22 // =======================================================================
23 // function : Serialize
24 // purpose  :
25 // =======================================================================
26 Graphic3d_Vec4 Graphic3d_Fresnel::Serialize() const
27 {
28   Graphic3d_Vec4 aData = Graphic3d_Vec4 (myFresnelData, 0.f);
29
30   if (myFresnelType != Graphic3d_FM_SCHLICK)
31   {
32     aData.x() = -static_cast<float> (myFresnelType);
33   }
34
35   return aData;
36 }
37
38 // =======================================================================
39 // function : fresnelNormal
40 // purpose  :
41 // =======================================================================
42 inline float fresnelNormal (float theN,
43                             float theK)
44 {
45   return ((theN - 1.f) * (theN - 1.f) + theK * theK) /
46          ((theN + 1.f) * (theN + 1.f) + theK * theK);
47 }
48
49 // =======================================================================
50 // function : CreateConductor
51 // purpose  :
52 // =======================================================================
53 Graphic3d_Fresnel Graphic3d_Fresnel::CreateConductor (const Graphic3d_Vec3& theRefractionIndex,
54                                                       const Graphic3d_Vec3& theAbsorptionIndex)
55 {
56   const Graphic3d_Vec3 aFresnel (fresnelNormal (theRefractionIndex.x(), theAbsorptionIndex.x()),
57                                  fresnelNormal (theRefractionIndex.y(), theAbsorptionIndex.y()),
58                                  fresnelNormal (theRefractionIndex.z(), theAbsorptionIndex.z()));
59
60   return Graphic3d_Fresnel (Graphic3d_FM_SCHLICK, aFresnel);
61 }
62
63 //=======================================================================
64 //function : DumpJson
65 //purpose  : 
66 //=======================================================================
67 void Graphic3d_Fresnel::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
68 {
69   OCCT_DUMP_CLASS_BEGIN (theOStream, Graphic3d_Fresnel)
70
71   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFresnelType)
72   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myFresnelData)
73 }
74
75 // =======================================================================
76 // function : Graphic3d_BSDF
77 // purpose  :
78 // =======================================================================
79 Graphic3d_BSDF::Graphic3d_BSDF()
80 : Ks (Graphic3d_Vec3 (0.f), 1.f)
81 {
82   FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
83   FresnelBase = Graphic3d_Fresnel::CreateConstant (1.f);
84 }
85
86 // =======================================================================
87 // function : operator==
88 // purpose  :
89 // =======================================================================
90 bool Graphic3d_BSDF::operator== (const Graphic3d_BSDF& theOther) const
91 {
92   return Kc          == theOther.Kc
93       && Kd          == theOther.Kd
94       && Kt          == theOther.Kt
95       && Ks          == theOther.Ks
96       && Le          == theOther.Le
97       && Absorption  == theOther.Absorption
98       && FresnelCoat == theOther.FresnelCoat
99       && FresnelBase == theOther.FresnelBase;
100 }
101
102 // =======================================================================
103 // function : Normalize
104 // purpose  :
105 // =======================================================================
106 void Graphic3d_BSDF::Normalize()
107 {
108   float aMax = 0.f;
109
110   for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
111   {
112     aMax = std::max (aMax, Kd[aChannelID] + Ks[aChannelID] + Kt[aChannelID]);
113   }
114
115   if (aMax > 1.f)
116   {
117     for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
118     {
119       Kd[aChannelID] /= aMax;
120       Ks[aChannelID] /= aMax;
121       Kt[aChannelID] /= aMax;
122     }
123   }
124 }
125
126 // =======================================================================
127 // function : CreateDiffuse
128 // purpose  :
129 // =======================================================================
130 Graphic3d_BSDF Graphic3d_BSDF::CreateDiffuse (const Graphic3d_Vec3& theWeight)
131 {
132   Graphic3d_BSDF aBSDF;
133
134   aBSDF.Kd = theWeight;
135
136   return aBSDF;
137 }
138
139 // =======================================================================
140 // function : CreateMetallic
141 // purpose  :
142 // =======================================================================
143 Graphic3d_BSDF Graphic3d_BSDF::CreateMetallic (const Graphic3d_Vec3& theWeight, const Graphic3d_Fresnel& theFresnel, const float theRoughness)
144 {
145   Graphic3d_BSDF aBSDF;
146
147   aBSDF.FresnelBase = theFresnel;
148
149   // Selecting between specular and glossy
150   // BRDF depending on the given roughness
151   aBSDF.Ks = Graphic3d_Vec4 (theWeight, theRoughness);
152
153   return aBSDF;
154 }
155
156 // =======================================================================
157 // function : CreateTransparent
158 // purpose  :
159 // =======================================================================
160 Graphic3d_BSDF Graphic3d_BSDF::CreateTransparent (const Graphic3d_Vec3& theWeight,
161                                                   const Graphic3d_Vec3& theAbsorptionColor,
162                                                   const float           theAbsorptionCoeff)
163 {
164   Graphic3d_BSDF aBSDF;
165
166   // Create Fresnel parameters for the coat layer;
167   // set it to 0 value to simulate ideal refractor
168   aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
169
170   aBSDF.Kt = theWeight;
171
172   // Link reflection and transmission coefficients
173   aBSDF.Kc.r() = aBSDF.Kt.r();
174   aBSDF.Kc.g() = aBSDF.Kt.g();
175   aBSDF.Kc.b() = aBSDF.Kt.b();
176
177   aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
178                                      theAbsorptionCoeff);
179
180   return aBSDF;
181 }
182
183 // =======================================================================
184 // function : CreateGlass
185 // purpose  :
186 // =======================================================================
187 Graphic3d_BSDF Graphic3d_BSDF::CreateGlass (const Graphic3d_Vec3& theWeight,
188                                             const Graphic3d_Vec3& theAbsorptionColor,
189                                             const float           theAbsorptionCoeff,
190                                             const float           theRefractionIndex)
191 {
192   Graphic3d_BSDF aBSDF;
193
194   // Create Fresnel parameters for the coat layer
195   aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateDielectric (theRefractionIndex);
196
197   aBSDF.Kt = theWeight;
198
199   aBSDF.Kc.r() = aBSDF.Kt.r();
200   aBSDF.Kc.g() = aBSDF.Kt.g();
201   aBSDF.Kc.b() = aBSDF.Kt.b();
202
203   aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
204                                      theAbsorptionCoeff);
205
206   return aBSDF;
207 }
208
209 // =======================================================================
210 // function : CreateMetallicRoughness
211 // purpose  :
212 // =======================================================================
213 Graphic3d_BSDF Graphic3d_BSDF::CreateMetallicRoughness (const Graphic3d_PBRMaterial& thePbr)
214 {
215   const Graphic3d_Vec3 aDiff = (Graphic3d_Vec3 )thePbr.Color().GetRGB() * thePbr.Alpha();
216   const Standard_ShortReal aRougness2 = thePbr.NormalizedRoughness() * thePbr.NormalizedRoughness();
217
218   Graphic3d_BSDF aBsdf;
219   aBsdf.Le = thePbr.Emission();
220   if (thePbr.IOR() > 1.0f
221    && thePbr.Alpha() < 1.0f
222    && thePbr.Metallic() <= ShortRealEpsilon())
223   {
224     aBsdf.FresnelCoat = Graphic3d_Fresnel::CreateDielectric (thePbr.IOR());
225     aBsdf.Kt = Graphic3d_Vec3(1.0f);
226     aBsdf.Kc.r() = aBsdf.Kt.r();
227     aBsdf.Kc.g() = aBsdf.Kt.g();
228     aBsdf.Kc.b() = aBsdf.Kt.b();
229     aBsdf.Absorption.SetValues (thePbr.Color().GetRGB(), thePbr.Alpha() * 0.25f);
230   }
231   else
232   {
233     aBsdf.FresnelBase = Graphic3d_Fresnel::CreateSchlick (aDiff * thePbr.Metallic());
234     aBsdf.Ks.SetValues (Graphic3d_Vec3 (thePbr.Alpha()), aRougness2);
235     aBsdf.Kt = Graphic3d_Vec3 (1.0f - thePbr.Alpha());
236     aBsdf.Kd = aDiff * (1.0f - thePbr.Metallic());
237   }
238
239   return aBsdf;
240 }
241
242 //=======================================================================
243 //function : DumpJson
244 //purpose  : 
245 //=======================================================================
246 void Graphic3d_BSDF::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
247 {
248   OCCT_DUMP_CLASS_BEGIN (theOStream, Graphic3d_BSDF)
249
250   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Kc)
251   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Kd)
252   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Ks)
253   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Kt)
254   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Le)
255   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &Absorption)
256
257   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &FresnelCoat)
258   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &FresnelBase)
259 }