Stellarium 0.14.3
Scenery3d.hpp
1 /*
2  * Stellarium Scenery3d Plug-in
3  *
4  * Copyright (C) 2011-15 Simon Parzer, Peter Neubauer, Georg Zotti, Andrei Borza, Florian Schaukowitsch
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
19  */
20 
21 #ifndef _SCENERY3D_HPP_
22 #define _SCENERY3D_HPP_
23 
24 #include "StelGui.hpp"
25 #include "StelModule.hpp"
26 #include "StelPainter.hpp"
27 #include "Landscape.hpp"
28 #include "SolarSystem.hpp"
29 
30 #include "OBJ.hpp"
31 #include "Heightmap.hpp"
32 #include "Frustum.hpp"
33 #include "Polyhedron.hpp"
34 #include "S3DEnum.hpp"
35 #include "SceneInfo.hpp"
36 #include "ShaderManager.hpp"
37 
38 #include <QMatrix4x4>
39 
40 //predeclarations
41 class QOpenGLFramebufferObject;
42 class Scenery3dMgr;
43 class LandscapeMgr;
44 
46 class Scenery3d
47 {
48 public:
50  Scenery3d(Scenery3dMgr *parent);
51  virtual ~Scenery3d();
52 
54  bool loadScene(const SceneInfo& scene);
55 
60  void handleKeys(QKeyEvent* e);
61 
64  void update(double deltaTime);
66  void drawCoordinatesText();
68  void drawDebug();
69 
71  void draw(StelCore* core);
73  void init();
74 
76  SceneInfo getCurrentScene() { return currentScene; }
77 
78  bool getDebugEnabled() const { return debugEnabled; }
79  void setDebugEnabled(bool debugEnabled) { this->debugEnabled = debugEnabled; }
80  bool getPixelLightingEnabled() const { return shaderParameters.pixelLighting; }
81  void setPixelLightingEnabled(const bool val) { shaderParameters.pixelLighting = val; invalidateCubemap(); }
82  bool getShadowsEnabled(void) const { return shaderParameters.shadows; }
83  void setShadowsEnabled(bool shadowsEnabled) { shaderParameters.shadows = shadowsEnabled; reinitShadowmapping = true; invalidateCubemap(); }
84  bool getUseSimpleShadows() const {return simpleShadows; }
85  void setUseSimpleShadows(bool val) { simpleShadows = val; reinitShadowmapping = true; invalidateCubemap(); }
86  bool getBumpsEnabled(void) const { return shaderParameters.bump; }
87  void setBumpsEnabled(bool bumpsEnabled) { shaderParameters.bump = bumpsEnabled; invalidateCubemap(); }
88  bool getTorchEnabled(void) const { return shaderParameters.torchLight; }
89  void setTorchEnabled(bool torchEnabled) { shaderParameters.torchLight = torchEnabled; invalidateCubemap(); }
90  S3DEnum::ShadowFilterQuality getShadowFilterQuality() const { return shaderParameters.shadowFilterQuality; }
91  void setShadowFilterQuality(S3DEnum::ShadowFilterQuality quality) { shaderParameters.shadowFilterQuality = quality; reinitShadowmapping=true; invalidateCubemap();}
92  bool getPCSS() const { return shaderParameters.pcss; }
93  void setPCSS(bool val) { shaderParameters.pcss = val; reinitShadowmapping = true; invalidateCubemap(); }
94  bool getLocationInfoEnabled(void) const { return textEnabled; }
95  void setLocationInfoEnabled(bool locationinfoenabled) { this->textEnabled = locationinfoenabled; }
96 
97  bool getLazyCubemapEnabled() const { return lazyDrawing; }
98  void setLazyCubemapEnabled(bool val) { lazyDrawing = val; }
99  double getLazyCubemapInterval() const { return lazyInterval; }
100  void setLazyCubemapInterval(double val) { lazyInterval = val; }
101 
102  //This has the be the most crazy method name in the plugin
103  void getLazyCubemapUpdateOnlyDominantFaceOnMoving(bool &val, bool &alsoSecondDominantFace) { val = updateOnlyDominantOnMoving; alsoSecondDominantFace = updateSecondDominantOnMoving; }
104  void setLazyCubemapUpdateOnlyDominantFaceOnMoving(bool val, bool alsoSecondDominantFace) { updateOnlyDominantOnMoving = val; updateSecondDominantOnMoving = alsoSecondDominantFace; }
105 
107  inline void invalidateCubemap() { lastCubemapUpdate = 0.0; }
108 
109  S3DEnum::CubemappingMode getCubemappingMode() const { return cubemappingMode; }
112  void setCubemappingMode(S3DEnum::CubemappingMode mode)
113  {
114  if(mode == S3DEnum::CM_CUBEMAP_GSACCEL && !isGeometryShaderCubemapSupported())
115  {
116  //fallback to 6 Textures mode
117  mode = S3DEnum::CM_TEXTURES;
118  }
119  if(mode == S3DEnum::CM_CUBEMAP && isANGLEContext())
120  {
121  //Cubemap mode disabled on ANGLE because of an implementation bug with Qt 5.4's version
122  mode = S3DEnum::CM_TEXTURES;
123  }
124  cubemappingMode = mode; reinitCubemapping = true;
125  }
126 
127  void setUseFullCubemapShadows(bool val) { fullCubemapShadows = val; invalidateCubemap();}
128  bool getUseFullCubemapShadows() const { return fullCubemapShadows; }
129 
130  uint getCubemapSize() const { return cubemapSize; }
132  void setCubemapSize(uint size) { cubemapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitCubemapping = true; }
133  uint getShadowmapSize() const { return shadowmapSize; }
135  void setShadowmapSize(uint size) { shadowmapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitShadowmapping = true; }
136  float getTorchBrightness() const { return torchBrightness; }
137  void setTorchBrightness(float brightness) { torchBrightness = brightness; invalidateCubemap(); }
138  float getTorchRange() const { return torchRange; }
139  void setTorchRange(float range) { torchRange = range; invalidateCubemap(); }
140 
141  void setLoadCancel(bool val) { loadCancel = val; }
142 
145  void setGridPosition(Vec3d pos);
147  Vec3d getCurrentGridPosition() const;
148 
150  void setEyeHeight(const float eyeheight) { eye_height = eyeheight; }
152  float getEyeHeight() const { return eye_height; }
153 
154  enum ShadowCaster { None, Sun, Moon, Venus };
155 
157  ShaderMgr& getShaderManager() { return shaderManager; }
158 
160  void finalizeLoad();
161 
162  //these are some properties that determine the features supported in the current GL context
163  //available after init() is called
164  bool isGeometryShaderCubemapSupported() { return supportsGSCubemapping; }
165  bool areShadowsSupported() { return supportsShadows; }
166  bool isShadowFilteringSupported() { return supportsShadowFiltering; }
167  bool isANGLEContext() { return isANGLE; }
168  unsigned int getMaximumFramebufferSize() { return maximumFramebufferSize; }
169 
170 private:
171  Scenery3dMgr* parent;
172  SceneInfo currentScene,loadingScene;
173  ShaderMgr shaderManager;
174  PlanetP sun,moon,venus;
175 
176  bool supportsGSCubemapping; //if the GL context supports geometry shader cubemapping
177  bool supportsShadows; //if shadows are supported
178  bool supportsShadowFiltering; //if shadow filtering is supported
179  bool isANGLE; //true if running on ANGLE
180  unsigned int maximumFramebufferSize;
181 
182  float torchBrightness; // toggle light brightness
183  float torchRange; // used to calculate attenuation like in the second form at http://framebunker.com/blog/lighting-2-attenuation/
184 
185  bool textEnabled; // switchable value: display coordinates on screen. THIS IS NOT FOR DEBUGGING, BUT A PROGRAM FEATURE!
186  bool debugEnabled; // switchable value: display debug graphics and debug texts on screen
187  bool fixShadowData; //for debugging, fixes all shadow mapping related data (shadowmap contents, matrices, frustums, focus bodies...) at their current values
188  bool simpleShadows;
189  bool fullCubemapShadows;
190  S3DEnum::CubemappingMode cubemappingMode;
191  bool reinitCubemapping,reinitShadowmapping;
192 
193  bool loadCancel; //true if loading process should be canceled
194 
195  unsigned int cubemapSize; // configurable values, typically 512/1024/2048/4096
196  unsigned int shadowmapSize;
197 
198  Vec3d absolutePosition; // current eyepoint in model (note: this is actually the negated position, i.e. the value used to translate the view matrix)
199  Vec3d moveVector; // position change in scene coords
200  Vec3f movement; // speed values for moving around the scenery
201  float eye_height;
202 
203  StelCore* core;
204  LandscapeMgr* landscapeMgr;
205  StelProjectorP altAzProjector;
206  QSharedPointer<OBJ> objModel, objModelLoad, groundModel, groundModelLoad;
207  Heightmap* heightmap;
208  Heightmap* heightmapLoad;
209 
210  Vec3d mainViewUp;
211  Vec3d mainViewDir;
212  Vec3d viewPos;
213 
214  int drawnTriangles,drawnModels;
215  int materialSwitches, shaderSwitches;
216 
218  bool requiresCubemap; //true if cubemapping is required (if projection is anything else than Perspective)
219  bool cubemappingUsedLastFrame; //true if cubemapping was used for the last frame. Used to determine if a projection switch occured.
220  bool lazyDrawing; //if lazy-drawing mode is enabled
221  bool updateOnlyDominantOnMoving; //if movement updates only dominant face directly
222  bool updateSecondDominantOnMoving; //if movement also updates the second-most dominant face
223  bool needsMovementEndUpdate;
224  bool needsCubemapUpdate; //if the draw-call has to recreate the cubemap completely
225  bool needsMovementUpdate; //if the draw-call has to recreate either the whole cubemap or the dominant face
226  double lazyInterval; //the lazy-drawing time interval
227  double lastCubemapUpdate; //when the last lazy draw happened (JDay)
228  qint64 lastCubemapUpdateRealTime; //when the last lazy draw happened (real system time, QDateTime::currentMSecsSinceEpoch)
229  qint64 lastMovementEndRealTime; //the timepoint when the last movement was stopped
230  GLuint cubeMapCubeTex; //GL_TEXTURE_CUBE_MAP, used in CUBEMAP or CUBEMAP_GSACCEL modes
231  GLuint cubeMapCubeDepth; //this is a depth-cubemap, only used in CUBEMAP_GSACCEL mode
232  GLuint cubeMapTex[6]; //GL_TEXTURE_2D, for "legacy" TEXTURES mode
233  GLuint cubeRB; //renderbuffer for depth of a single face in TEXTURES and CUBEMAP modes (attached to multiple FBOs)
234  int dominantFace,secondDominantFace;
235 
236  //because of use that deviates very much from QOpenGLFramebufferObject typical usage, we manage the FBOs ourselves
237  GLuint cubeFBO; //used in CUBEMAP_GSACCEL mode - only a single FBO exists, with a cubemap for color and one for depth
238  GLuint cubeSideFBO[6]; //used in TEXTURES and CUBEMAP mode, 6 textures/cube faces for color and a shared depth renderbuffer (we don't require the depth after rendering)
239 
240  bool cubeMappingCreated; //true if any cubemapping objects have been initialized and need to be cleaned up eventually
241 
242  //cube geometry
243  QVector<Vec3f> cubeVertices, transformedCubeVertices;
244  QVector<Vec2f> cubeTexcoords;
245  QOpenGLBuffer cubeVertexBuffer;
246  QOpenGLBuffer cubeIndexBuffer;
247  int cubeIndexCount;
248 
249  //cube rendering matrices
250  QMatrix4x4 cubeRotation[6]; //rotational matrices for cube faces. The cam position is added to this in each frame.
251  QMatrix4x4 cubeMVP[6]; //cube face MVP matrices
252 
254  //final model view matrix for shader upload
255  QMatrix4x4 modelViewMatrix;
256  //currently valid projection matrix for shader upload
257  QMatrix4x4 projectionMatrix;
258 
259  // a struct which encapsulates lighting info
260  struct LightParameters
261  {
262  QMatrix4x4 shadowModelView;
263 
264  ShadowCaster lightSource;
265  Vec3f lightDirectionV3f;
266  QVector3D lightDirectionWorld;
267  QVector3D ambient;
268  QVector3D directional;
269  QVector3D specular;
270  QVector3D emissive;
271 
272  QVector3D torchDiffuse;
273  float torchAttenuation;
274  } lightInfo;
275 
276  GlobalShaderParameters shaderParameters;
277 
278  //Scene AABB
279  AABB sceneBoundingBox;
280 
281  //Shadow Map FBO handles
282  QVector<GLuint> shadowFBOs;
283  //Holds the shadow textures
284  QVector<GLuint> shadowMapsArray;
285  //Holds the shadow transformation matrix per split (Crop/Projection/View)
286  QVector<QMatrix4x4> shadowCPM;
287  //Holds the xy-scaling of the orthographic light cam + pos of near/far planes in view coords
288  //Needed for consistent shadow filter sizes and PCSS effect
289  QVector<QVector4D> shadowFrustumSize;
290  // Frustum of the view camera, constrainted to the shadowFarZ instead of the camFarZ
291  Frustum camFrustShadow;
292  //near/far planes for the orthographic light that fits the whole scene
293  float lightOrthoNear;
294  float lightOrthoFar;
295  //Array holding the split frustums
296  QVector<Frustum> frustumArray;
297  //Vector holding the convex split bodies for focused shadow mapping
298  QVector<Polyhedron> focusBodies;
299 
300  float parallaxScale;
301 
302  QFont debugTextFont;
303 
304  QString lightMessage; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
305  QString lightMessage2; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
306  QString lightMessage3; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
307 
308  // --- initialization
310  void determineFeatureSupport();
312  bool initCubemapping();
314  void deleteCubemapping();
315 
317  bool initShadowmapping();
319  void deleteShadowmapping();
320 
321  void calcCubeMVP();
322 
323  // --- drawing methods ---
325  void drawDirect();
327  void drawWithCubeMap();
329  bool renderShadowMaps();
331  void renderShadowMapsForFace(int face);
333  void generateCubeMap();
335  void renderIntoCubemapGeometryShader();
337  void renderIntoCubemapSixPasses();
339  void drawFromCubeMap();
343  bool drawArrays(bool shading=true, bool blendAlphaAdditive=false);
344 
345 
346  // --- shading related stuff ---
348  void calculateShadowCaster();
350  void calculateLighting();
352  void setupPassUniforms(QOpenGLShaderProgram *shader);
354  void setupFrameUniforms(QOpenGLShaderProgram *shader);
356  void setupMaterialUniforms(QOpenGLShaderProgram *shader, const OBJ::Material& mat);
357 
359  Scenery3d::ShadowCaster calculateLightSource(float &ambientBrightness, float &diffuseBrightness, Vec3f &lightsourcePosition, float &emissiveFactor);
360 
362  float groundHeight();
363 
364  //Sets the scenes' AABB
365  void setSceneAABB(const AABB &bbox);
366 
367  //Save the Frustum to be able to move away from it and analyze it
368  void saveFrusts();
369 
371  void adjustShadowFrustum(const Vec3d viewPos, const Vec3d viewDir, const Vec3d viewUp, const float fov, const float aspect);
372  //Computes the frustum splits
373  void computeFrustumSplits(const Vec3d viewPos, const Vec3d viewDir, const Vec3d viewUp);
374  //Computes the focus body for given frustum
375  void computePolyhedron(Polyhedron& body, const Frustum& frustum, const Vec3f &shadowDir);
376  //Computes the crop matrix to focus the light
377  void computeCropMatrix(QMatrix4x4& cropMatrix, QVector4D &orthoScale, Polyhedron &focusBody, const QMatrix4x4 &lightProj, const QMatrix4x4 &lightMVP);
378  //Computes the light projection values
379  void computeOrthoProjVals(const Vec3f shadowDir, float &orthoExtent, float &orthoNear, float &orthoFar);
380 };
381 
382 #endif
float getEyeHeight() const
Gets the current observer eye height (vertical difference from feet to camera position).
Definition: Scenery3d.hpp:152
void init()
Performs initialization that requires an valid OpenGL context.
Contains all the metadata necessary for a Scenery3d scene, and can be loaded from special ...
Definition: SceneInfo.hpp:34
void setCubemapSize(uint size)
Note: This may not set the size to the desired one because of hardware limits, call getCubemapSize to...
Definition: Scenery3d.hpp:132
void drawCoordinatesText()
Draw observer grid coordinates as text.
void setEyeHeight(const float eyeheight)
Sets the observer eye height.
Definition: Scenery3d.hpp:150
This represents a heightmap for viewer-ground collision.
Definition: Heightmap.hpp:27
void setCubemappingMode(S3DEnum::CubemappingMode mode)
Changes cubemapping mode and forces re-initialization on next draw call.
Definition: Scenery3d.hpp:112
void draw(StelCore *core)
Draw scenery, called by Scenery3dMgr.
This implementation is based on Stingl's Robust Hard Shadows.
Definition: Polyhedron.hpp:31
A structure for global shader parameters.
QSharedPointer< StelProjector > StelProjectorP
Main class of the module, inherits from StelModule.
void update(double deltaTime)
Update method, called by Scenery3dMgr.
An axis-aligned bounding-box class.
Definition: AABB.hpp:42
void handleKeys(QKeyEvent *e)
Walk/Fly Navigation with Ctrl+Cursor and Ctrl+PgUp/Dn keys.
A simple shader cache class that gives us the correct shader depending on desired configuration...
Representation of a complete 3D scenery.
Definition: Scenery3d.hpp:46
bool loadScene(const SceneInfo &scene)
Loads the specified scene.
ShadowFilterQuality
Contains different shadow filter settings.
Definition: S3DEnum.hpp:46
Scenery3d(Scenery3dMgr *parent)
Initializes an empty Scenery3d object.
void invalidateCubemap()
Does a cubemap redraw at the next possible opportunity when lazy-drawing is enabled.
Definition: Scenery3d.hpp:107
void drawDebug()
Draw some text output. This can be filled as needed by development.
void setShadowmapSize(uint size)
Note: This may not set the size to the desired one because of hardware limits, call getShadowmapSize ...
Definition: Scenery3d.hpp:135
SceneInfo getCurrentScene()
Gets the current scene's metadata.
Definition: Scenery3d.hpp:76
Vec3d getCurrentGridPosition() const
Gets the current position on the scene's grid (height at feet)
void finalizeLoad()
Loads the model into GL and sets the loaded scene to be the current one.
Encapsulates all information that the describes the surface appearance of a StelModel.
Definition: OBJ.hpp:71
void setGridPosition(Vec3d pos)
Sets the observer position to the specified grid coordinates.
ShaderMgr & getShaderManager()
Returns the shader manager this instance uses.
Definition: Scenery3d.hpp:157