67312b79 |
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 |