0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model
[occt.git] / src / OpenGl / OpenGl_PBREnvironment.hxx
1 // Author: Ilya Khramov
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _OpenGl_PBREnvironment_HeaderFile
16 #define _OpenGl_PBREnvironment_HeaderFile
17
18 #include <OpenGl_Texture.hxx>
19 #include <OpenGl_VertexBuffer.hxx>
20
21 //! This class contains specular and diffuse maps required for Image Base Lighting (IBL) in PBR shading model with it's generation methods.
22 class OpenGl_PBREnvironment : public OpenGl_NamedResource
23 {
24   DEFINE_STANDARD_RTTIEXT(OpenGl_PBREnvironment, OpenGl_NamedResource)
25 public:
26
27   //! Creates and initializes new PBR environment. It is the only way to create OpenGl_PBREnvironment.
28   //! @param theCtx OpenGL context where environment will be created
29   //! @param thePow2Size final size of texture's sides can be calculated as 2^thePow2Size;
30   //!                    if thePow2Size less than 1 it will be set to 1
31   //! @param theSpecMapLevelsNum number of mipmap levels used in specular IBL map;
32   //!                            if theSpecMapLevelsNum less than 2 or less than Pow2Size + 1 it will be set to the corresponding values.
33   //! @param theId OpenGl_Resource name
34   //! @return handle to created PBR environment or NULL handle in case of fail
35   Standard_EXPORT static Handle(OpenGl_PBREnvironment) Create (const Handle(OpenGl_Context)&  theCtx,
36                                                                unsigned int                   thePow2Size = 9,
37                                                                unsigned int                   theSpecMapLevelsNum = 6,
38                                                                const TCollection_AsciiString& theId = "PBREnvironment");
39
40 public:
41
42   //! Binds diffuse and specular IBL maps to the corresponding texture units.
43   Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx);
44
45   //! Unbinds diffuse and specular IBL maps.
46   Standard_EXPORT void Unbind (const Handle(OpenGl_Context)& theCtx);
47
48   //! Fills all mipmaps of specular IBL map and diffuse IBL map with one color.
49   //! So that environment illumination will be constant.
50   Standard_EXPORT void Clear (const Handle(OpenGl_Context)& theCtx,
51                               const Graphic3d_Vec3&         theColor = Graphic3d_Vec3 (1.f));
52
53   //! Generates specular and diffuse (irradiance) IBL maps.
54   //! @param theCtx OpenGL context
55   //! @param theEnvMap source environment map
56   //! @param theZIsInverted flags indicates whether environment cubemap has inverted Z axis or not
57   //! @param theIsTopDown flags indicates whether environment cubemap has top-down memory layout or not
58   //! @param theDiffMapNbSamples number of samples in Monte-Carlo integration for diffuse IBL spherical harmonics calculation
59   //! @param theSpecMapNbSamples number of samples in Monte-Carlo integration for specular IBL map generation
60   //! @param theProbability controls strength of samples number reducing strategy during specular IBL map baking (see 'SpecIBLMapSamplesFactor' for details)
61   //! theZIsInverted and theIsTopDown can be taken from Graphic3d_CubeMap source of environment cubemap.
62   //! theDiffMapNbSamples and theSpecMapNbSamples is the main parameter directly affected to performance.
63   Standard_EXPORT void Bake (const Handle(OpenGl_Context)& theCtx,
64                              const Handle(OpenGl_Texture)& theEnvMap,
65                              Standard_Boolean              theZIsInverted = Standard_False,
66                              Standard_Boolean              theIsTopDown = Standard_True,
67                              Standard_Size                 theDiffMapNbSamples = 1024,
68                              Standard_Size                 theSpecMapNbSamples = 256,
69                              Standard_ShortReal            theProbability = 0.99f);
70
71   //! Returns number of mipmap levels used in specular IBL map.
72   //! It can be different from value passed to creation method.
73   unsigned int SpecMapLevelsNumber() const { return mySpecMapLevelsNumber; }
74
75   //! Returns size of IBL maps sides as power of 2.
76   //! So that the real size can be calculated as 2^Pow2Size()
77   unsigned int Pow2Size() const { return myPow2Size; }
78
79   //! Checks whether the given sizes affects to the current ones.
80   //! It can be imagined as creation of new PBR environment.
81   //! If creation method with this values returns the PBR environment having real sizes which are equals to current ones
82   //! then this method will return false.
83   //! It is handful when sizes are required to be changed.
84   //! If this method returns false there is no reason to recreate PBR environment in order to change sizes.
85   Standard_EXPORT bool SizesAreDifferent (unsigned int thePow2Size,
86                                           unsigned int theSpecMapLevelsNumber) const;
87
88   //! Indicates whether IBL map's textures have to be bound or it is not obligate.
89   bool IsNeededToBeBound() const
90   {
91     return myIsNeededToBeBound;
92   }
93
94   //! Releases all OpenGL resources.
95   //! It must be called before destruction.
96   Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
97
98   //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
99   virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE
100   {
101     unsigned int aDiffIBLMapSidePixelsCount = 1 << myPow2Size;
102     aDiffIBLMapSidePixelsCount *= aDiffIBLMapSidePixelsCount;
103     Standard_Size anEstimatedDataSize = aDiffIBLMapSidePixelsCount;
104     for (unsigned int i = 0; i < mySpecMapLevelsNumber; ++i)
105     {
106       anEstimatedDataSize += aDiffIBLMapSidePixelsCount >> (2 * i);
107     }
108     anEstimatedDataSize *= 6; // cubemap sides
109     anEstimatedDataSize *= 3; // channels
110     return anEstimatedDataSize;
111   }
112
113   //! Checks completeness of PBR environment.
114   //! Creation method returns only completed objects or null handles otherwise.
115   Standard_Boolean IsComplete() const { return myIsComplete; }
116
117   //! Destructor.
118   //! Warning! 'Release' method must be called before destruction.
119   //! Otherwise unhandled critical error will be generated.
120   Standard_EXPORT virtual ~OpenGl_PBREnvironment();
121
122 private:
123
124   //! Creates new PBR environment.
125   //! Parameters and logic are described in 'Create' method documentation.
126   Standard_EXPORT OpenGl_PBREnvironment (const Handle(OpenGl_Context)&  theCtx,
127                                          unsigned int                   thePowOf2Size = 9,
128                                          unsigned int                   theSpecMapLevelsNumber = 6,
129                                          const TCollection_AsciiString& theId = "PBREnvironment");
130
131 private:
132
133   //! Enum classified the type of IBL map
134   enum OpenGl_TypeOfIBLMap
135   {
136     OpenGl_TypeOfIBLMap_DiffuseSH,
137     OpenGl_TypeOfIBLMap_Specular
138   };
139
140   //! Initializes all textures.
141   //! @return false in case of failed texture initialization
142   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
143   bool initTextures (const Handle(OpenGl_Context)& theCtx);
144
145   //! Creates frame buffer object for IBL maps generation.
146   //! @return false in case of failed FBO initialization
147   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
148   bool initFBO (const Handle(OpenGl_Context)& theCtx);
149
150   //! Initializes vertex buffer object of screen rectangle.
151   //! @return false in case of failed creation
152   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
153   bool initVAO (const Handle(OpenGl_Context)& theCtx);
154
155   //! Responses for diffuse (irradiance) IBL map processing.
156   //! @return false in case of failed baking or clearing
157   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
158   bool processDiffIBLMap (const Handle(OpenGl_Context)& theCtx,
159                           Standard_Boolean      theIsDrawAction,
160                           Standard_Size         theNbSamples = 0);
161
162   //! Responses for specular IBL map processing.
163   //! @return false in case of failed baking or clearing
164   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
165   bool processSpecIBLMap (const Handle(OpenGl_Context)& theCtx,
166                           Standard_Boolean   theIsDrawAction,
167                           Standard_Integer   theEnvMapSize = 1024,
168                           Standard_Size      theNbSamples = 0,
169                           Standard_ShortReal theProbability = 1.f);
170
171   //! Checks completeness of frame buffer object for all targets
172   //! (all cube map sides and levels of IBL maps).
173   //! @return false in case of uncompleted frame buffer object.
174   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
175   bool checkFBOComplentess (const Handle(OpenGl_Context)& theCtx) const;
176
177   //! Version of 'Bake' without OpenGl_PBREnvironmentSetnry.
178   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
179   void bake (const Handle(OpenGl_Context)& theCtx,
180              const Handle(OpenGl_Texture)& theEnvMap,
181              Standard_Boolean              theZIsInverted = Standard_False,
182              Standard_Boolean              theIsTopDown = Standard_True,
183              Standard_Size                 theDiffMapNbSamples = 1024,
184              Standard_Size                 theSpecMapNbSamples = 256,
185              Standard_ShortReal            theProbability = 1.f);
186
187   //! Version of 'Clear' without OpenGl_PBREnvironmentSetnry.
188   //! Warning! Requires using of OpenGl_PBREnvironmentSentry.
189   void clear (const Handle(OpenGl_Context)& theCtx,
190               const Graphic3d_Vec3&         theColor = Graphic3d_Vec3 (1.f));
191
192 private:
193
194   unsigned int        myPow2Size;            //!< size of IBL maps sides (real size can be calculated as 2^myPow2Size)
195   unsigned int        mySpecMapLevelsNumber; //!< number of mipmap levels used in specular IBL map
196
197   OpenGl_Texture      myIBLMaps[2];          //!< IBL maps
198   OpenGl_VertexBuffer myVBO;                 //!< vertex buffer object of screen rectangular
199   GLuint              myFBO;                 //!< frame buffer object to generate or clear IBL maps
200
201   Standard_Boolean    myIsComplete;          //!< completeness of PBR environment
202   Standard_Boolean    myIsNeededToBeBound;   //!< indicates whether IBL map's textures have to be bound or it is not obligate
203
204 };
205
206 #endif // _OpenGl_PBREnvironment_HeaderFile