ShaderGenerator.hh 22.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openflipper.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenFlipper.                                        *
 *                                                                           *
 *  OpenFlipper is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenFlipper is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenFlipper. If not,                                  *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                       *
 *   $Author$                                                      *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/

Christopher Tenter's avatar
Christopher Tenter committed
43
44
#pragma once

45
46
#include <QStringList>
#include <QString>
Christopher Tenter's avatar
Christopher Tenter committed
47
48
#include <string>
#include <list>
49
50
51
#include <map>

#include <ACG/GL/gl.hh>
52
53
#include <ACG/Config/ACGDefines.hh>

Christopher Tenter's avatar
Christopher Tenter committed
54

Christopher Tenter's avatar
Christopher Tenter committed
55
56
57
58
namespace ACG
{


Christopher Tenter's avatar
Christopher Tenter committed
59
60
61
// #define MAX_SHADER_INPUT_UNITS 32
// #define MAX_SHADER_CONSTANTS 0x200
// #define MAX_SHADER_GEN_DEFINES 0x100
62
#define SG_MAX_SHADER_LIGHTS 8
Christopher Tenter's avatar
Christopher Tenter committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

enum ShaderGenLightType
{
  SG_LIGHT_DIRECTIONAL = 0,
  SG_LIGHT_POINT,
  SG_LIGHT_SPOT,
  SG_LIGHT_FORCE_DWORD = 0xFFFFFFFF
};

enum ShaderGenShadeMode
{
  SG_SHADE_UNLIT = 0,
  SG_SHADE_FLAT,
  SG_SHADE_GOURAUD,
  SG_SHADE_PHONG,
  SG_SHADE_FORCE_DWORD = 0xFFFFFFFF
};

81
class ShaderGenDesc
Christopher Tenter's avatar
Christopher Tenter committed
82
{
83
84
85
86
87
88
89
90
91

public:
  ShaderGenDesc() :
    numLights(0),
    shadeMode(SG_SHADE_UNLIT),
    vertexColors(false),
    vertexTemplateFile(""),
    geometryTemplateFile(""),
    fragmentTemplateFile(""),
92
93
    normalizeTexColors(true),
    textureTypes_()
94
95
96
97
98
99
  {
    for ( unsigned int i = 0 ; i < SG_MAX_SHADER_LIGHTS ; ++i)
      lightTypes[i] = SG_LIGHT_DIRECTIONAL;

  }

100
  //In case, something crashes with the light types, try this hammer ;-)
101
102
103
104
105
//  const ShaderGenDesc& operator= (const ShaderGenDesc& _rhs) {
//
//    numLights                         = _rhs.numLights;
//
//    std::copy(_rhs.lightTypes,_rhs.lightTypes+SG_MAX_SHADER_LIGHTS,lightTypes);
106
//    textureTypes_ = _rhs.textureTypes_;
107
108
109
110
111
112
113
114
115
116
117
//
//    shadeMode                         = _rhs.shadeMode;
//    vertexColors                      = _rhs.vertexColors;
//    vertexTemplateFile                = _rhs.vertexTemplateFile;
//    geometryTemplateFile              = _rhs.geometryTemplateFile;
//    fragmentTemplateFile              = _rhs.fragmentTemplateFile;
//
//    return *this;
//  }


Christopher Tenter's avatar
Christopher Tenter committed
118
  int numLights;
119
  ShaderGenLightType lightTypes[SG_MAX_SHADER_LIGHTS];
Christopher Tenter's avatar
Christopher Tenter committed
120
121
122
123

  ShaderGenShadeMode shadeMode;

  bool vertexColors;
Christopher Tenter's avatar
Christopher Tenter committed
124
125

  // optionally specify shader template file names
126
127
128
  QString vertexTemplateFile;
  QString geometryTemplateFile;
  QString fragmentTemplateFile;
129
130
131

  /// convert ShaderGenDesc to string format for debugging
  QString toString() const;
132

133
134
135
136
137
138
139
140
141
142
143
144
  /// Defines if the textureVariable is normalized or not, if multiple textures are used
  bool normalizeTexColors;



  struct TextureType
  {
    GLenum type;
    bool shadow;
  };
private:
  /// holds the texture types (second) and the stage id (first). if empty, shader does not support textures
Jan Möbius's avatar
Jan Möbius committed
145
  std::map<size_t,TextureType> textureTypes_;
146
147

public:
148
  const std::map<size_t,TextureType>& textureTypes() const {return textureTypes_;}
149
150
151
152

  /** \brief adds a texture type to the shader and enables texturing.
   *
   */
Jan Möbius's avatar
Jan Möbius committed
153
  void addTextureType(GLenum _type, bool _shadow, size_t _stage)
154
155
156
157
158
159
160
161
162
163
164
165
  {
    TextureType t;
    t.type = _type;
    t.shadow = _shadow;
    textureTypes_[_stage] = t;
  }

  ///disables texture support and removes all texture types
  void clearTextures(){textureTypes_.clear();}

  bool textured()const {return !textureTypes_.empty();}

166
};
167
168


169
/** \page ShaderGenerator_page Shader Generator
170

171
\section ShaderGenerator_auto_shader_uniforms Automatically generated Shader Uniforms
172

173
174
175
176
177
178
179
\subsection Matrix
\code
  mat4 g_mWVP  - world-view-projection transform
  mat4 g_mWV   - world-view transform
  mat4 g_mWVIT - inverse transpose of world view matrix
  mat4 g_mP    - projection matrix
\endcode
180

181
182
183
184
185
186
187
188
\subsection Color
\code
  vec3 g_cDiffuse - diffuse color
  vec3 g_cAmbient - ambient color
  vec3 g_cEmissive - emissive color
  vec3 g_cSpecular - specular color
  vec4 g_vMaterial - vec4(shininess, alpha, unused, unused)
\endcode
189
190


191
\subsection Lighting
192

193
194
195
196
197
198
199
200
201
202
\code
  // light parameters denoted by zero-based index i
  vec3 g_cLightDiffuse_i   - diffuse color
  vec3 g_cLightAmbient_i   - ambient color
  vec3 g_cLightSpecular_i  - specular color
  vec3 g_vLightPos_i       - position in view space (for point and spot lights only)
  vec3 g_vLightAtten_i     - [constant, linear, quadratic] attenuation factors (for point and spot lights only)
  vec3 g_vLightDir_i       - light direction in view space (for spot and directional lights only)
  vec2 g_vLightAngleExp_i  - [cos(spotCutOffAngle), spot exponent] (for spot lights only)
\endcode
203

204
205
206
207
\subsection Texturing
\code
  sampler2D g_Texture0     - texture sampler (if textured is enabled in ShaderGenDesc)
\endcode
208
209
210



211
\section ShaderGenerator_auto_shader_inout Automatically generated shader input/output:
212

213
\subsection  ShaderGenerator_vertex_shader_io Vertex shader IO
214

215
216
\code
  in vec4 inPosition - vertex position in model space
217

218
219
220
  in vec3 inNormal   - vertex normal (only if ShaderGenDesc.shadeMode != unlit)
  in vec4 inColor    - vertex color (only if ShaderGenDesc.vertexColors == true)
  in vec2 inTexCoord - texture coordinate (only if ShaderGenDesc.textured == true)
221

222
223
224
225
226
  out vec4 outPosCS  - position in clip space
  out vec3 outNormal - normal in view space (only if ShaderGenDesc.shadeMode == phong)
  out vec4 outPosVS  - position in view space (only if ShaderGenDesc.shadeMode == phong)
  out vec4 outColor  - vertex color after lighting (only if ShaderGenDesc.shadeMode == flat or gouraud)
  out vec2 outTexCoord - texture coordinate (only if ShaderGenDesc.textured == true)
227

228
229
  // insert input/outputs added from modifiers here
\endcode
230

231
\subsection ShaderGenerator_fragment_shader_io Fragment shader IO
232
233

See vertex shader outputs for fragment inputs.
234
235
\code
  out vec4 outFragment - fragment color
236

237
238
  // insert input/outputs added from modifiers here
\endcode
239
240


241
\section ShaderGenerator_auto_shader_defines Automatically generated shader defines
242
243
244
These come in handy when you need to keep compatibility with custom shaders.

Depending on the shademode of ShaderGenDesc, exactly one of the following defines is active.
245
246
247
248
 - SG_GOURAUD
 - SG_FLAT
 - SG_UNLIT
 - SG_PHONG
249
250


251
252
Additional defines:
\code
253
SG_NORMALS      // defined if vertex normals are available
254
255
SG_TEXTURE      // defined if ShaderGenDesc.textured     == true
SG_VERTEX_COLOR // defined if ShaderGenDesc.vertexColors == true
256

257
\endcode
258

259
260
261
Lighting:
\code
 SG_NUM_LIGHTS   // number of lights
262

263
264
  //for each light i:
  SG_LIGHT_TYPE_i // Determine the type of light i; set to one of {SG_LIGHT_DIRECTIONAL, SG_LIGHT_POINT, SG_LIGHT_SPOT}
265

266
267
268
269
270
  // Example:
  #define SG_LIGHT_TYPE_0 SG_LIGHT_DIRECTIONAL
  #define SG_LIGHT_TYPE_1 SG_LIGHT_DIRECTIONAL
  #define SG_LIGHT_TYPE_2 SG_LIGHT_POINT
\endcode
271

272
\section ShaderGenerator_general_vertex_shader_structure Vertex shader generation structure
273

274
\code
275
276
void main()
{
277
278
  vec4 sg_vPosPS    = g_mWVP * inPosition;
  vec4 sg_vPosVS    = g_mWV  * inPosition;
279
280
  vec3 sg_vNormalVS = vec3(0.0, 1.0, 0.0);
  vec2 sg_vTexCoord = vec2(0.0, 0.0);
281
  vec4 sg_cColor    = vec4(g_cEmissive, ALPHA);
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

#if normals available
  sg_vNormalVS = g_mWVIT * inNormal;

#if textured
  sg_vTexCoord = inTexCoord;

#if vertexcolors
  sg_cColor = inColor;


#if vertex-lighting enabled
  lighting code, save lit color in sg_cColor


  // -------------------------------------------------------------------------
  // begin customized code
299
300
  // - insert registered begin-code modifiers, that ideally operate on generated sg_* variables
  // - loaded code from template file is added here
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  // make sure to use #ifdef #endif if you make use of conditional inputs such as normals, texcoords..
  // end of customized code
  // -------------------------------------------------------------------------
  
  gl_Position = sv_vPosPS;
  outPosCS = sg_vPosPS;

#if textured
  outTexCoord = sg_vTexCoord;

#if vertex-lighting
  outColor = sg_cColor;

#if fragment-lighting
  outNormal = sg_vNormalVS;
  outPosVS = sg_vPosVS;

318
  // end-code modifiers are added here
319
320
}

321
322
\endcode

323
324
325

---------------------------------------------------------------------------------------

326
\section ShaderGenerator_general_fragment_shader_structure Fragment shader generation structure
327
328


329
\code
330
331
void main()
{
332

333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
  // compute screen-projected coordinates, useful for various post-processing effects
  vec2 sg_vScreenPos = outPosCS.xy / outPosCS.w * 0.5 + vec2(0.5, 0.5);
  
  vec4 sg_cColor = vec4(g_cEmisive, ALPHA);

#if vertex-lighting
  sg_cColor = outColor;

#if fragment lighting
  vec4 sg_vPosVS = outPosVS;
  vec3 sg_vNormalVS = outNormal;
  lighting code here, save color to sg_cColor


#if textured
  vec4 sg_cTex = texture(g_Texture0, outTexCoord);
  sg_cColor *= sg_cTex;

  // -------------------------------------------------------------------------
  // begin customized code
353
354
  // - insert registered begin-code modifiers, that ideally operate on generated sg_* variables
  // - loaded code from template file is added here
355
356
357
358
359
360
  // make sure to use #ifdef #endif if you make use of conditional inputs such as normals, texcoords..
  // end of customized code
  // -------------------------------------------------------------------------

  outFragment = sg_cColor;

361
  // end-code modifiers are added here
362
}
363
\endcode
364
365
366

*/

Christopher Tenter's avatar
Christopher Tenter committed
367
/**
368
The ShaderGenerator is used to collect shader io, uniforms, defines and includes.
Christopher Tenter's avatar
Christopher Tenter committed
369
370
371
372

The shader main-function is not generated here and must be provided
as a parameter to the buildShaderCode function.
*/
373
class ACGDLLEXPORT ShaderGenerator
Christopher Tenter's avatar
Christopher Tenter committed
374
375
376
377
378
379
{
public:

  ShaderGenerator();
  virtual ~ShaderGenerator();

Jan Möbius's avatar
Jan Möbius committed
380
  /** \brief Imports another shader, same as \#include
Christopher Tenter's avatar
Christopher Tenter committed
381
  */
382
  void addIncludeFile(QString _fileName);
Christopher Tenter's avatar
Christopher Tenter committed
383

384
  /** \brief Adds fitting vertex shader io for a given description
Christopher Tenter's avatar
Christopher Tenter committed
385
386
387
  */
  void initVertexShaderIO(const ShaderGenDesc* _desc);
  
388
389
390
391
  /** \brief Adds fitting vertex shader io for a given description
  */
  void initGeometryShaderIO(const ShaderGenDesc* _desc);

392
  /** \brief Adds fitting fragment shader io for a given description
Christopher Tenter's avatar
Christopher Tenter committed
393
394
395
  */
  void initFragmentShaderIO(const ShaderGenDesc* _desc);

396
397
398
  /** \brief Adds frequently used uniform parameters
   *
   * Adds frequently used uniform parameters like:
399
400
401
   *  - world, view, projection matrices
   *  - cam pos, view dir
   *  - per object material names: g_cDiffuse, g_cAmbient...
Christopher Tenter's avatar
Christopher Tenter committed
402
403
404
  */
  void initDefaultUniforms();

405
406
407
408
  /** \brief Add one GLSL input specifier
   *
   * Stores string pointer only
   * Example:
409
410
411
   * \code
   *   in vec4 inPosition;
   * \endcode
Christopher Tenter's avatar
Christopher Tenter committed
412
  */
413
  void addInput(QString _input);
Christopher Tenter's avatar
Christopher Tenter committed
414

415
416
417
418
  /** \brief Add one GLSL output specifier
   *
   * Stores string pointer only
   * Example:
419
420
421
   * \code
   *   out vec4 inPosition;
   *   \endcode
422
   */
423
  void addOutput(QString _output);
Christopher Tenter's avatar
Christopher Tenter committed
424

425
426
427
428
  /** \brief Add one GLSL uniform specifier
   *
   * Stores string pointer only
   * Example:
429
430
431
   * \code
   *   uniform sampler2D sampAmbient;
   * \endcode
432
   */
Jan Möbius's avatar
Jan Möbius committed
433
  void addUniform(QString _uniform, QString _comment = "");
Christopher Tenter's avatar
Christopher Tenter committed
434

435
436
437
  /** \brief Add one define
   *
   * Example:
438
439
440
   * \code
   *   #define SG_GOURAUD 1
   * \endcode
441
   */
442
  void addDefine(QString _uniform);
Christopher Tenter's avatar
Christopher Tenter committed
443
444


445
  /** \brief Add a light description to shader:
Christopher Tenter's avatar
Christopher Tenter committed
446
447
448
  */
  void addLight(int lightIndex_, ShaderGenLightType _light);

449
  /** \brief Shader assembly function
Christopher Tenter's avatar
Christopher Tenter committed
450
  */
451
  void buildShaderCode(QStringList* _pMainCode);
Christopher Tenter's avatar
Christopher Tenter committed
452

453
  /** \brief Get result of buildShaderCode
Christopher Tenter's avatar
Christopher Tenter committed
454
  */
455
  const QStringList& getShaderCode();
Christopher Tenter's avatar
Christopher Tenter committed
456

457
458
  /** \brief Save generated shader code to text file
   *
459
   * @param _fileName Where to save
Christopher Tenter's avatar
Christopher Tenter committed
460
461
462
463
464
  */
  void saveToFile(const char* _fileName);

private:

465
466
467
468
  /** aborts, if string already present
   *  prefix, postfix are very primitive,
   *  only checks for occurrence disregard locations
   */
Jan Möbius's avatar
Jan Möbius committed
469
  void addStringToList(QString _str, QStringList* _list, QString _prefix = "", QString _postfix = "");
Christopher Tenter's avatar
Christopher Tenter committed
470
471
472
473

  /** Adds command lines to the shader code.
  Eventually appends missing ';'
  */
474
  void addIOToCode(const QStringList& _cmds);
Christopher Tenter's avatar
Christopher Tenter committed
475

476
  QStringList code_;
Christopher Tenter's avatar
Christopher Tenter committed
477
478


479
  /// glsl code imports (with \#include )
480
  QStringList imports_;
Christopher Tenter's avatar
Christopher Tenter committed
481

482
  QString version_;
Christopher Tenter's avatar
Christopher Tenter committed
483

484
485
486
487
  QStringList inputs_;
  QStringList outputs_;
  QStringList uniforms_;
  QStringList genDefines_;
Christopher Tenter's avatar
Christopher Tenter committed
488
489
490
};


491

Jan Möbius's avatar
Jan Möbius committed
492
493
494
495
496
497
/**
 *
 * A shader modifier can modify uniforms, in/outputs
 * and glsl code of vertex and fragment shaders.
 * This is useful for global effects like shadow mapping
 * and depth peeling, where only a little changes in code are necessary.
498
499
 *
 * Usage:
500
501
502
 *  -# Derive a new subclass of ShaderModifier and implement necessary modify functions.
 *  -# Allocate a static instance of your modifier and register it to ShaderProgGenerator to get it's modifier-ID
 *  -# Create ShaderProgGenerator with a bitwise combination of modifier IDs to activate them.
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
 *
 * Example:
 * \code
 *
 *   // First modifier
 *   class VertexShaderModifier1 : public ACG::ShaderModifier {
 *   public:
 *     void modifyVertexEndCode(QStringList* _code) {
 *       _code->push_back("// Vertex End Code Modifier begin");
 *       _code->push_back("<Some glsl code>  ");
 *       _code->push_back("// Vertex End Code Modifier end");
 *     }
 *
 *     static VertexShaderModifier1 instance;
 *   };
 *
 *   // Static instance required!
 *   VertexShaderModifier YarnVertexShaderModifier::instance;
 *
 *
 *   class VertexShaderModifier2 : public ACG::ShaderModifier {
 *   public:
 *     void modifyVertexEndCode(QStringList* _code) {
 *       _code->push_back("// Vertex End Code Modifier 2 begin");
 *       _code->push_back("<Some glsl code>  ");
 *       _code->push_back("// Vertex End Code Modifier 2 end");
 *     }
 *
 *     static VertexShaderModifier2 instance;
 *   };
 *
 *   VertexShaderModifier2 VertexShaderModifier2::instance;
 * \endcode
 *
 * To use the modifiers, you have to register them to the shader generator:
 * \code
 *  // Register the modifiers
 *  ACG::ShaderProgGenerator::registerModifier(&VertexShaderModifier::instance);
 *  ACG::ShaderProgGenerator::registerModifier(&VertexShaderModifier2::instance);
 *
 *  // Use them via the shader cache
 *  GLSL::Program* prog = ACG::ShaderCache::getInstance()->getProgram(&shDesc,(VertexShaderModifier::instance.getID() | VertexShaderModifier2::instance.getID() ));
 * \endcode
Jan Möbius's avatar
Jan Möbius committed
546
 */
547
548
549
550
551
552
553
554
class ACGDLLEXPORT ShaderModifier
{
  friend class ShaderProgGenerator;

public:
  ShaderModifier(void);
  virtual ~ShaderModifier(void);

555
556
557
558
559
560
561
562
563
564
  /** \brief Add your own inputs/outputs to the vertex shader.
  *
  * Your implementation may look like this:
  *
  * \code
  *   _shader->addInput("vec4 inTangent");
  *   _shader->addUniform("vec4 shaderParam");
  * \endcode
  *
  * @param _shader shader interface
565
  */
566
  virtual void modifyVertexIO(ShaderGenerator* _shader) {}
567

568
569
570
571
572
573
574
575
576
577
578
  /** \brief Append code the the vertex shader.
   *
   * Refer to the generation structure (\ref ShaderGenerator_page ) to see where
   * your code is added and which variables you can modify.
   * Use
   * \code
   *   _code->push_back("...");
   * \endcode
   * to insert your code here.
   *
   * @param _code string list of shader code.
579
  */
580
  virtual void modifyVertexBeginCode(QStringList* _code) {}
581

582
583
584
585
586
587
588
589
590
591
592
593
594
  /** \brief  Append code the the vertex shader
   *
   * Refer to the generation structure (\ref ShaderGenerator_page ) to see
   * where your code is added and which variables you can modify.
   * Use
   *
   * \code
   *   _code->push_back("...");
   * \endcode
   * to insert your code here
   *
   * @param _code string list of shader code.
   */
595
596
  virtual void modifyVertexEndCode(QStringList* _code) {}

597
598
599
600
601
602
603
604
605
606
607
608
609
  /** \brief Add your own inputs/outputs to the geometry shader.
   *
   * your implementation may look like this:
   *
   * \code
   * _shader->addInput("sampler2D depthSampler");
   * _shader->addUniform("vec4 shaderParam");
   * \endcode
   *
   * @param _shader shader interface
  */
  virtual void modifyGeometryIO(ShaderGenerator* _shader) {}

610
611
612
613
614
615
616
617
618
619
  /** \brief Add your own inputs/outputs to the fragment shader.
   *
   * your implementation may look like this:
   *
   * \code
   * _shader->addInput("sampler2D depthSampler");
   * _shader->addUniform("vec4 shaderParam");
   * \endcode
   *
   * @param _shader shader interface
620
  */
621
  virtual void modifyFragmentIO(ShaderGenerator* _shader) {}
622

623
624
625
626
627
628
629
630
631
632
633
  /** \brief Append code the the fragment shader.
   *
   * Refer to the generation structure (\ref ShaderGenerator_page ) to see where
   * your code is added and which variables you can modify.
   * Use
   * \code
   *   _code->push_back("...");
   * \endcode
   * to insert your code here
   *
   * @param _code string list of shader code.
634
  */
635
  virtual void modifyFragmentBeginCode(QStringList* _code) {}
636

637
  /** \brief Append code the the fragment shader.
638
639
640
641
642
643
644
645
646
   *
   *  Refer to the generation structure (\ref ShaderGenerator_page )
   *  to see where your code is added and which variables you can modify.
   *  Use
   *  \code
   *    _code->push_back("...");
   *  \endcode
   *  to insert your code here.
   * @param _code string list of shader code.
647
  */
648
649
  virtual void modifyFragmentEndCode(QStringList* _code) {}

650
651
652
  /** \brief Returns the modifier ID
   *
   * @return Id of the modifier
653
  */
654
655
656
657
658
659
660
661
  unsigned int getID() {return modifierID_;}

