0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model
[occt.git] / src / Graphic3d / Graphic3d_BSDF.cxx
CommitLineData
189f85a3 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
67312b79 18#include <Graphic3d_PBRMaterial.hxx>
19
189f85a3 20#include <algorithm>
21
22// =======================================================================
23// function : Serialize
24// purpose :
25// =======================================================================
26Graphic3d_Vec4 Graphic3d_Fresnel::Serialize() const
27{
28 Graphic3d_Vec4 aData = Graphic3d_Vec4 (myFresnelData, 0.f);
29
30 if (myFresnelType != Graphic3d_FM_SCHLICK)
31 {
05aa616d 32 aData.x() = -static_cast<float> (myFresnelType);
189f85a3 33 }
34
35 return aData;
36}
37
38// =======================================================================
39// function : fresnelNormal
40// purpose :
41// =======================================================================
05aa616d 42inline float fresnelNormal (float theN,
43 float theK)
189f85a3 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// =======================================================================
53Graphic3d_Fresnel Graphic3d_Fresnel::CreateConductor (const Graphic3d_Vec3& theRefractionIndex,
54 const Graphic3d_Vec3& theAbsorptionIndex)
55{
05aa616d 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 : Graphic3d_BSDF
65// purpose :
66// =======================================================================
67Graphic3d_BSDF::Graphic3d_BSDF()
67312b79 68: Ks (Graphic3d_Vec3 (0.f), 1.f)
05aa616d 69{
70 FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
71 FresnelBase = Graphic3d_Fresnel::CreateConstant (1.f);
72}
73
74// =======================================================================
75// function : operator==
76// purpose :
77// =======================================================================
78bool Graphic3d_BSDF::operator== (const Graphic3d_BSDF& theOther) const
79{
80 return Kc == theOther.Kc
81 && Kd == theOther.Kd
82 && Kt == theOther.Kt
83 && Ks == theOther.Ks
84 && Le == theOther.Le
85 && Absorption == theOther.Absorption
86 && FresnelCoat == theOther.FresnelCoat
87 && FresnelBase == theOther.FresnelBase;
189f85a3 88}
89
90// =======================================================================
91// function : Normalize
92// purpose :
93// =======================================================================
94void Graphic3d_BSDF::Normalize()
95{
05aa616d 96 float aMax = 0.f;
97
98 for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
99 {
100 aMax = std::max (aMax, Kd[aChannelID] + Ks[aChannelID] + Kt[aChannelID]);
101 }
189f85a3 102
103 if (aMax > 1.f)
104 {
05aa616d 105 for (int aChannelID = 0; aChannelID < 3; ++aChannelID)
106 {
107 Kd[aChannelID] /= aMax;
108 Ks[aChannelID] /= aMax;
109 Kt[aChannelID] /= aMax;
110 }
189f85a3 111 }
112}
113
114// =======================================================================
115// function : CreateDiffuse
116// purpose :
117// =======================================================================
118Graphic3d_BSDF Graphic3d_BSDF::CreateDiffuse (const Graphic3d_Vec3& theWeight)
119{
120 Graphic3d_BSDF aBSDF;
121
122 aBSDF.Kd = theWeight;
123
124 return aBSDF;
125}
126
127// =======================================================================
128// function : CreateMetallic
129// purpose :
130// =======================================================================
05aa616d 131Graphic3d_BSDF Graphic3d_BSDF::CreateMetallic (const Graphic3d_Vec3& theWeight, const Graphic3d_Fresnel& theFresnel, const float theRoughness)
189f85a3 132{
133 Graphic3d_BSDF aBSDF;
134
05aa616d 135 aBSDF.FresnelBase = theFresnel;
189f85a3 136
137 // Selecting between specular and glossy
138 // BRDF depending on the given roughness
05aa616d 139 aBSDF.Ks = Graphic3d_Vec4 (theWeight, theRoughness);
189f85a3 140
141 return aBSDF;
142}
143
144// =======================================================================
145// function : CreateTransparent
146// purpose :
147// =======================================================================
05aa616d 148Graphic3d_BSDF Graphic3d_BSDF::CreateTransparent (const Graphic3d_Vec3& theWeight,
149 const Graphic3d_Vec3& theAbsorptionColor,
150 const float theAbsorptionCoeff)
189f85a3 151{
152 Graphic3d_BSDF aBSDF;
153
05aa616d 154 // Create Fresnel parameters for the coat layer;
155 // set it to 0 value to simulate ideal refractor
156 aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
157
189f85a3 158 aBSDF.Kt = theWeight;
159
05aa616d 160 // Link reflection and transmission coefficients
161 aBSDF.Kc.r() = aBSDF.Kt.r();
162 aBSDF.Kc.g() = aBSDF.Kt.g();
163 aBSDF.Kc.b() = aBSDF.Kt.b();
189f85a3 164
05aa616d 165 aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
166 theAbsorptionCoeff);
189f85a3 167
168 return aBSDF;
169}
170
171// =======================================================================
172// function : CreateGlass
173// purpose :
174// =======================================================================
05aa616d 175Graphic3d_BSDF Graphic3d_BSDF::CreateGlass (const Graphic3d_Vec3& theWeight,
176 const Graphic3d_Vec3& theAbsorptionColor,
177 const float theAbsorptionCoeff,
178 const float theRefractionIndex)
189f85a3 179{
180 Graphic3d_BSDF aBSDF;
181
05aa616d 182 // Create Fresnel parameters for the coat layer
183 aBSDF.FresnelCoat = Graphic3d_Fresnel::CreateDielectric (theRefractionIndex);
184
189f85a3 185 aBSDF.Kt = theWeight;
186
05aa616d 187 aBSDF.Kc.r() = aBSDF.Kt.r();
188 aBSDF.Kc.g() = aBSDF.Kt.g();
189 aBSDF.Kc.b() = aBSDF.Kt.b();
189f85a3 190
05aa616d 191 aBSDF.Absorption = Graphic3d_Vec4 (theAbsorptionColor,
192 theAbsorptionCoeff);
189f85a3 193
194 return aBSDF;
67312b79 195}
196
197// =======================================================================
198// function : CreateMetallicRoughness
199// purpose :
200// =======================================================================
201Graphic3d_BSDF Graphic3d_BSDF::CreateMetallicRoughness (const Graphic3d_PBRMaterial& thePbr)
202{
203 const Graphic3d_Vec3 aDiff = (Graphic3d_Vec3 )thePbr.Color().GetRGB() * thePbr.Alpha();
204 const Standard_ShortReal aRougness2 = thePbr.NormalizedRoughness() * thePbr.NormalizedRoughness();
205
206 Graphic3d_BSDF aBsdf;
207 aBsdf.FresnelBase = Graphic3d_Fresnel::CreateSchlick (aDiff * thePbr.Metallic());
208 aBsdf.Ks.SetValues (Graphic3d_Vec3 (thePbr.Alpha()), aRougness2);
209 aBsdf.Kt = Graphic3d_Vec3 (1.0f - thePbr.Alpha());
210 aBsdf.Kd = aDiff * (1.0f - thePbr.Metallic());
211 return aBsdf;
212}