Stellarium 0.15.2
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 Scenery3dMgr;
42 class LandscapeMgr;
43 
45 class Scenery3d : protected QOpenGLFunctions
46 {
47 public:
49  Scenery3d(Scenery3dMgr *parent);
50  virtual ~Scenery3d();
51 
53  bool loadScene(const SceneInfo& scene);
54 
59  void handleKeys(QKeyEvent* e);
60 
63  void update(double deltaTime);
65  void drawCoordinatesText();
67  void drawDebug();
68 
70  void draw(StelCore* core);
72  void init();
73 
75  SceneInfo getCurrentScene() { return currentScene; }
76 
77  bool getDebugEnabled() const { return debugEnabled; }
78  void setDebugEnabled(bool debugEnabled) { this->debugEnabled = debugEnabled; }
79  bool getPixelLightingEnabled() const { return shaderParameters.pixelLighting; }
80  void setPixelLightingEnabled(const bool val) { shaderParameters.pixelLighting = val; invalidateCubemap(); }
81  bool getShadowsEnabled(void) const { return shaderParameters.shadows; }
82  void setShadowsEnabled(bool shadowsEnabled) { shaderParameters.shadows = shadowsEnabled; reinitShadowmapping = true; invalidateCubemap(); }
83  bool getUseSimpleShadows() const {return simpleShadows; }
84  void setUseSimpleShadows(bool val) { simpleShadows = val; reinitShadowmapping = true; invalidateCubemap(); }
85  bool getBumpsEnabled(void) const { return shaderParameters.bump; }
86  void setBumpsEnabled(bool bumpsEnabled) { shaderParameters.bump = bumpsEnabled; invalidateCubemap(); }
87  bool getTorchEnabled(void) const { return shaderParameters.torchLight; }
88  void setTorchEnabled(bool torchEnabled) { shaderParameters.torchLight = torchEnabled; invalidateCubemap(); }
89  S3DEnum::ShadowFilterQuality getShadowFilterQuality() const { return shaderParameters.shadowFilterQuality; }
90  void setShadowFilterQuality(S3DEnum::ShadowFilterQuality quality) { shaderParameters.shadowFilterQuality = quality; reinitShadowmapping=true; invalidateCubemap();}
91  bool getPCSS() const { return shaderParameters.pcss; }
92  void setPCSS(bool val) { shaderParameters.pcss = val; reinitShadowmapping = true; invalidateCubemap(); }
93  bool getLocationInfoEnabled(void) const { return textEnabled; }
94  void setLocationInfoEnabled(bool locationinfoenabled) { this->textEnabled = locationinfoenabled; }
95 
96  bool getLazyCubemapEnabled() const { return lazyDrawing; }
97  void setLazyCubemapEnabled(bool val) { lazyDrawing = val; }
98  double getLazyCubemapInterval() const { return lazyInterval; }
99  void setLazyCubemapInterval(double val) { lazyInterval = val; }
100 
101  //This has the be the most crazy method name in the plugin
102  void getLazyCubemapUpdateOnlyDominantFaceOnMoving(bool &val, bool &alsoSecondDominantFace) { val = updateOnlyDominantOnMoving; alsoSecondDominantFace = updateSecondDominantOnMoving; }
103  void setLazyCubemapUpdateOnlyDominantFaceOnMoving(bool val, bool alsoSecondDominantFace) { updateOnlyDominantOnMoving = val; updateSecondDominantOnMoving = alsoSecondDominantFace; }
104 
106  inline void invalidateCubemap() { lastCubemapUpdate = 0.0; }
107 
108  S3DEnum::CubemappingMode getCubemappingMode() const { return cubemappingMode; }
112  {
113  if(mode == S3DEnum::CM_CUBEMAP_GSACCEL && !isGeometryShaderCubemapSupported())
114  {
115  //fallback to 6 Textures mode
116  mode = S3DEnum::CM_TEXTURES;
117  }
118  if(mode == S3DEnum::CM_CUBEMAP && isANGLEContext())
119  {
120  //Cubemap mode disabled on ANGLE because of an implementation bug with Qt 5.4's version
121  mode = S3DEnum::CM_TEXTURES;
122  }
123  cubemappingMode = mode; reinitCubemapping = true;
124  }
125 
126  void setUseFullCubemapShadows(bool val) { fullCubemapShadows = val; invalidateCubemap();}
127  bool getUseFullCubemapShadows() const { return fullCubemapShadows; }
128 
129  uint getCubemapSize() const { return cubemapSize; }
131  void setCubemapSize(uint size) { cubemapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitCubemapping = true; }
132  uint getShadowmapSize() const { return shadowmapSize; }
134  void setShadowmapSize(uint size) { shadowmapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitShadowmapping = true; }
135  float getTorchBrightness() const { return torchBrightness; }
136  void setTorchBrightness(float brightness) { torchBrightness = brightness; invalidateCubemap(); }
137  float getTorchRange() const { return torchRange; }
138  void setTorchRange(float range) { torchRange = range; invalidateCubemap(); }
139 
140  void setLoadCancel(bool val) { loadCancel = val; }
141 
144  void setGridPosition(Vec3d pos);
147 
149  void setEyeHeight(const float eyeheight) { eye_height = eyeheight; }
151  float getEyeHeight() const { return eye_height; }
152 
153  enum ShadowCaster { None, Sun, Moon, Venus };
154 
156  ShaderMgr& getShaderManager() { return shaderManager; }
157 
159  void finalizeLoad();
160 
161  //these are some properties that determine the features supported in the current GL context
162  //available after init() is called
163  bool isGeometryShaderCubemapSupported() { return supportsGSCubemapping; }
164  bool areShadowsSupported() { return supportsShadows; }
165  bool isShadowFilteringSupported() { return supportsShadowFiltering; }
166  bool isANGLEContext() { return isANGLE; }
167  unsigned int getMaximumFramebufferSize() { return maximumFramebufferSize; }
168 
169 private:
170  Scenery3dMgr* parent;
171  SceneInfo currentScene,loadingScene;
172  ShaderMgr shaderManager;
173  PlanetP sun,moon,venus;
174 
175  bool supportsGSCubemapping; //if the GL context supports geometry shader cubemapping
176  bool supportsShadows; //if shadows are supported
177  bool supportsShadowFiltering; //if shadow filtering is supported
178  bool isANGLE; //true if running on ANGLE
179  unsigned int maximumFramebufferSize;
180  GLuint defaultFBO; //the default background FBO handle
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 transformedCubeVertexBuffer;
247  QOpenGLBuffer cubeIndexBuffer;
248  int cubeIndexCount;
249 
250  //cube rendering matrices
251  QMatrix4x4 cubeRotation[6]; //rotational matrices for cube faces. The cam position is added to this in each frame.
252  QMatrix4x4 cubeMVP[6]; //cube face MVP matrices
253 
255  //final model view matrix for shader upload
256  QMatrix4x4 modelViewMatrix;
257  //currently valid projection matrix for shader upload
258  QMatrix4x4 projectionMatrix;
259 
260  // a struct which encapsulates lighting info
261  struct LightParameters
262  {
263  QMatrix4x4 shadowModelView;
264 
265  ShadowCaster lightSource;
266  Vec3f lightDirectionV3f;
267  QVector3D lightDirectionWorld;
268  QVector3D ambient;
269  QVector3D directional;
270  QVector3D specular;
271  QVector3D emissive;
272 
273  QVector3D torchDiffuse;
274  float torchAttenuation;
275  } lightInfo;
276 
277  GlobalShaderParameters shaderParameters;
278 
279  //Scene AABB
280  AABB sceneBoundingBox;
281 
282  //Shadow Map FBO handles
283  QVector<GLuint> shadowFBOs;
284  //Holds the shadow textures
285  QVector<GLuint> shadowMapsArray;
286  //Holds the shadow transformation matrix per split (Crop/Projection/View)
287  QVector<QMatrix4x4> shadowCPM;
288  //Holds the xy-scaling of the orthographic light cam + pos of near/far planes in view coords
289  //Needed for consistent shadow filter sizes and PCSS effect
290  QVector<QVector4D> shadowFrustumSize;
291  // Frustum of the view camera, constrainted to the shadowFarZ instead of the camFarZ
292  Frustum camFrustShadow;
293  //near/far planes for the orthographic light that fits the whole scene
294  float lightOrthoNear;
295  float lightOrthoFar;
296  //Array holding the split frustums
297  QVector<Frustum> frustumArray;
298  //Vector holding the convex split bodies for focused shadow mapping
299  QVector<Polyhedron> focusBodies;
300 
301  float parallaxScale;
302 
303  QFont debugTextFont;
304 
305  QString lightMessage; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
306  QString lightMessage2; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
307  QString lightMessage3; // DEBUG/TEST ONLY. contains on-screen info on ambient/directional light strength and source.
308 
309  // --- initialization
311  void determineFeatureSupport();
313  bool initCubemapping();
315  void deleteCubemapping();
316 
318  bool initShadowmapping();
320  void deleteShadowmapping();
321 
322  void calcCubeMVP();
323 
324  // --- drawing methods ---
326  void drawDirect();
328  void drawWithCubeMap();
330  bool renderShadowMaps();
332  void renderShadowMapsForFace(int face);
334  void generateCubeMap();
336  void renderIntoCubemapGeometryShader();
338  void renderIntoCubemapSixPasses();
340  void drawFromCubeMap();
344  bool drawArrays(bool shading=true, bool blendAlphaAdditive=false);
345 
346 
347  // --- shading related stuff ---
349  void calculateShadowCaster();
351  void calculateLighting();
353  void setupPassUniforms(QOpenGLShaderProgram *shader);
355  void setupFrameUniforms(QOpenGLShaderProgram *shader);
357  void setupMaterialUniforms(QOpenGLShaderProgram *shader, const OBJ::Material& mat);
358 
360  Scenery3d::ShadowCaster calculateLightSource(float &ambientBrightness, float &diffuseBrightness, Vec3f &lightsourcePosition, float &emissiveFactor);
361 
363  float groundHeight();
364 
365  //Sets the scenes' AABB
366  void setSceneAABB(const AABB &bbox);
367 
368  //Save the Frustum to be able to move away from it and analyze it
369  void saveFrusts();
370 
372  void adjustShadowFrustum(const Vec3d viewPos, const Vec3d viewDir, const Vec3d viewUp, const float fov, const float aspect);
373  //Computes the frustum splits
374  void computeFrustumSplits(const Vec3d viewPos, const Vec3d viewDir, const Vec3d viewUp);
375  //Computes the focus body for given frustum
376  void computePolyhedron(Polyhedron& body, const Frustum& frustum, const Vec3f &shadowDir);
377  //Computes the crop matrix to focus the light
378  void computeCropMatrix(QMatrix4x4& cropMatrix, QVector4D &orthoScale, Polyhedron &focusBody, const QMatrix4x4 &lightProj, const QMatrix4x4 &lightMVP);
379  //Computes the light projection values
380  void computeOrthoProjVals(const Vec3f shadowDir, float &orthoExtent, float &orthoNear, float &orthoFar);
381 };
382 
383 #endif
float getEyeHeight() const
Gets the current observer eye height (vertical difference from feet to camera position).
Definition: Scenery3d.hpp:151
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:131
Uses 6 textures, one for each side of the cube. Seems to be the best for old Intel drivers...
Definition: S3DEnum.hpp:38
void drawCoordinatesText()
Draw observer grid coordinates as text.
void setEyeHeight(const float eyeheight)
Sets the observer eye height.
Definition: Scenery3d.hpp:149
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:111
void draw(StelCore *core)
Draw scenery, called by Scenery3dMgr.
This implementation is based on Stingl&#39;s Robust Hard Shadows.
Definition: Polyhedron.hpp:31
A structure for global shader parameters.
Manages all the rendering at the level of the observer&#39;s surroundings.
Uses a single GL_TEXTURE_CUBEMAP, seems to work a bit better on "modern" GPUs.
Definition: S3DEnum.hpp:40
Main class for Stellarium core processing.
Definition: StelCore.hpp:48
QSharedPointer< StelProjector > StelProjectorP
Shared pointer on a StelProjector instance (implement reference counting)
Uses a single GL_TEXTURE_CUBEMAP and a geometry shader to render all 6 sides in one pass...
Definition: S3DEnum.hpp:42
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:45
bool loadScene(const SceneInfo &scene)
Loads the specified scene.
ShadowFilterQuality
Contains different shadow filter settings.
Definition: S3DEnum.hpp:46
CubemappingMode
Determines the method used for cubemap creation.
Definition: S3DEnum.hpp:35
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:106
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:134
SceneInfo getCurrentScene()
Gets the current scene&#39;s metadata.
Definition: Scenery3d.hpp:75
Vec3d getCurrentGridPosition() const
Gets the current position on the scene&#39;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:156