  operator unsigned int() const {return modifierID_;}

private:
  unsigned int modifierID_;
};

Jan Möbius's avatar
Jan Möbius committed
662
663
664
665

/**
ShaderProgGenerator is responsible for generating a matching pair of vertex and fragment shaders.
*/
666
class ACGDLLEXPORT ShaderProgGenerator
Christopher Tenter's avatar
Christopher Tenter committed
667
668
{
public:
669
670
671
672
673
674
675

  /**
  The shader directory has to be defined first before making use of the generator!
  For example: setShaderDir(OpenFlipper::Options::shaderDirStr())
  */
  static void setShaderDir(QString _dir);

676
677
678
679
680
  /**
  Return shader directory path as previosly specified by user
  */
  static QString getShaderDir();

681
682
683
684
  /** 
  @param _desc description-set of shader properties.
  @param _modifierFlags bitflag of modifier-IDs that should be used for the generation.
  */
685
  ShaderProgGenerator(const ShaderGenDesc* _desc, unsigned int _modifierFlags = 0);
Christopher Tenter's avatar
Christopher Tenter committed
686
687
  virtual ~ShaderProgGenerator(void);

688

Christopher Tenter's avatar
Christopher Tenter committed
689
  void saveVertexShToFile(const char* _fileName);
690
  void saveGeometryShToFile(const char* _fileName);
Christopher Tenter's avatar
Christopher Tenter committed
691
692
  void saveFragmentShToFile(const char* _fileName);

693
  /** \brief Returns generated vertex shader code
Christopher Tenter's avatar
Christopher Tenter committed
694
  */
Christopher Tenter's avatar
Christopher Tenter committed
695
  const QStringList& getVertexShaderCode();
Christopher Tenter's avatar
Christopher Tenter committed
696

697
698
699
700
  /** \brief Returns generated geometry shader code
  */
  const QStringList& getGeometryShaderCode();

701
  /** \brief Returns generated fragment shader code
Christopher Tenter's avatar
Christopher Tenter committed
702
703
  */
  const QStringList& getFragmentShaderCode();
Christopher Tenter's avatar
Christopher Tenter committed
704

705

706
707
708
709
710
711
  /** \brief Shader modifiers has to be registered before it can be used.
             They also must remain allocated for the rest of the applications runtime.
             Use a combination of modifier-IDs in the constructor of ShaderProgGen to active them.
  @param _modifier address of a modifier implementation
  @return modifier ID
  */
712
713
  static unsigned int registerModifier(ShaderModifier* _modifier);

714
  bool hasGeometryShader() { return !desc_.geometryTemplateFile.isEmpty(); };
715

716
717
718
719
  /** \brief Generates the shader code
  */
  void generateShaders();

Christopher Tenter's avatar
Christopher Tenter committed
720
721
private:

722
  /** \brief Loads external shader templates
Christopher Tenter's avatar
Christopher Tenter committed
723
724
725
  */
  void loadShaderTemplateFromFile();

Christopher Tenter's avatar
Christopher Tenter committed
726
  void buildVertexShader();
727
  void buildGeometryShader();
Christopher Tenter's avatar
Christopher Tenter committed
728
729
  void buildFragmentShader();

730
731
  void addVertexBeginCode(QStringList* _code);
  void addVertexEndCode(QStringList* _code);
Christopher Tenter's avatar
Christopher Tenter committed
732

733
734
  void addFragmentBeginCode(QStringList* _code);
  void addFragmentEndCode(QStringList* _code);
Christopher Tenter's avatar
Christopher Tenter committed
735

736
737
738
739
  /** \brief Adds lighting definition functions
   *
   * LitPointLight() ...
   */
740
  void addLightingFunctions(QStringList* _code);
Christopher Tenter's avatar
Christopher Tenter committed
741

742
743
  /** \brief Adds lighting function calls to code
   */
744
  void addLightingCode(QStringList* _code);
Christopher Tenter's avatar
Christopher Tenter committed
745
746

  /// returns path to _strFileName without last slash
747
  QString getPathName(QString _strFileName);
Christopher Tenter's avatar
Christopher Tenter committed
748
749
750

  /// checks if _str is an include directive
  /// eventually imports the included file to the specified generator
751
  int checkForIncludes(QString _str, ShaderGenerator* _gen, QString _includePath);
Christopher Tenter's avatar
Christopher Tenter committed
752
753
754
755
756
757

  /// provide generated defines to shader
  void initGenDefines(ShaderGenerator* _gen);

  static void loadLightingFunctions();

Christopher Tenter's avatar
Christopher Tenter committed
758
  static void loadStringListFromFile(QString _fileName, QStringList* _out);
Christopher Tenter's avatar
Christopher Tenter committed
759
760

  ShaderGenerator* vertex_;
761
  ShaderGenerator* geometry_;
Christopher Tenter's avatar
Christopher Tenter committed
762
763
  ShaderGenerator* fragment_;

764
  QStringList vertexTemplate_;
765
  QStringList geometryTemplate_;
766
  QStringList fragmentTemplate_;
Christopher Tenter's avatar
Christopher Tenter committed
767

768
769
770
771
772
773
774
  ShaderGenDesc   desc_;
  unsigned int usage_;


  /// registered shader modifier
  static int numModifiers_;
  static ShaderModifier* modifiers_[32];
Christopher Tenter's avatar
Christopher Tenter committed
775
776

  /// path + filename to shader templates
777
  QString vertexShaderFile_;
778
  QString geometryShaderFile_;
779
  QString fragmentShaderFile_;
Christopher Tenter's avatar
Christopher Tenter committed
780
781


782
  static QString shaderDir_;
783
  static QStringList lightingCode_;
784
785

  
Christopher Tenter's avatar
Christopher Tenter committed
786
787
788
};


Jan Möbius's avatar
Jan Möbius committed
789
790
791
//=============================================================================
} // namespace ACG
//=============================================================================