Stellarium 0.14.3
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 "OBJ.hpp"
24 #include "StelOpenGL.hpp"
25 #include "S3DEnum.hpp"
26 
27 #include <QMap>
28 
29 class QOpenGLShaderProgram;
30 
33 {
34  bool openglES; //true if we work with an OGL ES2 context, may have to adapt shaders
35  bool shadowTransform;
36  bool pixelLighting;
37  bool bump;
38  bool shadows;
39  S3DEnum::ShadowFilterQuality shadowFilterQuality;
40  bool pcss;
41  bool geometryShader;
42  bool torchLight;
43  //for now, only 1 or 4 really supported
44  int frustumSplits;
45 };
46 
49 class ShaderMgr
50 {
51 public:
52  ShaderMgr();
53  ~ShaderMgr();
54 
56  enum ATTLOC
57  {
68  };
69 
71  enum UNIFORM
72  {
83  UNIFORM_MAT_SHADOW1,
84  UNIFORM_MAT_SHADOW2,
85  UNIFORM_MAT_SHADOW3,
88 
99  UNIFORM_TEX_SHADOW1,
100  UNIFORM_TEX_SHADOW2,
101  UNIFORM_TEX_SHADOW3,
102 
107 
118 
123 
132  };
133 
135  inline QOpenGLShaderProgram* getShader(const GlobalShaderParameters &globals, const OBJ::Material *mat = NULL);
136 
138  inline QOpenGLShaderProgram* getDebugShader();
139 
141  inline QOpenGLShaderProgram* getCubeShader();
142 
144  inline QOpenGLShaderProgram* getTextureShader();
145 
148  inline GLint uniformLocation(const QOpenGLShaderProgram* shad,UNIFORM uni);
149 
151  void clearCache();
152 
153 private:
154  typedef QMap<QString,UNIFORM> t_UniformStrings;
155  static t_UniformStrings uniformStrings;
156 
157  //A Bitflag enum which contains features that shaders can implement, and which this manager can dynamically select
158  enum FeatureFlags
159  {
160  INVALID = 0,
161  //Transform-only shader (all flags off) (use for depth-only render), should be mutually exclusive with SHADING
162  TRANSFORM = (1<<0),
163  //The shader has some sort of light-dependent color output, should be mutually exclusive with TRANSFORM
164  SHADING = (1<<1),
165  //Per-pixel lighting
166  PIXEL_LIGHTING = (1<<2),
167  //Shader applies shadows from shadow maps
168  SHADOWS = (1<<3),
169  //Shader applies bump/normal maps
170  BUMP = (1<<4),
171  //Shader applies height maps (in addition to bump map)
172  HEIGHT = (1<<5),
173  //Shader applies alpha testing (w. fragment discard)
174  ALPHATEST = (1<<6),
175  //Shader filters shadows
176  SHADOW_FILTER = (1<<7),
177  //shader filters shadows (higher quality)
178  SHADOW_FILTER_HQ = (1<<8),
179  //uses specular material
180  MAT_SPECULAR = (1<<9),
181  //has diffuse texture. On its own (i.e. esp. without SHADING) it defines the basic texture shader.
182  MAT_DIFFUSETEX = (1<<10),
183  //has emissive texture
184  MAT_EMISSIVETEX = (1<<11),
185  //needs geometry shader cubemapping
186  GEOMETRY_SHADER = (1<<12),
187  //shader performs cubemap lookup
188  CUBEMAP = (1<<13),
189  //shader performs blending, otherwise it is expected to output alpha 1.0
190  //it is required for correct blending for our cubemapping
191  BLENDING = (1<<14),
192  //shader uses an additional point light positioned at the camera that performs additional diffuse illumination
193  TORCH = (1<<15),
194  //debug shader for AABBs/Frustums
195  DEBUG = (1<<16),
196  //PCSS shadow filtering
197  PCSS = (1<<17),
198  //only a single shadow frustum is used
199  SINGLE_SHADOW_FRUSTUM = (1<<18),
200  //set if opengl es2
201  OGL_ES2 = (1<<19),
202  };
203 
204  typedef QMap<QString,FeatureFlags> t_FeatureFlagStrings;
205  static t_FeatureFlagStrings featureFlagsStrings;
206 
207  QString getVShaderName(uint flags);
208  QString getGShaderName(uint flags);
209  QString getFShaderName(uint flags);
210  QOpenGLShaderProgram* findOrLoadShader(uint flags);
212  bool preprocessShader(const QString& fileName, const uint flags, QByteArray& processedSource);
213  //compiles and links the shader with this specified source code
214  bool loadShader(QOpenGLShaderProgram& program, const QByteArray& vShader, const QByteArray& gShader, const QByteArray& fShader);
215  void buildUniformCache(QOpenGLShaderProgram& program);
216 
217  typedef QHash<uint,QOpenGLShaderProgram*> t_ShaderCache;
218  t_ShaderCache m_shaderCache;
219 
220  typedef QHash<QByteArray,QOpenGLShaderProgram*> t_ShaderContentCache;
221  t_ShaderContentCache m_shaderContentCache;
222 
223  typedef QHash<UNIFORM,GLuint> t_UniformCacheEntry;
224  typedef QHash<const QOpenGLShaderProgram*, t_UniformCacheEntry> t_UniformCache;
225  t_UniformCache m_uniformCache;
226 };
227 
228 QOpenGLShaderProgram* ShaderMgr::getShader(const GlobalShaderParameters& globals,const OBJ::Material* mat)
229 {
230  //Build bitflags from bools. Some stuff requires pixelLighting to be enabled, so check it too.
231 
232  uint flags = INVALID;
233  if(globals.openglES) flags|=OGL_ES2;
234  if(!globals.shadowTransform)
235  {
236  flags |= SHADING;
237  if(globals.pixelLighting) flags|= PIXEL_LIGHTING;
238  if(globals.pixelLighting && globals.shadows) flags|= SHADOWS;
239  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_HARDWARE) flags|= SHADOW_FILTER;
240  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_LOW_HARDWARE) flags|= SHADOW_FILTER_HQ;
241  if(globals.pixelLighting && globals.shadows && (globals.shadowFilterQuality == S3DEnum::SFQ_LOW || globals.shadowFilterQuality == S3DEnum::SFQ_HIGH) && globals.pcss) flags|= PCSS;
242  if(globals.geometryShader) flags|= GEOMETRY_SHADER;
243  if(globals.torchLight) flags|= TORCH;
244  if(globals.frustumSplits == 1) flags|= SINGLE_SHADOW_FRUSTUM;
245  }
246  else
247  {
248  flags |= TRANSFORM;
249  }
250 
251  if(mat)
252  {
253  if(mat->alphatest && mat->texture && mat->texture->hasAlphaChannel()) //alpha test needs diffuse texture, otherwise it would not make sense
254  flags|= ALPHATEST;
255  if(mat->hasSpecularity)
256  flags|= MAT_SPECULAR;
257  if(mat->hasTransparency)
258  flags|= BLENDING;
259  if(mat->texture)
260  flags|= MAT_DIFFUSETEX;
261  if(mat->emissive_texture)
262  flags|= MAT_EMISSIVETEX;
263  if(mat->bump_texture && globals.bump && globals.pixelLighting)
264  flags|= BUMP;
265  if(mat->height_texture && globals.bump && globals.pixelLighting)
266  flags|= HEIGHT;
267  }
268 
269  return findOrLoadShader(flags);
270 }
271 
272 QOpenGLShaderProgram* ShaderMgr::getDebugShader()
273 {
274  return findOrLoadShader(DEBUG);
275 }
276 
277 QOpenGLShaderProgram* ShaderMgr::getCubeShader()
278 {
279  return findOrLoadShader(CUBEMAP);
280 }
281 
282 QOpenGLShaderProgram* ShaderMgr::getTextureShader()
283 {
284  return findOrLoadShader(MAT_DIFFUSETEX);
285 }
286 
287 GLint ShaderMgr::uniformLocation(const QOpenGLShaderProgram *shad, UNIFORM uni)
288 {
289  t_UniformCache::iterator it = m_uniformCache.find(shad);
290  if(it!=m_uniformCache.end())
291  {
292  return it.value().value(uni,-1);
293  }
294  return -1;
295 }
296 
297 #endif
Material global transparency.
Uses a 16-tap Poisson disk.
Definition: S3DEnum.hpp:53
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.
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.
bool hasSpecularity
Quick check if this material has specularity.
Definition: OBJ.hpp:121
Squared frustum splits (vec4)
This is the OpenGL attribute location where vertex normals are mapped to.
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)
bool alphatest
If to perform binary alpha testing. Default off.
Definition: OBJ.hpp:117
Defines the Height texture slot.
bool hasTransparency
Quick check if this material has "real" transparency (i.e. needs blending)
Definition: OBJ.hpp:123
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...
Defines the emissive texture slot.
ShadowFilterQuality
Contains different shadow filter settings.
Definition: S3DEnum.hpp:46
Uses a 64-tap Poisson disk.
Definition: S3DEnum.hpp:57
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...
This is the OpenGL attribute location where vertex texture coordinates are mapped to...
QOpenGLShaderProgram * getShader(const GlobalShaderParameters &globals, const OBJ::Material *mat=NULL)
Returns a shader that supports the specified operations. Must be called within a GL context...
This is the OpenGL attribute location where vertex bitangents are mapped to.
The shadow matrices (4x 4x4 Matrices)
This is the OpenGL attribute location where vertex tangents are mapped to.
This is the OpenGL attribute location where vertex positions are mapped to.
Scaling of each frustum's light ortho projection (4xvec2)
Encapsulates all information that the describes the surface appearance of a StelModel.
Definition: OBJ.hpp:71
Material emissive color * light emissive.
void clearCache()
Clears the shaders that have been created by this manager. Must be called within a GL context...
ATTLOC
Enum for OpenGL shader attribute locations.
Light directional * Material diffuse.