Stellarium  0.90.0
S3DRenderer.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 _S3DRENDERER_HPP_
22 #define _S3DRENDERER_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 "StelOBJ.hpp"
31 #include "StelOpenGLArray.hpp"
32 #include "Heightmap.hpp"
33 #include "Frustum.hpp"
34 #include "Polyhedron.hpp"
35 #include "S3DEnum.hpp"
36 #include "SceneInfo.hpp"
37 #include "ShaderManager.hpp"
38 
39 #include <QMatrix4x4>
40 
41 //predeclarations
42 class LandscapeMgr;
43 class S3DScene;
44 
45 Q_DECLARE_LOGGING_CATEGORY(s3drenderer)
46 
47 class S3DRenderer : public QObject, protected QOpenGLFunctions
49 {
50  Q_OBJECT
51 public:
53  S3DRenderer(QObject* parent = Q_NULLPTR);
54  virtual ~S3DRenderer();
55 
57  void draw(StelCore* core, S3DScene &scene);
59  void init();
60 
61  bool getDebugEnabled() const { return debugEnabled; }
62  void setDebugEnabled(bool debugEnabled) { this->debugEnabled = debugEnabled; }
63  bool getPixelLightingEnabled() const { return shaderParameters.pixelLighting; }
64  void setPixelLightingEnabled(const bool val) { shaderParameters.pixelLighting = val; invalidateCubemap(); }
65  bool getShadowsEnabled(void) const { return shaderParameters.shadows; }
66  void setShadowsEnabled(bool shadowsEnabled) { shaderParameters.shadows = shadowsEnabled; reinitShadowmapping = true; invalidateCubemap(); }
67  bool getUseSimpleShadows() const {return simpleShadows; }
68  void setUseSimpleShadows(bool val) { simpleShadows = val; reinitShadowmapping = true; invalidateCubemap(); }
69  bool getBumpsEnabled(void) const { return shaderParameters.bump; }
70  void setBumpsEnabled(bool bumpsEnabled) { shaderParameters.bump = bumpsEnabled; invalidateCubemap(); }
71  bool getTorchEnabled(void) const { return shaderParameters.torchLight; }
72  void setTorchEnabled(bool torchEnabled) { shaderParameters.torchLight = torchEnabled; invalidateCubemap(); }
73  S3DEnum::ShadowFilterQuality getShadowFilterQuality() const { return shaderParameters.shadowFilterQuality; }
74  void setShadowFilterQuality(S3DEnum::ShadowFilterQuality quality) { shaderParameters.shadowFilterQuality = quality; reinitShadowmapping=true; invalidateCubemap();}
75  bool getPCSS() const { return shaderParameters.pcss; }
76  void setPCSS(bool val) { shaderParameters.pcss = val; reinitShadowmapping = true; invalidateCubemap(); }
77  bool getLocationInfoEnabled(void) const { return textEnabled; }
78  void setLocationInfoEnabled(bool locationinfoenabled) { this->textEnabled = locationinfoenabled; }
79 
80  bool getLazyCubemapEnabled() const { return lazyDrawing; }
81  void setLazyCubemapEnabled(bool val) { lazyDrawing = val; }
82  double getLazyCubemapInterval() const { return lazyInterval; }
83  void setLazyCubemapInterval(double val) { lazyInterval = val; }
84 
85  //This has the be the most crazy method name in the plugin
86  void getLazyCubemapUpdateOnlyDominantFaceOnMoving(bool &val, bool &alsoSecondDominantFace) const { val = updateOnlyDominantOnMoving; alsoSecondDominantFace = updateSecondDominantOnMoving; }
87  void setLazyCubemapUpdateOnlyDominantFaceOnMoving(bool val, bool alsoSecondDominantFace) { updateOnlyDominantOnMoving = val; updateSecondDominantOnMoving = alsoSecondDominantFace; }
88 
90  inline void invalidateCubemap() { lastCubemapUpdate = 0.0; }
91 
92  S3DEnum::CubemappingMode getCubemappingMode() const { return cubemappingMode; }
96  {
97  if(mode == S3DEnum::CM_CUBEMAP_GSACCEL && !isGeometryShaderCubemapSupported())
98  {
99  //fallback to 6 Textures mode
100  mode = S3DEnum::CM_TEXTURES;
101  }
102  if(mode == S3DEnum::CM_CUBEMAP && isANGLEContext())
103  {
104  //Cubemap mode disabled on ANGLE because of an implementation bug with Qt 5.4's version
105  mode = S3DEnum::CM_TEXTURES;
106  }
107  cubemappingMode = mode; reinitCubemapping = true;
108  }
109 
110  void setUseFullCubemapShadows(bool val) { fullCubemapShadows = val; invalidateCubemap();}
111  bool getUseFullCubemapShadows() const { return fullCubemapShadows; }
112 
113  uint getCubemapSize() const { return cubemapSize; }
115  void setCubemapSize(uint size) { cubemapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitCubemapping = true; }
116  uint getShadowmapSize() const { return shadowmapSize; }
118  void setShadowmapSize(uint size) { shadowmapSize = (size > maximumFramebufferSize ? maximumFramebufferSize : size); reinitShadowmapping = true; }
119  float getTorchBrightness() const { return torchBrightness; }
120  void setTorchBrightness(float brightness) { torchBrightness = brightness; invalidateCubemap(); }
121  float getTorchRange() const { return torchRange; }
122  void setTorchRange(float range) { torchRange = range; invalidateCubemap(); }
123 
124  //Debugging method, save the Frustum to be able to move away from it and analyze it
125  void saveFrusts();
126 
128  ShaderMgr& getShaderManager() { return shaderManager; }
129 
130  //these are some properties that determine the features supported in the current GL context
131  //available after init() is called
132  bool isGeometryShaderCubemapSupported() const { return supportsGSCubemapping; }
133  bool areShadowsSupported() const { return supportsShadows; }
134  bool isShadowFilteringSupported() const { return supportsShadowFiltering; }
135  bool isANGLEContext() const { return isANGLE; }
136  unsigned int getMaximumFramebufferSize() const { return maximumFramebufferSize; }
137 signals:
138  void message(const QString& msg) const;
139 
140 private:
141  ShaderMgr shaderManager;
142  PlanetP sun,moon,venus;
143  // a pointer to the scene currently being drawn. only valid during draw() calls
144  S3DScene* currentScene;
145 
146  bool supportsGSCubemapping; //if the GL context supports geometry shader cubemapping
147  bool supportsShadows; //if shadows are supported
148  bool supportsShadowFiltering; //if shadow filtering is supported
149  bool isANGLE; //true if running on ANGLE
150  unsigned int maximumFramebufferSize;
151  GLuint defaultFBO; //the default background FBO handle
152 
153  float torchBrightness; // toggle light brightness
154  float torchRange; // used to calculate attenuation like in the second form at http://framebunker.com/blog/lighting-2-attenuation/
155 
156  bool textEnabled; // switchable value: display coordinates on screen. THIS IS NOT FOR DEBUGGING, BUT A PROGRAM FEATURE!
157  bool debugEnabled; // switchable value: display debug graphics and debug texts on screen
158  bool fixShadowData; //for debugging, fixes all shadow mapping related data (shadowmap contents, matrices, frustums, focus bodies...) at their current values
159  bool simpleShadows;
160  bool fullCubemapShadows;
161  S3DEnum::CubemappingMode cubemappingMode;
162  bool reinitCubemapping,reinitShadowmapping;
163 
164  unsigned int cubemapSize; // configurable values, typically 512/1024/2048/4096
165  unsigned int shadowmapSize;
166 
167  bool wasMovedInLastDrawCall;
168  Vec3d lastDrawnPosition;
169 
170  StelCore* core;
171  LandscapeMgr* landscapeMgr;
172  StelProjectorP altAzProjector;
173 
174  // state required during drawing
175  GlobalShaderParameters renderShaderParameters;
176  bool backfaceCullState;
177  bool blendEnabled;
178  const S3DScene::Material* lastMaterial;
179  QOpenGLShaderProgram* curShader;
180  QSet<QOpenGLShaderProgram*> initializedShaders;
181  QVector<const StelOBJ::MaterialGroup*> transparentGroups;
182 
183  // debug info
184  int drawnTriangles,drawnModels;
185  int materialSwitches, shaderSwitches;
186 
188  bool requiresCubemap; //true if cubemapping is required (if projection is anything else than Perspective)
189  bool cubemappingUsedLastFrame; //true if cubemapping was used for the last frame. Used to determine if a projection switch occured.
190  bool lazyDrawing; //if lazy-drawing mode is enabled
191  bool updateOnlyDominantOnMoving; //if movement updates only dominant face directly
192  bool updateSecondDominantOnMoving; //if movement also updates the second-most dominant face
193  bool needsMovementEndUpdate;
194  bool needsCubemapUpdate; //if the draw-call has to recreate the cubemap completely
195  bool needsMovementUpdate; //if the draw-call has to recreate either the whole cubemap or the dominant face
196  double lazyInterval; //the lazy-drawing time interval
197  double lastCubemapUpdate; //when the last lazy draw happened (JDay)
198  qint64 lastCubemapUpdateRealTime; //when the last lazy draw happened (real system time, QDateTime::currentMSecsSinceEpoch)
199  qint64 lastMovementEndRealTime; //the timepoint when the last movement was stopped
200  GLuint cubeMapCubeTex; //GL_TEXTURE_CUBE_MAP, used in CUBEMAP or CUBEMAP_GSACCEL modes
201  GLuint cubeMapCubeDepth; //this is a depth-cubemap, only used in CUBEMAP_GSACCEL mode
202  GLuint cubeMapTex[6]; //GL_TEXTURE_2D, for "legacy" TEXTURES mode
203  GLuint cubeRB; //renderbuffer for depth of a single face in TEXTURES and CUBEMAP modes (attached to multiple FBOs)
204  int dominantFace,secondDominantFace;
205 
206  //because of use that deviates very much from QOpenGLFramebufferObject typical usage, we manage the FBOs ourselves
207  GLuint cubeFBO; //used in CUBEMAP_GSACCEL mode - only a single FBO exists, with a cubemap for color and one for depth
208  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)
209 
210  bool cubeMappingCreated; //true if any cubemapping objects have been initialized and need to be cleaned up eventually
211 
212  //cube geometry
213  QVector<Vec3f> cubeVertices, transformedCubeVertices;
214  QVector<Vec2f> cubeTexcoords;
215  QOpenGLBuffer cubeVertexBuffer;
216  QOpenGLBuffer transformedCubeVertexBuffer;
217  QOpenGLBuffer cubeIndexBuffer;
218  int cubeIndexCount;
219 
220  //cube rendering matrices
221  QMatrix4x4 cubeRotation[6]; //rotational matrices for cube faces. The cam position is added to this in each frame.
222  QMatrix4x4 cubeMVP[6]; //cube face MVP matrices
223 
225  //final model view matrix for shader upload
226  QMatrix4x4 modelViewMatrix;
227  //currently valid projection matrix for shader upload
228  QMatrix4x4 projectionMatrix;
229 
230  // a struct which encapsulates lighting info
231  struct LightParameters
232  {
233  //this is used for shadow calculation
234  enum ShadowCaster { SC_None, SC_Sun, SC_Moon, SC_Venus } shadowCaster;
235  QMatrix4x4 shadowModelView;
236 
237  Vec3f lightDirectionV3f;
238  //same as lightDirectionV3f, but as QVector3D
239  QVector3D lightDirectionWorld;
240  QVector3D ambient;
241  QVector3D directional;
242  QVector3D specular;
243  QVector3D emissive;
244 
245  QVector3D torchDiffuse;
246  float torchAttenuation;
247 
248  //these are just used for debugging
249  enum DirectionalSource { DS_Sun_Horiz, DS_Sun, DS_Moon, DS_Venus, DS_Venus_Ambient } directionalSource;
250  float sunAmbient;
251  float moonAmbient;
252  float backgroundAmbient;
253  float landscapeOpacity;
254  } lightInfo;
255 
256  GlobalShaderParameters shaderParameters;
257 
258  //Shadow Map FBO handles
259  QVector<GLuint> shadowFBOs;
260  //Holds the shadow textures
261  QVector<GLuint> shadowMapsArray;
262  //Holds the shadow transformation matrix per split (Crop/Projection/View)
263  QVector<QMatrix4x4> shadowCPM;
264  //Holds the xy-scaling of the orthographic light cam + pos of near/far planes in view coords
265  //Needed for consistent shadow filter sizes and PCSS effect
266  QVector<QVector4D> shadowFrustumSize;
267  // Frustum of the view camera, constrainted to the shadowFarZ instead of the camFarZ
268  Frustum camFrustShadow;
269  //near/far planes for the orthographic light that fits the whole scene
270  float lightOrthoNear;
271  float lightOrthoFar;
272  //Array holding the split frustums
273  QVector<Frustum> frustumArray;
274  //Vector holding the convex split bodies for focused shadow mapping
275  QVector<Polyhedron> focusBodies;
276 
277  float parallaxScale;
278 
279  QFont debugTextFont;
280 
281  // --- initialization
283  void determineFeatureSupport();
285  bool initCubemapping();
287  void deleteCubemapping();
288 
290  bool initShadowmapping();
292  void deleteShadowmapping();
293 
294  void calcCubeMVP(const Vec3d translation);
295 
296  // --- drawing methods ---
298  void drawDirect();
300  void drawWithCubeMap();
302  bool renderShadowMaps();
304  void renderShadowMapsForFace(int face);
306  void generateCubeMap();
308  void renderIntoCubemapGeometryShader();
310  void renderIntoCubemapSixPasses();
312  void drawFromCubeMap();
316  bool drawArrays(bool shading=true, bool blendAlphaAdditive=false);
318  bool drawMaterialGroup(const StelOBJ::MaterialGroup& matGroup, bool shading, bool blendAlphaAdditive);
319 
321  void drawCoordinatesText();
323  void drawDebug();
324 
325  // --- shading related stuff ---
327  void calculateShadowCaster();
329  void calculateLighting();
331  void setupPassUniforms(QOpenGLShaderProgram *shader);
333  void setupFrameUniforms(QOpenGLShaderProgram *shader);
335  void setupMaterialUniforms(QOpenGLShaderProgram *shader, const S3DScene::Material& mat);
336 
338  void adjustShadowFrustum(const Vec3d &viewPos, const Vec3d &viewDir, const Vec3d &viewUp, const float fov, const float aspect);
339  //Computes the frustum splits
340  void computeFrustumSplits(const Vec3d& viewPos, const Vec3d& viewDir, const Vec3d& viewUp);
341  //Computes the focus body for given frustum
342  void computePolyhedron(Polyhedron& body, const Frustum& frustum, const Vec3f &shadowDir);
343  //Computes the crop matrix to focus the light
344  void computeCropMatrix(QMatrix4x4& cropMatrix, QVector4D &orthoScale, Polyhedron &focusBody, const QMatrix4x4 &lightProj, const QMatrix4x4 &lightMVP);
345  //Computes the light projection values
346  void computeOrthoProjVals(const Vec3f shadowDir, float &orthoExtent, float &orthoNear, float &orthoFar);
347 
348  void rendererMessage(const QString& msg) const;
349 };
350 
351 #endif //_S3DRENDERER_HPP_
void setCubemapSize(uint size)
Note: This may not set the size to the desired one because of hardware limits, call getCubemapSize to...
Uses 6 textures, one for each side of the cube. Seems to be the best for old Intel drivers...
Definition: S3DEnum.hpp:38
ShaderMgr & getShaderManager()
Returns the shader manager this instance uses.
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
void setShadowmapSize(uint size)
Note: This may not set the size to the desired one because of hardware limits, call getShadowmapSize ...
void setCubemappingMode(S3DEnum::CubemappingMode mode)
Changes cubemapping mode and forces re-initialization on next draw call.
Definition: S3DRenderer.hpp:95
A simple shader cache class that gives us the correct shader depending on desired configuration...
Scenery3d renderer class.
Definition: S3DRenderer.hpp:48
void invalidateCubemap()
Does a cubemap redraw at the next possible opportunity when lazy-drawing is enabled.
Definition: S3DRenderer.hpp:90
ShadowFilterQuality
Contains different shadow filter settings.
Definition: S3DEnum.hpp:46
Extension of StelOBJ::Material which provides Scenery3d specific stuff.
Definition: S3DScene.hpp:38
CubemappingMode
Determines the method used for cubemap creation.
Definition: S3DEnum.hpp:35
Represents a bunch of faces following after each other that use the same material.
Definition: StelOBJ.hpp:142