SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLSkybox.cpp
Go to the documentation of this file.
1 /**
2  * \file SLSkybox
3  * \authors Marcus Hudritsch
4  * \date December 2017
5  * \authors Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #include <SLBox.h>
12 #include <SLGLProgramGeneric.h>
13 #include <SLGLTexture.h>
14 #include <SLGLTextureIBL.h>
15 #include <SLMaterial.h>
16 #include <SLSceneView.h>
17 #include <SLSkybox.h>
18 
19 //-----------------------------------------------------------------------------
20 /**
21  * @brief Construct a new SLSkybox::SLSkybox object with 6 images for all sides
22  * @details It is important that during instantiation NO OpenGL functions (gl*)
23  * get called because this constructor will be most probably called in a parallel
24  * thread from within a SLScene::assemble function. All objects that get rendered
25  * have to do their OpenGL initialization when they are used the first time
26  * during rendering in the main thread.
27  * @param assetMgr Asset manager that will own the skybox mesh
28  * @param shaderPath Path to the shader files
29  * @param cubeMapXPos Texture image file for the positive X side
30  * @param cubeMapXNeg Texture image file for the negative X side
31  * @param cubeMapYPos Texture image file for the positive Y side
32  * @param cubeMapYNeg Texture image file for the negative Y side
33  * @param cubeMapZPos Texture image file for the positive Z side
34  * @param cubeMapZNeg Texture image file for the negative Z side
35  * @param name Name of the skybox
36  */
38  SLstring shaderPath,
39  SLstring cubeMapXPos,
40  SLstring cubeMapXNeg,
41  SLstring cubeMapYPos,
42  SLstring cubeMapYNeg,
43  SLstring cubeMapZPos,
44  SLstring cubeMapZNeg,
45  SLstring name) : SLNode(name)
46 {
47  assert(assetMgr &&
48  "SLSkybox: asset manager is currently mandatory for sky-boxes! "
49  "Alternatively the live-time of the box has to be managed in the sky-box!");
50 
51  // Set HDR flag to false, this is a normal SkyBox
52  _isHDR = false;
53  _isBuilt = true;
54  _environmentCubemap = nullptr;
55  _irradianceCubemap = nullptr;
56  _roughnessCubemap = nullptr;
57  _brdfLutTexture = nullptr;
58  _hdrTexture = nullptr;
59  _exposure = 1.0f;
60 
61  // Create texture, material and program
62  _environmentCubemap = new SLGLTexture(assetMgr,
63  cubeMapXPos,
64  cubeMapXNeg,
65  cubeMapYPos,
66  cubeMapYNeg,
67  cubeMapZPos,
68  cubeMapZNeg);
69 
70  SLMaterial* matCubeMap = new SLMaterial(assetMgr, "matCubeMap");
71  matCubeMap->addTexture(_environmentCubemap);
72 
73  SLGLProgram* sp = new SLGLProgramGeneric(assetMgr,
74  shaderPath + "SkyBox.vert",
75  shaderPath + "SkyBox.frag");
76  matCubeMap->program(sp);
77 
78  // Create a box with max. point at min. parameter and vice versa.
79  // Like this the boxes normals will point to the inside.
80  addMesh(new SLBox(assetMgr,
81  10,
82  10,
83  10,
84  -10,
85  -10,
86  -10,
87  "box",
88  matCubeMap));
89 }
90 //-----------------------------------------------------------------------------
91 //! Constructor for a cube map skybox from a HDR Image
92 /*! This constructor generates a cube map skybox from a HDR Image and also
93 all the textures needed for image based lighting and store them in the textures
94 of the material of this sky box.
95 */
96 
97 /**
98  * @brief Construct a new SLSkybox::SLSkybox object with an HDR image
99  * @details This constructor generates a cube map skybox from a HDR Image and also
100  * all the textures needed for image based lighting and store them in the textures
101  * of the material of this sky box.\n
102  * @remarks It is important that during instantiation NO OpenGL functions (gl*)
103  * get called because this constructor will be most probably called in a parallel
104  * thread from within an SLScene::registerAssetsToLoad or SLScene::assemble
105  * function. All objects that get rendered have to do their OpenGL initialization
106  * when they are used the first time during rendering in the main thread.
107  * @param assetMgr Asset manager that will own the skybox mesh
108  * @param shaderPath Path to the shader files
109  * @param hdrImage HDR texture image file
110  * @param resolution Resolution of the texture objects for image based lighting
111  * @param name Name of the skybox
112  */
114  SLstring shaderPath,
115  SLstring hdrImage,
116  SLVec2i resolution,
117  SLstring name) : SLNode(name)
118 {
119  // Set HDR flag to true, this is a HDR SkyBox
120  _isHDR = true;
121  _isBuilt = false;
122  _exposure = 1.0f;
123 
124  // Create shader program for the background
125  SLGLProgram* backgroundShader = new SLGLProgramGeneric(am,
126  shaderPath + "PBR_SkyboxHDR.vert",
127  shaderPath + "PBR_SkyboxHDR.frag");
128 
129  // The HDR texture is only used to create the environment,
130  // the irradiance and the roughness cubemaps
131  _hdrTexture = new SLGLTexture(am,
132  hdrImage,
133  GL_LINEAR,
134  GL_LINEAR,
135  TT_hdr,
136  GL_CLAMP_TO_EDGE,
137  GL_CLAMP_TO_EDGE);
138 
139  // The environment cubemap is used for the rendering of the skybox
141  shaderPath,
142  _hdrTexture,
143  resolution,
145  GL_TEXTURE_CUBE_MAP,
146  true, // read back environment for ray tracing
147  GL_LINEAR_MIPMAP_LINEAR);
148 
149  // The irradiance cubemap is used for the ambient indirect light of PBR materials
151  shaderPath,
153  SLVec2i(32, 32),
155  GL_TEXTURE_CUBE_MAP);
156 
157  // The roughness cubemap is used for the blurred reflections on PBR materials
159  shaderPath,
161  SLVec2i(128, 128),
163  GL_TEXTURE_CUBE_MAP);
164 
165  // The BRDF lookup texture is used for the specular gloss reflection calculation
167  shaderPath,
168  nullptr,
169  SLVec2i(512, 512),
170  TT_brdfLUT,
171  GL_TEXTURE_2D);
172 
173  // Create the material of the sky box and store there the other texture to be used for other materials
174  SLMaterial* envMaterial = new SLMaterial(am, "matCubeMap");
175  envMaterial->addTexture(_environmentCubemap);
176  envMaterial->program(backgroundShader);
177  envMaterial->skybox(this);
178 
179  // Create the box for the sky box
180  addMesh(new SLBox(am,
181  10,
182  10,
183  10,
184  -10,
185  -10,
186  -10,
187  "box",
188  envMaterial));
189 }
190 
191 //-----------------------------------------------------------------------------
192 //! Builds all texture for HDR image based lighting
194 {
195  _hdrTexture->build(0);
200  _isBuilt = true;
201 }
202 //-----------------------------------------------------------------------------
203 //! Draw the skybox with a cube map with the camera in its center.
205 {
206  assert(sv && "No SceneView passed to SLSkybox::drawAroundCamera");
207 
208  SLGLState* stateGL = SLGLState::instance();
209 
210  if (_isHDR && !_isBuilt)
211  build();
212 
213  // Put skybox at the cameras position
214  translation(sv->camera()->translationWS());
215 
216  // Apply world transform
217  stateGL->modelMatrix = updateAndGetWM();
218 
219  // Freeze depth buffer
220  stateGL->depthMask(false);
221 
222  // Change depth buffer comparisons for HDR SkyBoxes
223  if (_isHDR)
224  stateGL->depthFunc(GL_LEQUAL);
225 
226  // Draw the box
227  drawMesh(sv);
228 
229  // Change back the depth buffer comparisons
230  stateGL->depthFunc(GL_LESS);
231 
232  // Unlock depth buffer
233  stateGL->depthMask(true);
234 }
235 //-----------------------------------------------------------------------------
236 //! Returns the color in the skybox at the the specified direction dir
238 {
239  if (_mesh && _mesh->mat())
240  {
241  SLMaterial* mat = _mesh->mat();
242 
243  if (!mat->textures(TT_diffuse).empty())
244  {
245  if (mat->textures(TT_diffuse)[0]->images().size() == 6)
246  {
247  SLGLTexture* tex = mat->textures(TT_diffuse)[0];
248  return tex->getTexelf(dir);
249  }
250  }
251 
252  if (!mat->textures(TT_environmentCubemap).empty())
253  {
254  if (mat->textures(TT_environmentCubemap)[0]->images().size() == 6)
255  {
257  return tex->getTexelf(dir);
258  }
259  }
260  }
261 
262  return SLCol4f::BLACK;
263 }
264 //-----------------------------------------------------------------------------
string SLstring
Definition: SL.h:158
@ TT_brdfLUT
Definition: SLGLTexture.h:93
@ TT_irradianceCubemap
Definition: SLGLTexture.h:91
@ TT_environmentCubemap
Definition: SLGLTexture.h:90
@ TT_roughnessCubemap
Definition: SLGLTexture.h:92
@ TT_diffuse
Definition: SLGLTexture.h:78
@ TT_hdr
Definition: SLGLTexture.h:89
SLVec2< SLint > SLVec2i
Definition: SLVec2.h:140
Toplevel holder of the assets meshes, materials, textures and shaders.
Axis aligned box mesh.
Definition: SLBox.h:31
Generic Shader Program class inherited from SLGLProgram.
Encapsulation of an OpenGL shader program object.
Definition: SLGLProgram.h:56
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
SLMat4f modelMatrix
Init all states.
Definition: SLGLState.h:89
void depthMask(SLbool state)
Definition: SLGLState.cpp:190
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
void depthFunc(SLenum func)
Definition: SLGLState.cpp:205
Texture object for OpenGL texturing.
Definition: SLGLTexture.h:110
virtual void build(SLint texUnit)
SLCol4f getTexelf(SLfloat u, SLfloat v, SLuint imgIndex=0)
SLGLTexture::getTexelf returns a pixel color from u & v texture coordinates.
Texture object generated in run time from another texture.
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
void skybox(SLSkybox *sb)
Definition: SLMaterial.h:207
void addTexture(SLGLTexture *texture)
Adds the passed texture to the equivalent texture type vector.
Definition: SLMaterial.cpp:348
SLVGLTexture & textures(SLTextureType type)
Definition: SLMaterial.h:233
void program(SLGLProgram *sp)
Definition: SLMaterial.h:205
SLMaterial * mat() const
Definition: SLMesh.h:177
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
virtual void drawMesh(SLSceneView *sv)
Draws the single mesh.
Definition: SLNode.cpp:176
void translation(const SLVec3f &pos, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:828
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
virtual void addMesh(SLMesh *mesh)
Definition: SLNode.cpp:157
SLMesh * _mesh
pointer to a single mesh
Definition: SLNode.h:346
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
void camera(SLCamera *camera)
Definition: SLSceneView.h:145
SLGLTexture * _environmentCubemap
Definition: SLSkybox.h:65
SLGLTexture * _hdrTexture
Definition: SLSkybox.h:69
void build()
Builds all texture for HDR image based lighting.
Definition: SLSkybox.cpp:193
SLCol4f colorAtDir(const SLVec3f &dir)
Returns the color in the skybox at the the specified direction dir.
Definition: SLSkybox.cpp:237
SLGLTexture * _irradianceCubemap
Definition: SLSkybox.h:66
SLbool _isHDR
flag for HDR skyboxes
Definition: SLSkybox.h:71
SLSkybox(SLAssetManager *assetMgr, SLstring shaderPath, SLstring cubeMapXPos, SLstring cubeMapXNeg, SLstring cubeMapYPos, SLstring cubeMapYNeg, SLstring cubeMapZPos, SLstring cubeMapZNeg, SLstring name="Default Skybox")
Construct a new SLSkybox::SLSkybox object with 6 images for all sides.
Definition: SLSkybox.cpp:37
void drawAroundCamera(SLSceneView *sv)
Draw the skybox with a cube map with the camera in its center.
Definition: SLSkybox.cpp:204
SLGLTexture * _roughnessCubemap
Definition: SLSkybox.h:67
SLGLTexture * _brdfLutTexture
Definition: SLSkybox.h:68
SLbool _isBuilt
flag for late HDR skybox building
Definition: SLSkybox.h:72
SLfloat _exposure
Definition: SLSkybox.h:70
static SLVec4 BLACK
Definition: SLVec4.h:213