Stellarium  0.16.1
ShaderManager.hpp
1 /*
2  * Stellarium Scenery3d Plug-in
3  *
4  * Copyright (C) 2014 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 _SHADERMANAGER_HPP_
22 #define _SHADERMANAGER_HPP_
23 #include "S3DScene.hpp"
24 #include "StelTexture.hpp"
25 #include "S3DEnum.hpp"
26 
27 #include <QMap>
28 
29 class QOpenGLShaderProgram;
30 
31 Q_DECLARE_LOGGING_CATEGORY(shaderMgr)
32 
35 {
36  bool openglES; //true if we work with an OGL ES2 context, may have to adapt shaders
37  bool shadowTransform;
38  bool pixelLighting;
39  bool bump;
40  bool shadows;
41  S3DEnum::ShadowFilterQuality shadowFilterQuality;
42  bool pcss;
43  bool geometryShader;
44  bool torchLight;
45  //for now, only 1 or 4 really supported
46  int frustumSplits;
47  bool hwShadowSamplers;
48 };
49 
52 class ShaderMgr
53 {
54 public:
55  ShaderMgr();
56  ~ShaderMgr();
57 
59  enum UNIFORM
60  {
71  UNIFORM_MAT_SHADOW1,
72  UNIFORM_MAT_SHADOW2,
73  UNIFORM_MAT_SHADOW3,
76 
87  UNIFORM_TEX_SHADOW1,
88  UNIFORM_TEX_SHADOW2,
89  UNIFORM_TEX_SHADOW3,
90 
95 
106 
111 
120  };
121 
123  inline QOpenGLShaderProgram* getShader(const GlobalShaderParameters &globals, const S3DScene::Material *mat = Q_NULLPTR);
124 
126  inline QOpenGLShaderProgram* getDebugShader();
127 
129  inline QOpenGLShaderProgram* getCubeShader();
130 
132  inline QOpenGLShaderProgram* getTextureShader();
133 
136  inline GLint uniformLocation(const QOpenGLShaderProgram* shad,UNIFORM uni);
137 
139  void clearCache();
140 
141 private:
142  typedef QMap<QString,UNIFORM> t_UniformStrings;
143  static t_UniformStrings uniformStrings;
144 
145  //A Bitflag enum which contains features that shaders can implement, and which this manager can dynamically select
146  enum FeatureFlags
147  {
148  INVALID = 0,
149  //Transform-only shader (all flags off) (use for depth-only render), should be mutually exclusive with SHADING
150  TRANSFORM = (1<<0),
151  //The shader has some sort of light-dependent color output, should be mutually exclusive with TRANSFORM
152  SHADING = (1<<1),
153  //Per-pixel lighting
154  PIXEL_LIGHTING = (1<<2),
155  //Shader applies shadows from shadow maps
156  SHADOWS = (1<<3),
157  //Shader applies bump/normal maps
158  BUMP = (1<<4),
159  //Shader applies height maps (in addition to bump map)
160  HEIGHT = (1<<5),
161  //Shader applies alpha testing (w. fragment discard)
162  ALPHATEST = (1<<6),
163  //Shader filters shadows
164  SHADOW_FILTER = (1<<7),
165  //shader filters shadows (higher quality)
166  SHADOW_FILTER_HQ = (1<<8),
167  //uses specular material
168  MAT_SPECULAR = (1<<9),
169  //has diffuse texture. On its own (i.e. esp. without SHADING) it defines the basic texture shader.
170  MAT_DIFFUSETEX = (1<<10),
171  //has emissive texture
172  MAT_EMISSIVETEX = (1<<11),
173  //needs geometry shader cubemapping
174  GEOMETRY_SHADER = (1<<12),
175  //shader performs cubemap lookup
176  CUBEMAP = (1<<13),
177  //shader performs blending, otherwise it is expected to output alpha 1.0
178  //it is required for correct blending for our cubemapping
179  BLENDING = (1<<14),
180  //shader uses an additional point light positioned at the camera that performs additional diffuse illumination
181  TORCH = (1<<15),
182  //debug shader for AABBs/Frustums
183  DEBUG = (1<<16),
184  //PCSS shadow filtering
185  PCSS = (1<<17),
186  //only a single shadow frustum is used
187  SINGLE_SHADOW_FRUSTUM = (1<<18),
188  //set if opengl es2
189  OGL_ES2 = (1<<19),
190  //true if shadow samplers (shadow2d) should be used for shadow maps instead of normal samplers (texture2d)
191  HW_SHADOW_SAMPLERS = (1<<20)
192  };
193 
194  typedef QMap<QString,FeatureFlags> t_FeatureFlagStrings;
195  static t_FeatureFlagStrings featureFlagsStrings;
196 
197  QString getVShaderName(uint flags);
198  QString getGShaderName(uint flags);
199  QString getFShaderName(uint flags);
200  QOpenGLShaderProgram* findOrLoadShader(uint flags);
202  bool preprocessShader(const QString& fileName, const uint flags, QByteArray& processedSource);
203  //compiles and links the shader with this specified source code
204  bool loadShader(QOpenGLShaderProgram& program, const QByteArray& vShader, const QByteArray& gShader, const QByteArray& fShader);
205  void buildUniformCache(QOpenGLShaderProgram& program);
206 
207  typedef QHash<uint,QOpenGLShaderProgram*> t_ShaderCache;
208  t_ShaderCache m_shaderCache;
209 
210  typedef QHash<QByteArray,QOpenGLShaderProgram*> t_ShaderContentCache;
211  t_ShaderContentCache m_shaderContentCache;
212 
213  typedef QHash<UNIFORM,GLuint> t_UniformCacheEntry;
214  typedef QHash<const QOpenGLShaderProgram*, t_UniformCacheEntry> t_UniformCache;
215  t_UniformCache m_uniformCache;
216 };
217 
218 QOpenGLShaderProgram* ShaderMgr::getShader(const GlobalShaderParameters& globals,const S3DScene::Material* mat)
219 {
220  //Build bitflags from bools. Some stuff requires pixelLighting to be enabled, so check it too.
221 
222  uint flags = INVALID;
223  if(globals.openglES) flags|=OGL_ES2;
224  if(!globals.shadowTransform)
225  {
226  flags |= SHADING;
227  if(globals.pixelLighting) flags|= PIXEL_LIGHTING;
228  if(globals.pixelLighting && globals.shadows) flags|= SHADOWS;
229  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_HARDWARE) flags|= SHADOW_FILTER;
230  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_LOW_HARDWARE) flags|= SHADOW_FILTER_HQ;
231  if(globals.pixelLighting && globals.shadows && !globals.hwShadowSamplers && (globals.shadowFilterQuality == S3DEnum::SFQ_LOW || globals.shadowFilterQuality == S3DEnum::SFQ_HIGH) && globals.pcss) flags|= PCSS;
232  if(globals.hwShadowSamplers) flags|=HW_SHADOW_SAMPLERS;
233  if(globals.geometryShader) flags|= GEOMETRY_SHADER;
234  if(globals.torchLight) flags|= TORCH;
235  if(globals.frustumSplits == 1) flags|= SINGLE_SHADOW_FRUSTUM;
236  }
237  else
238  {
239  flags |= TRANSFORM;
240  }
241 
242  if(mat)
243  {
244  if(mat->bAlphatest && mat->tex_Kd && mat->tex_Kd->hasAlphaChannel()) //alpha test needs diffuse texture, otherwise it would not make sense
245  flags|= ALPHATEST;
246  if(mat->traits.hasSpecularity)
247  flags|= MAT_SPECULAR;
248  if(mat->traits.hasTransparency || mat->traits.isFading)
249  flags|= BLENDING;
250  if(mat->traits.hasDiffuseTexture)
251  flags|= MAT_DIFFUSETEX;
252  if(mat->traits.hasEmissiveTexture)
253  flags|= MAT_EMISSIVETEX;
254  if(mat->traits.hasBumpTexture && globals.bump && globals.pixelLighting)
255  flags|= BUMP;
256  if(mat->traits.hasHeightTexture && globals.bump && globals.pixelLighting)
257  flags|= HEIGHT;
258  }
259 
260  return findOrLoadShader(flags);
261 }
262 
263 QOpenGLShaderProgram* ShaderMgr::getDebugShader()
264 {
265  return findOrLoadShader(DEBUG);
266 }
267 
268 QOpenGLShaderProgram* ShaderMgr::getCubeShader()
269 {
270  return findOrLoadShader(CUBEMAP);
271 }
272 
273 QOpenGLShaderProgram* ShaderMgr::getTextureShader()
274 {
275  return findOrLoadShader(MAT_DIFFUSETEX);
276 }
277 
278 GLint ShaderMgr::uniformLocation(const QOpenGLShaderProgram *shad, UNIFORM uni)
279 {
280  t_UniformCache::iterator it = m_uniformCache.find(shad);
281  if(it!=m_uniformCache.end())
282  {
283  return it.value().value(uni,-1);
284  }
285  return -1;
286 }
287 
288 #endif
Material global transparency.
Uses a 16-tap Poisson disk.
Definition: S3DEnum.hpp:53
bool hasSpecularity
True when tex_height is a valid texture.
Definition: S3DScene.hpp:76
Defines the ModelView matrix.
Defines the combined ModelViewProjection matrix, used if shader needs no separation of the 2 for a bi...
Material specular shininess (exponent)
Defines the Projection matrix.
Torch color * mat diffuse.
Torchlight attenuation factor (1 float, like in the second model at http://framebunker.com/blog/lighting-2-attenuation/)
Light specular * Material specular color.
bool hasEmissiveTexture
True when tex_Kd is a valid texture.
Definition: S3DScene.hpp:73
A structure for global shader parameters.
Defines the 3x3 Normal matrix (transpose of the inverse MV matrix)
Defines the Bump texture slot.
QOpenGLShaderProgram * getDebugShader()
Returns the Frustum/Boundingbox Debug shader.
Squared frustum splits (vec4)
bool hasTransparency
True when both Ks and Ns are non-zero.
Definition: S3DScene.hpp:77
UNIFORM
Enum for OpenGL shader uniform locations (faster than accessing by string each time) ...
Defines the Diffuse texture slot.
The first cube MVP (array mat4, total 6)
QOpenGLShaderProgram * getTextureShader()
Returns the basic texturing shader.
(Light ambient + const factor) * Material ambient or diffuse, depending on Illum model ...
Light direction vector (view space)
QOpenGLShaderProgram * getShader(const GlobalShaderParameters &globals, const S3DScene::Material *mat=Q_NULLPTR)
Returns a shader that supports the specified operations. Must be called within a GL context...
Defines the Height texture slot.
Uses a 16-tap Poisson disk + hardware filtering.
Definition: S3DEnum.hpp:55
QOpenGLShaderProgram * getCubeShader()
Returns the cubemapping shader.
A simple shader cache class that gives us the correct shader depending on desired configuration...
bool hasHeightTexture
True when tex_bump is a valid texture.
Definition: S3DScene.hpp:75
Defines the emissive texture slot.
ShadowFilterQuality
Contains different shadow filter settings.
Definition: S3DEnum.hpp:46
Extension of StelOBJ::Material which provides Scenery3d specific stuff.
Definition: S3DScene.hpp:38
Uses a 64-tap Poisson disk.
Definition: S3DEnum.hpp:57
bool isFading
True when the material is (currently) completely invisible.
Definition: S3DScene.hpp:80
Enables OpenGL hardware shadow filtering.
Definition: S3DEnum.hpp:51
GLint uniformLocation(const QOpenGLShaderProgram *shad, UNIFORM uni)
Returns the location of this uniform for this shader, or -1 if this uniform does not exist...
The shadow matrices (4x 4x4 Matrices)
Scaling of each frustum&#39;s light ortho projection (4xvec2)
Material emissive color * light emissive.
void clearCache()
Clears the shaders that have been created by this manager. Must be called within a GL context...
bool hasBumpTexture
True when tex_Ke is a valid texture.
Definition: S3DScene.hpp:74
Light directional * Material diffuse.