Stellarium 0.15.2
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  bool hwShadowSamplers;
46 };
47 
50 class ShaderMgr
51 {
52 public:
53  ShaderMgr();
54  ~ShaderMgr();
55 
57  enum ATTLOC
58  {
68  ATTLOC_BITANGENT
69  };
70 
72  enum UNIFORM
73  {
84  UNIFORM_MAT_SHADOW1,
85  UNIFORM_MAT_SHADOW2,
86  UNIFORM_MAT_SHADOW3,
89 
100  UNIFORM_TEX_SHADOW1,
101  UNIFORM_TEX_SHADOW2,
102  UNIFORM_TEX_SHADOW3,
103 
108 
119 
124 
133  };
134 
136  inline QOpenGLShaderProgram* getShader(const GlobalShaderParameters &globals, const OBJ::Material *mat = NULL);
137 
139  inline QOpenGLShaderProgram* getDebugShader();
140 
142  inline QOpenGLShaderProgram* getCubeShader();
143 
145  inline QOpenGLShaderProgram* getTextureShader();
146 
149  inline GLint uniformLocation(const QOpenGLShaderProgram* shad,UNIFORM uni);
150 
152  void clearCache();
153 
154 private:
155  typedef QMap<QString,UNIFORM> t_UniformStrings;
156  static t_UniformStrings uniformStrings;
157 
158  //A Bitflag enum which contains features that shaders can implement, and which this manager can dynamically select
159  enum FeatureFlags
160  {
161  INVALID = 0,
162  //Transform-only shader (all flags off) (use for depth-only render), should be mutually exclusive with SHADING
163  TRANSFORM = (1<<0),
164  //The shader has some sort of light-dependent color output, should be mutually exclusive with TRANSFORM
165  SHADING = (1<<1),
166  //Per-pixel lighting
167  PIXEL_LIGHTING = (1<<2),
168  //Shader applies shadows from shadow maps
169  SHADOWS = (1<<3),
170  //Shader applies bump/normal maps
171  BUMP = (1<<4),
172  //Shader applies height maps (in addition to bump map)
173  HEIGHT = (1<<5),
174  //Shader applies alpha testing (w. fragment discard)
175  ALPHATEST = (1<<6),
176  //Shader filters shadows
177  SHADOW_FILTER = (1<<7),
178  //shader filters shadows (higher quality)
179  SHADOW_FILTER_HQ = (1<<8),
180  //uses specular material
181  MAT_SPECULAR = (1<<9),
182  //has diffuse texture. On its own (i.e. esp. without SHADING) it defines the basic texture shader.
183  MAT_DIFFUSETEX = (1<<10),
184  //has emissive texture
185  MAT_EMISSIVETEX = (1<<11),
186  //needs geometry shader cubemapping
187  GEOMETRY_SHADER = (1<<12),
188  //shader performs cubemap lookup
189  CUBEMAP = (1<<13),
190  //shader performs blending, otherwise it is expected to output alpha 1.0
191  //it is required for correct blending for our cubemapping
192  BLENDING = (1<<14),
193  //shader uses an additional point light positioned at the camera that performs additional diffuse illumination
194  TORCH = (1<<15),
195  //debug shader for AABBs/Frustums
196  DEBUG = (1<<16),
197  //PCSS shadow filtering
198  PCSS = (1<<17),
199  //only a single shadow frustum is used
200  SINGLE_SHADOW_FRUSTUM = (1<<18),
201  //set if opengl es2
202  OGL_ES2 = (1<<19),
203  //true if shadow samplers (shadow2d) should be used for shadow maps instead of normal samplers (texture2d)
204  HW_SHADOW_SAMPLERS = (1<<20)
205  };
206 
207  typedef QMap<QString,FeatureFlags> t_FeatureFlagStrings;
208  static t_FeatureFlagStrings featureFlagsStrings;
209 
210  QString getVShaderName(uint flags);
211  QString getGShaderName(uint flags);
212  QString getFShaderName(uint flags);
213  QOpenGLShaderProgram* findOrLoadShader(uint flags);
215  bool preprocessShader(const QString& fileName, const uint flags, QByteArray& processedSource);
216  //compiles and links the shader with this specified source code
217  bool loadShader(QOpenGLShaderProgram& program, const QByteArray& vShader, const QByteArray& gShader, const QByteArray& fShader);
218  void buildUniformCache(QOpenGLShaderProgram& program);
219 
220  typedef QHash<uint,QOpenGLShaderProgram*> t_ShaderCache;
221  t_ShaderCache m_shaderCache;
222 
223  typedef QHash<QByteArray,QOpenGLShaderProgram*> t_ShaderContentCache;
224  t_ShaderContentCache m_shaderContentCache;
225 
226  typedef QHash<UNIFORM,GLuint> t_UniformCacheEntry;
227  typedef QHash<const QOpenGLShaderProgram*, t_UniformCacheEntry> t_UniformCache;
228  t_UniformCache m_uniformCache;
229 };
230 
231 QOpenGLShaderProgram* ShaderMgr::getShader(const GlobalShaderParameters& globals,const OBJ::Material* mat)
232 {
233  //Build bitflags from bools. Some stuff requires pixelLighting to be enabled, so check it too.
234 
235  uint flags = INVALID;
236  if(globals.openglES) flags|=OGL_ES2;
237  if(!globals.shadowTransform)
238  {
239  flags |= SHADING;
240  if(globals.pixelLighting) flags|= PIXEL_LIGHTING;
241  if(globals.pixelLighting && globals.shadows) flags|= SHADOWS;
242  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_HARDWARE) flags|= SHADOW_FILTER;
243  if(globals.pixelLighting && globals.shadows && globals.shadowFilterQuality>S3DEnum::SFQ_LOW_HARDWARE) flags|= SHADOW_FILTER_HQ;
244  if(globals.pixelLighting && globals.shadows && !globals.hwShadowSamplers && (globals.shadowFilterQuality == S3DEnum::SFQ_LOW || globals.shadowFilterQuality == S3DEnum::SFQ_HIGH) && globals.pcss) flags|= PCSS;
245  if(globals.hwShadowSamplers) flags|=HW_SHADOW_SAMPLERS;
246  if(globals.geometryShader) flags|= GEOMETRY_SHADER;
247  if(globals.torchLight) flags|= TORCH;
248  if(globals.frustumSplits == 1) flags|= SINGLE_SHADOW_FRUSTUM;
249  }
250  else
251  {
252  flags |= TRANSFORM;
253  }
254 
255  if(mat)
256  {
257  if(mat->alphatest && mat->texture && mat->texture->hasAlphaChannel()) //alpha test needs diffuse texture, otherwise it would not make sense
258  flags|= ALPHATEST;
259  if(mat->hasSpecularity)
260  flags|= MAT_SPECULAR;
261  if(mat->hasTransparency)
262  flags|= BLENDING;
263  if(mat->texture)
264  flags|= MAT_DIFFUSETEX;
265  if(mat->emissive_texture)
266  flags|= MAT_EMISSIVETEX;
267  if(mat->bump_texture && globals.bump && globals.pixelLighting)
268  flags|= BUMP;
269  if(mat->height_texture && globals.bump && globals.pixelLighting)
270  flags|= HEIGHT;
271  }
272 
273  return findOrLoadShader(flags);
274 }
275 
276 QOpenGLShaderProgram* ShaderMgr::getDebugShader()
277 {
278  return findOrLoadShader(DEBUG);
279 }
280 
281 QOpenGLShaderProgram* ShaderMgr::getCubeShader()
282 {
283  return findOrLoadShader(CUBEMAP);
284 }
285 
286 QOpenGLShaderProgram* ShaderMgr::getTextureShader()
287 {
288  return findOrLoadShader(MAT_DIFFUSETEX);
289 }
290 
291 GLint ShaderMgr::uniformLocation(const QOpenGLShaderProgram *shad, UNIFORM uni)
292 {
293  t_UniformCache::iterator it = m_uniformCache.find(shad);
294  if(it!=m_uniformCache.end())
295  {
296  return it.value().value(uni,-1);
297  }
298  return -1;
299 }
300 
301 #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...
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&#39;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.
ATTLOC
Enum for OpenGL shader attribute locations.
Light directional * Material diffuse.