50 #include "ShaderGenerator.hh"
57 #include <QTextStream>
65 std::vector<ShaderModifier*> ShaderProgGenerator::registeredModifiers_;
75 ShaderGenerator::Keywords::Keywords()
77 : macro_requestPosVS(
"#define SG_REQUEST_POSVS"),
78 macro_requestPosOS(
"#define SG_REQUEST_POSOS"),
79 macro_requestTexcoord(
"#define SG_REQUEST_TEXCOORD"),
80 macro_requestVertexColor(
"#define SG_REQUEST_VERTEXCOLOR"),
81 macro_requestNormalVS(
"#define SG_REQUEST_NORMALVS"),
82 macro_requestNormalOS(
"#define SG_REQUEST_NORMALOS"),
84 macro_requestRenormalize(
"#define SG_REQUEST_RENORMARLIZE"),
88 macro_inputPosVS(
"SG_INPUT_POSVS"),
89 macro_inputPosOS(
"SG_INPUT_POSOS"),
90 macro_inputPosCS(
"SG_INPUT_POSCS"),
91 macro_inputNormalVS(
"SG_INPUT_NORMALVS"),
92 macro_inputNormalOS(
"SG_INPUT_NORMALOS"),
93 macro_inputTexcoord(
"SG_INPUT_TEXCOORD"),
94 macro_inputVertexColor(
"SG_INPUT_VERTEXCOLOR"),
96 macro_outputPosVS(
"SG_OUTPUT_POSVS"),
97 macro_outputPosOS(
"SG_OUTPUT_POSOS"),
98 macro_outputPosCS(
"SG_OUTPUT_POSCS"),
99 macro_outputNormalVS(
"SG_OUTPUT_NORMALVS"),
100 macro_outputNormalOS(
"SG_OUTPUT_NORMALOS"),
101 macro_outputTexcoord(
"SG_OUTPUT_TEXCOORD"),
102 macro_outputVertexColor(
"SG_OUTPUT_VERTEXCOLOR"),
107 ioNormalVS(
"NormalVS"),
108 ioNormalOS(
"NormalOS"),
109 ioTexcoord(
"TexCoord"),
112 vs_inputPrefix(
"in"),
113 vs_outputPrefix(
"outVertex"),
114 tcs_outputPrefix(
"outTc"),
115 tes_outputPrefix(
"outTe"),
116 gs_outputPrefix(
"outGeometry"),
117 fs_outputPrefix(
"outFragment"),
119 vs_inputPosition(vs_inputPrefix +
"Position"),
120 vs_inputNormal(vs_inputPrefix +
"Normal"),
121 vs_inputTexCoord(vs_inputPrefix + ioTexcoord),
122 vs_inputColor(vs_inputPrefix + ioColor),
124 vs_outputPosCS(vs_outputPrefix + ioPosCS),
125 vs_outputPosVS(vs_outputPrefix + ioPosVS),
126 vs_outputPosOS(vs_outputPrefix + ioPosOS),
127 vs_outputTexCoord(vs_outputPrefix + ioTexcoord),
128 vs_outputNormalVS(vs_outputPrefix + ioNormalVS),
129 vs_outputNormalOS(vs_outputPrefix + ioNormalOS),
130 vs_outputVertexColor(vs_outputPrefix + ioColor),
131 fs_outputFragmentColor(fs_outputPrefix)
135 const ShaderGenerator::Keywords ShaderGenerator::keywords;
138 ShaderGenerator::ShaderGenerator()
139 : version_(150), inputArrays_(false), outputArrays_(false)
143 ShaderGenerator::~ShaderGenerator()
157 addInput(
"vec4", keywords.vs_inputPosition);
158 addOutput(
"vec4", keywords.vs_outputPosCS);
160 if (_iodesc->inputNormal_)
161 addInput(
"vec3", keywords.vs_inputNormal);
163 if (_desc->textured())
165 std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = _desc->textureTypes().begin();
168 if (iter->second.type == GL_TEXTURE_3D) {
169 addInput(
"vec3", keywords.vs_inputTexCoord);
170 addOutput(
"vec3", keywords.vs_outputTexCoord);
172 addInput(
"vec2", keywords.vs_inputTexCoord);
173 addOutput(
"vec2", keywords.vs_outputTexCoord);
177 if (_iodesc->inputColor_)
178 addInput(
"vec4", keywords.vs_inputColor);
180 if (_iodesc->passNormalVS_)
181 addOutput(
"vec3", keywords.vs_outputNormalVS);
183 if (_iodesc->passNormalOS_)
184 addOutput(
"vec3", keywords.vs_outputNormalOS);
192 if (_desc->shadeMode == SG_SHADE_FLAT)
194 if (!_desc->geometryTemplateFile.isEmpty())
195 strColorOut = keywords.vs_outputVertexColor;
199 addStringToList(
"vec4 " + keywords.vs_outputVertexColor, &outputs_,
"flat out ",
"; ");
202 else if (_desc->shadeMode == SG_SHADE_GOURAUD || _desc->vertexColors || _iodesc->inputColor_)
203 strColorOut = keywords.vs_outputVertexColor;
205 if (strColorOut.size())
209 addStringToList(
"vec4 " + keywords.vs_outputVertexColor, &outputs_, _desc->vertexColorsInterpolator +
" out ",
";");
215 if (_iodesc->passPosVS_)
216 addOutput(
"vec4", keywords.vs_outputPosVS);
218 if (_iodesc->passPosOS_)
219 addOutput(
"vec4", keywords.vs_outputPosOS);
221 if (_iodesc->passTexCoord_ && !_desc->textured())
226 if (_desc->texGenMode && _desc->texGenDim > 0 && _desc->texGenDim <= 4 && !_desc->texGenPerFragment)
227 texdim = _desc->texGenDim;
229 QString texcoordType;
231 texcoordType.sprintf(
"vec%i", texdim);
233 texcoordType =
"float";
235 addInput(texcoordType, keywords.vs_inputTexCoord);
236 addOutput(texcoordType, keywords.vs_outputTexCoord);
240 defineIOAbstraction(_iodesc,
true,
false);
247 outputArrays_ =
true;
249 outputPrefix_ = keywords.tcs_outputPrefix;
251 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
253 defineIOAbstraction(_iodesc,
false,
false);
260 outputArrays_ =
false;
262 outputPrefix_ = keywords.tes_outputPrefix;
264 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
266 defineIOAbstraction(_iodesc,
false,
false);
273 outputArrays_ =
false;
275 outputPrefix_ = keywords.gs_outputPrefix;
277 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
279 defineIOAbstraction(_iodesc,
false,
false);
287 inputArrays_ =
false;
288 outputArrays_ =
false;
290 outputPrefix_ = keywords.fs_outputPrefix;
292 matchInputs(_prevStage,
false);
293 addOutput(
"vec4", keywords.fs_outputFragmentColor);
295 defineIOAbstraction(_iodesc,
false,
true);
299 void ShaderGenerator::defineIOAbstraction(
const DefaultIODesc* _iodesc,
bool _vs,
bool _fs )
305 addIODefine(keywords.macro_inputPosOS, keywords.vs_inputPosition);
308 addIODefine(keywords.macro_inputTexcoord, keywords.vs_inputTexCoord);
310 if (_iodesc->inputNormal_)
311 addIODefine(keywords.macro_inputNormalOS, keywords.vs_inputNormal);
313 if (_iodesc->inputColor_)
314 addIODefine(keywords.macro_inputVertexColor, keywords.vs_inputColor);
320 addIODefine(keywords.macro_outputPosCS, keywords.vs_outputPosCS);
323 addIODefine(keywords.macro_outputPosVS, keywords.vs_outputPosVS);
325 if (_iodesc->passPosOS_)
326 addIODefine(keywords.macro_outputPosOS, keywords.vs_outputPosOS);
328 if (_iodesc->passTexCoord_)
329 addIODefine(keywords.macro_outputTexcoord, keywords.vs_outputTexCoord);
331 if (_iodesc->passNormalVS_)
332 addIODefine(keywords.macro_outputNormalVS, keywords.vs_outputNormalVS);
334 if (_iodesc->passNormalOS_)
335 addIODefine(keywords.macro_outputNormalOS, keywords.vs_outputNormalOS);
337 if (_iodesc->passColor_)
338 addIODefine(keywords.macro_outputVertexColor, keywords.vs_outputVertexColor);
344 addIODefine(keywords.macro_inputPosVS, inputPrefix_ + keywords.ioPosVS);
346 addIODefine(keywords.macro_outputPosVS, outputPrefix_ + keywords.ioPosVS);
349 if (_iodesc->passPosOS_)
351 addIODefine(keywords.macro_inputPosOS, inputPrefix_ + keywords.ioPosOS);
353 addIODefine(keywords.macro_outputPosOS, outputPrefix_ + keywords.ioPosOS);
356 addIODefine(keywords.macro_inputPosCS, inputPrefix_ + keywords.ioPosCS);
358 addIODefine(keywords.macro_outputPosCS, outputPrefix_ + keywords.ioPosCS);
360 if (_iodesc->passNormalVS_)
362 addIODefine(keywords.macro_inputNormalVS, inputPrefix_ + keywords.ioNormalVS);
364 addIODefine(keywords.macro_outputNormalVS, outputPrefix_ + keywords.ioNormalVS);
367 if (_iodesc->passNormalOS_)
369 addIODefine(keywords.macro_inputNormalOS, inputPrefix_ + keywords.ioNormalOS);
371 addIODefine(keywords.macro_outputNormalOS, outputPrefix_ + keywords.ioNormalOS);
374 if (_iodesc->passTexCoord_)
376 addIODefine(keywords.macro_inputTexcoord, inputPrefix_ + keywords.ioTexcoord);
378 addIODefine(keywords.macro_outputTexcoord, outputPrefix_ + keywords.ioTexcoord);
381 if (_iodesc->passColor_)
383 addIODefine(keywords.macro_inputVertexColor, inputPrefix_ + keywords.ioColor);
385 addIODefine(keywords.macro_outputVertexColor, outputPrefix_ + keywords.ioColor);
394 void ShaderGenerator::initDefaultUniforms()
396 addUniform(
"mat4 g_mWVP" ,
" // Projection * Modelview");
397 addUniform(
"mat4 g_mWV" ,
" // Modelview matrix");
398 addUniform(
"mat3 g_mWVIT" ,
" // Modelview inverse transposed");
399 addUniform(
"mat4 g_mP",
" // Projection matrix");
401 addUniform(
"vec3 g_vCamPos");
402 addUniform(
"vec3 g_vCamDir");
404 addUniform(
"vec3 g_cDiffuse");
405 addUniform(
"vec3 g_cAmbient");
406 addUniform(
"vec3 g_cEmissive");
407 addUniform(
"vec3 g_cSpecular");
408 addUniform(
"vec4 g_vMaterial");
409 addUniform(
"vec3 g_cLightModelAmbient");
413 #define ADDLIGHT(x) (sz.sprintf(x"_%d", lightIndex_), addUniform(sz))
415 void ShaderGenerator::addLight(
int lightIndex_, ShaderGenLightType _light)
419 ADDLIGHT(
"vec3 g_cLightDiffuse");
420 ADDLIGHT(
"vec3 g_cLightAmbient");
421 ADDLIGHT(
"vec3 g_cLightSpecular");
423 if (_light == SG_LIGHT_POINT ||
424 _light == SG_LIGHT_SPOT)
426 ADDLIGHT(
"vec3 g_vLightPos");
427 ADDLIGHT(
"vec3 g_vLightAtten");
430 if (_light == SG_LIGHT_DIRECTIONAL ||
431 _light == SG_LIGHT_SPOT)
432 ADDLIGHT(
"vec3 g_vLightDir");
435 if (_light == SG_LIGHT_SPOT)
436 ADDLIGHT(
"vec2 g_vLightAngleExp");
441 void ShaderGenerator::addStringToList(QString _str,
449 if (!_str.startsWith(_prefix))
452 if (!_str.endsWith(_postfix))
457 tmp = tmp.simplified();
460 if (!_arr->contains(tmp))
461 _arr->push_back(tmp);
466 void ShaderGenerator::addInput(
const QString& _input)
468 addStringToList(_input, &inputs_,
"in ",
";");
472 void ShaderGenerator::addOutput(
const QString& _output)
474 addStringToList(_output, &outputs_,
"out ",
";");
478 void ShaderGenerator::addDefine(
const QString& _def)
480 addStringToList(_def, &genDefines_,
"#define ");
484 void ShaderGenerator::addIODefine(
const QString& _macroName,
const QString& _resolvedName)
486 addDefine(_macroName + QString(
" ") + _resolvedName);
489 void ShaderGenerator::addMacros(
const QStringList& _macros)
494 typedef std::reverse_iterator<QStringList::const_iterator> QStringListReverseIterator;
495 QStringListReverseIterator rbegin( _macros.end() ), rend( _macros.begin() );
497 for (QStringListReverseIterator it = rbegin; it != rend; ++it)
498 genDefines_.push_front(*it);
501 bool ShaderGenerator::hasDefine(QString _define)
const
503 if (genDefines_.contains(_define))
508 QString trimmedDef = _define.trimmed();
510 for (QStringList::const_iterator it = genDefines_.constBegin(); it != genDefines_.constEnd(); ++it)
512 QString trimmedRef = it->trimmed();
514 if (trimmedRef.startsWith(trimmedDef))
519 for (QStringList::const_iterator it = rawIO_.constBegin(); it != rawIO_.constEnd(); ++it)
521 QString trimmedRef = it->trimmed();
523 if (trimmedRef.startsWith(trimmedDef))
530 void ShaderGenerator::addLayout(QString _def)
532 addStringToList(_def, &layouts_);
536 void ShaderGenerator::addUniform(QString _uniform, QString _comment)
539 if (!_uniform.startsWith(
"uniform ") && !_uniform.contains(
" uniform "))
542 addStringToList(_uniform, &uniforms_, prefix,
"; " + _comment );
547 void ShaderGenerator::addIOToCode(
const QStringList& _cmds)
555 if (!it.contains(
";"))
556 code_.back().append(
";");
562 void ShaderGenerator::buildShaderCode(QStringList* _pMainCode,
const QStringList& _defaultLightingFunctions)
565 glslversion.sprintf(
"#version %d", version_);
567 code_.push_back(glslversion);
572 foreach(it, genDefines_)
576 foreach(it, layouts_)
580 addIOToCode(inputs_);
581 addIOToCode(outputs_);
582 addIOToCode(uniforms_);
585 bool requiresLightingCode =
false;
588 foreach(it, imports_)
590 if (it.contains(
"LitDirLight") || it.contains(
"LitPointLight") || it.contains(
"LitSpotLight"))
591 requiresLightingCode =
true;
594 if (requiresLightingCode)
596 foreach(it, _defaultLightingFunctions)
601 foreach(it, imports_)
607 if (!requiresLightingCode)
609 foreach(it, (*_pMainCode))
611 if (it.contains(
"LitDirLight") || it.contains(
"LitPointLight") || it.contains(
"LitSpotLight"))
612 requiresLightingCode =
true;
615 if (requiresLightingCode)
617 foreach(it, _defaultLightingFunctions)
624 code_.append(rawIO_);
628 foreach(it, (*_pMainCode))
634 void ShaderGenerator::addIncludeFile(QString _fileName)
636 QFile file(_fileName);
638 if (file.open(QIODevice::ReadOnly | QIODevice::Text))
640 QTextStream fileStream(&file);
644 imports_.push_back(
"// ==============================================================================");
645 imports_.push_back(QString(
"// ShaderGenerator - begin of imported file: ") + _fileName);
648 while (!fileStream.atEnd())
650 QString tmpLine = fileStream.readLine();
652 imports_.push_back(tmpLine.simplified());
658 imports_.push_back(QString(
"// ShaderGenerator - end of imported file #include \"") + _fileName);
659 imports_.push_back(
"// ==============================================================================");
667 void ShaderGenerator::saveToFile(
const char* _fileName)
669 QFile file(_fileName);
670 if (file.open(QIODevice::WriteOnly | QIODevice::Text))
672 QTextStream fileStream(&file);
676 fileStream << it <<
'\n';
682 const QStringList& ShaderGenerator::getShaderCode()
687 void ShaderGenerator::setGLSLVersion(
int _version )
693 bool _passToNextStage,
694 QString _inputPrefix,
695 QString _outputPrefix)
697 if (!_previousShaderStage)
699 std::cout <<
"error: ShaderGenerator::matchInputs called without providing input stage" << std::endl;
704 foreach(it, _previousShaderStage->outputs_)
708 QString outKeyword =
"out ";
709 QString inKeyword =
"in ";
712 input.replace(input.indexOf(outKeyword), outKeyword.size(), inKeyword);
718 QRegExp alphaNum(
"[a-zA-Z0-9]");
719 int lastNameChar = input.lastIndexOf(alphaNum);
720 input.insert(lastNameChar+1,
"[]");
726 addStringToList(input, &inputs_);
728 if (_passToNextStage)
732 QString output = input;
733 output.replace(output.indexOf(_inputPrefix), _inputPrefix.size(), _outputPrefix);
734 output.replace(output.indexOf(inKeyword), inKeyword.size(), outKeyword);
737 if (inputArrays_ && !outputArrays_)
739 int bracketStart = output.indexOf(
"[");
740 int bracketEnd = output.indexOf(
"]");
741 output.remove(bracketStart, bracketEnd-bracketStart+1);
743 else if (!inputArrays_ && outputArrays_)
745 QRegExp alphaNum(
"[a-zA-Z0-9]");
746 int lastNameChar = output.lastIndexOf(alphaNum);
747 output.insert(lastNameChar+1,
"[]");
753 addStringToList(output, &outputs_);
758 int ShaderGenerator::getNumOutputs()
const
760 return outputs_.size();
763 QString ShaderGenerator::getOutputName(
int _id)
const
765 QString output = outputs_.at(_id);
768 output.remove(
"out ");
770 int bracketStart = output.indexOf(
"[");
771 int bracketEnd = output.lastIndexOf(
"]");
773 if (bracketStart >= 0)
774 output.remove(bracketStart, bracketEnd-bracketStart+1);
777 QStringList decompOutput = output.split(
" ");
778 return decompOutput.last();
781 int ShaderGenerator::getNumInputs()
const
783 return inputs_.size();
786 QString ShaderGenerator::getInputName(
int _id)
const
788 QString input = inputs_.at(_id);
791 input.remove(
"out ");
793 int bracketStart = input.indexOf(
"[");
794 int bracketEnd = input.lastIndexOf(
"]");
796 if (bracketStart >= 0)
797 input.remove(bracketStart, bracketEnd-bracketStart+1);
800 QStringList decompInput = input.split(
" ");
801 return decompInput.last();
804 QString ShaderGenerator::getIOMapName(
int _inId)
const
806 QString inputName = getInputName(_inId);
809 QString outputName = inputName;
810 outputName.replace(outputName.indexOf(inputPrefix_), inputPrefix_.size(), outputPrefix_);
816 ShaderGenerator::DefaultIODesc::DefaultIODesc()
817 : inputTexCoord_(false),
820 passPosVS_(false), passPosOS_(false),
821 passTexCoord_(false),
823 passNormalVS_(false), passNormalOS_(false)
830 QString ShaderProgGenerator::shaderDir_;
831 QStringList ShaderProgGenerator::lightingCode_;
835 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
841 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
843 init(_desc, _modifierIDs, _numActiveMods);
847 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
849 init(_desc, _modifierIDs.empty() ? 0 : &_modifierIDs[0], (
unsigned int)_modifierIDs.size());
853 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
855 unsigned int numMods = !_modifierIDs || _modifierIDs->empty() ? 0 : (
unsigned int)_modifierIDs->size();
856 init(_desc, numMods ? &((*_modifierIDs)[0]) : 0, numMods);
860 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
862 init(_desc, _modifiers, _numActiveMods);
866 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
868 init(_desc, _modifierIDs.empty() ? 0 : &(_modifierIDs[0]), (
unsigned int)_modifierIDs.size());
872 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
874 unsigned int numMods = !_modifierIDs || _modifierIDs->empty() ? 0 : (
unsigned int)_modifierIDs->size();
875 init(_desc, numMods ? &((*_modifierIDs)[0]) : 0, numMods);
881 if (_modifierIDs && _numActiveMods)
883 activeMods_.resize(_numActiveMods);
885 for (
unsigned int i = 0; i < _numActiveMods; ++i)
886 activeMods_[i] = registeredModifiers_[ _modifierIDs[i] ];
889 init(_desc, (ShaderModifier**)0, 0);
894 if (_modifiers && _numActiveMods)
896 activeMods_.resize(_numActiveMods);
898 for (
unsigned int i = 0; i < _numActiveMods; ++i)
899 activeMods_[i] = _modifiers[i];
903 if (shaderDir_.isEmpty())
904 std::cout <<
"error: call ShaderProgGenerator::setShaderDir() first!" << std::endl;
912 if (!desc_.geometryTemplateFile.isEmpty())
913 std::cerr <<
"Warning: removing geometry shader from ShaderDesc" << std::endl;
915 desc_.geometryTemplateFile.clear();
921 if (!desc_.tessControlTemplateFile.isEmpty() || !desc_.tessEvaluationTemplateFile.isEmpty())
922 std::cerr <<
"Warning: removing tessellation shader from ShaderDesc" << std::endl;
924 desc_.tessControlTemplateFile.clear();
925 desc_.tessEvaluationTemplateFile.clear();
930 if (!desc_.geometryTemplateFile.isEmpty())
931 desc_.version = std::max(desc_.version, 150);
933 if (!desc_.tessControlTemplateFile.isEmpty() || !desc_.tessEvaluationTemplateFile.isEmpty())
934 desc_.version = std::max(desc_.version, 400);
937 loadLightingFunctions();
944 ShaderProgGenerator::~ShaderProgGenerator(
void)
957 bool success =
false;
962 QFile file(absFilename);
964 if (file.open(QIODevice::ReadOnly | QIODevice::Text))
966 if (!file.isReadable())
967 std::cout <<
"error: unreadable file -> \"" << absFilename.toStdString() <<
"\"" << std::endl;
970 QTextStream filestream(&file);
972 while (!filestream.atEnd())
974 QString szLine = filestream.readLine();
975 _out->push_back(szLine.trimmed());
984 std::cout <<
"error: " << file.errorString().toStdString() <<
" -> \"" << absFilename.toStdString() <<
"\"" << std::endl;
990 void ShaderProgGenerator::loadLightingFunctions()
992 if (lightingCode_.size())
return;
994 static const QString lightingCodeFile =
"ShaderGen/SG_LIGHTING.GLSL";
996 QString fileName = shaderDir_ + QDir::separator() + QString(lightingCodeFile);
998 lightingCode_.push_back(
"// ==============================================================================");
999 lightingCode_.push_back(QString(
"// ShaderGenerator - default lighting functions imported from file: ") + fileName);
1005 lightingCode_.push_back(QString(
"// ShaderGenerator - end of default lighting functions"));
1006 lightingCode_.push_back(
"// ==============================================================================");
1013 switch (desc_.shadeMode)
1015 case SG_SHADE_GOURAUD:
1019 case SG_SHADE_UNLIT:
1021 case SG_SHADE_PHONG:
1025 std::cout << __FUNCTION__ <<
" -> unknown shade mode: " << desc_.shadeMode << std::endl;
1028 if (desc_.textured())
1031 if (desc_.vertexColors)
1045 QString strNumLights;
1046 strNumLights.sprintf(
"SG_NUM_LIGHTS %d", desc_.numLights);
1050 const char* lightTypeNames[] = {
"SG_LIGHT_DIRECTIONAL",
1051 "SG_LIGHT_POINT",
"SG_LIGHT_SPOT"};
1053 for (
int i = 0; i < 3; ++i)
1057 for (
int i = 0; i < desc_.numLights; ++i)
1059 QString strLightType;
1060 strLightType.sprintf(
"SG_LIGHT_TYPE_%d %s", i, lightTypeNames[desc_.lightTypes[i]]);
1064 _gen->
addDefine(
"SG_ALPHA g_vMaterial.y");
1073 void ShaderProgGenerator::buildVertexShader()
1085 if (desc_.texGenDim && (desc_.texGenMode == GL_OBJECT_LINEAR || desc_.texGenMode == GL_EYE_LINEAR) && !desc_.texGenPerFragment)
1088 QString uniformDecl =
"vec4 g_vTexGenPlane";
1089 if (desc_.texGenDim > 1)
1090 uniformDecl +=
"[" + QString::number(desc_.texGenDim) +
"]";
1091 vertex_->
addUniform(uniformDecl,
" // texture projection planes");
1096 for (
size_t i = 0; i < activeMods_.size(); ++i)
1097 activeMods_[i]->modifyVertexIO(vertex_);
1107 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1108 desc_.shadeMode == SG_SHADE_FLAT)
1110 for (
int i = 0; i < desc_.numLights; ++i)
1111 vertex_->
addLight(i, desc_.lightTypes[i]);
1116 QStringList mainCode;
1118 if (!vertexTemplate_.size())
1120 mainCode.push_back(
"void main()");
1121 mainCode.push_back(
"{");
1123 addVertexBeginCode(&mainCode);
1124 addVertexEndCode(&mainCode);
1126 mainCode.push_back(
"}");
1134 foreach(it,vertexTemplate_)
1141 if (it.contains(
"SG_VERTEX_BEGIN"))
1142 addVertexBeginCode(&mainCode);
1145 if (it.contains(
"SG_VERTEX_END"))
1146 addVertexEndCode(&mainCode);
1150 mainCode.push_back(it);
1164 void ShaderProgGenerator::addVertexBeginCode(QStringList* _code)
1168 _code->push_back(QString(
"vec4 sg_vPosPS = g_mWVP * ") + ShaderGenerator::keywords.macro_inputPosOS + QString(
";"));
1169 _code->push_back(
"vec4 sg_vPosVS = g_mWV * inPosition;");
1170 _code->push_back(
"vec3 sg_vNormalVS = vec3(0.0, 1.0, 0.0);");
1171 _code->push_back(
"vec3 sg_vNormalOS = vec3(0.0, 1.0, 0.0);");
1173 if (desc_.vertexColors && (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE))
1174 _code->push_back(QString(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
".xyz, SG_ALPHA);"));
1176 _code->push_back(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * g_cAmbient, SG_ALPHA);");
1180 _code->push_back(
"sg_vNormalVS = normalize(g_mWVIT * inNormal);");
1181 _code->push_back(
"sg_vNormalOS = normalize(inNormal);");
1184 if (
ioDesc_.inputColor_ && (desc_.shadeMode == SG_SHADE_UNLIT || desc_.colorMaterialMode == GL_EMISSION))
1185 _code->push_back(QString(
"sg_cColor = ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
";"));
1192 for (
size_t i = 0; i < activeMods_.size(); ++i)
1193 activeMods_[i]->modifyVertexBeginCode(_code);
1197 void ShaderProgGenerator::addVertexEndCode(QStringList* _code)
1199 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1200 desc_.shadeMode == SG_SHADE_FLAT)
1207 _code->push_back(
"gl_Position = sg_vPosPS;");
1208 _code->push_back(
"outVertexPosCS = sg_vPosPS;");
1211 _code->push_back(
"outVertexTexCoord = sg_vTexCoord;");
1214 _code->push_back(
"outVertexColor = sg_cColor;");
1217 _code->push_back(ShaderGenerator::keywords.macro_outputNormalVS + QString(
" = sg_vNormalVS;"));
1220 _code->push_back(ShaderGenerator::keywords.macro_outputNormalOS + QString(
" = sg_vNormalOS;"));
1223 _code->push_back(ShaderGenerator::keywords.macro_outputPosVS + QString(
" = sg_vPosVS;"));
1226 _code->push_back(ShaderGenerator::keywords.macro_outputPosOS + QString(
" = ") + ShaderGenerator::keywords.macro_inputPosOS + QString(
";"));
1231 for (
size_t i = 0; i < activeMods_.size(); ++i)
1232 activeMods_[i]->modifyVertexEndCode(_code);
1238 if (_str.contains(
"#include "))
1240 QString strIncludeFile = _str.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
1242 if (strIncludeFile.isEmpty())
1243 std::cout <<
"wrong include syntax: " << _str.toStdString() << std::endl;
1246 QString fullPathToIncludeFile = _includePath + QDir::separator() + strIncludeFile;
1259 if (_str.contains(
"#include "))
1261 QString strIncludeFile = _str.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
1263 if (strIncludeFile.isEmpty())
1264 std::cout <<
"wrong include syntax: " << _str.toStdString() << std::endl;
1267 QString fullPathToIncludeFile = _includePath + QDir::separator() + strIncludeFile;
1270 fullPathToIncludeFile.replace(
'\\',
'/');
1273 QString cleanFilepath = QDir::cleanPath(fullPathToIncludeFile);
1284 void ShaderProgGenerator::buildTessControlShader()
1287 if ( desc_.tessControlTemplateFile.isEmpty() )
1297 delete tessControl_;
1315 for (
size_t i = 0; i < activeMods_.size(); ++i)
1316 activeMods_[i]->modifyTessControlIO(tessControl_);
1323 QStringList mainCode;
1328 mainCode.push_back(
"void sg_MapIO(const int inIdx)");
1329 mainCode.push_back(
"{");
1332 mainCode.push_back(
"gl_out[gl_InvocationID].gl_Position = gl_in[inIdx].gl_Position;");
1340 QString outputAssignCode = outputName + QString(
"[gl_InvocationID] = ") + inputName + QString(
"[inIdx];");
1342 mainCode.push_back(outputAssignCode);
1345 mainCode.push_back(
"}");
1351 foreach(it,tessControlTemplate_)
1356 mainCode.push_back(it);
1363 void ShaderProgGenerator::buildTessEvalShader()
1366 if ( desc_.tessEvaluationTemplateFile.isEmpty() )
1379 tessEval_ =
new ShaderGenerator();
1384 ShaderGenerator* prevStage = tessControl_;
1387 prevStage = vertex_;
1394 foreach(itLayout, tessEvalLayout_)
1398 for (
size_t i = 0; i < activeMods_.size(); ++i)
1399 activeMods_[i]->modifyTessControlIO(tessEval_);
1405 QStringList mainCode;
1412 mainCode.push_back(
"void sg_MapIOBarycentric()");
1413 mainCode.push_back(
"{");
1416 mainCode.push_back(
"gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;");
1424 QString outputAssignCode = outputName + QString(
" = ") +
1425 QString(
"gl_TessCoord.x*") + inputName + QString(
"[0] + ") +
1426 QString(
"gl_TessCoord.y*") + inputName + QString(
"[1] + ") +
1427 QString(
"gl_TessCoord.z*") + inputName + QString(
"[2];");
1429 mainCode.push_back(outputAssignCode);
1432 mainCode.push_back(
"}");
1437 mainCode.push_back(
"void sg_MapIOBilinear()");
1438 mainCode.push_back(
"{");
1441 mainCode.push_back(
"gl_Position = mix( mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x), mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x), gl_TessCoord.y);");
1449 QString outputAssignCode = outputName + QString(
" = mix( ") +
1450 QString(
"mix(") + inputName + QString(
"[0], ") + inputName + QString(
"[1], gl_TessCoord.x), ") +
1451 QString(
"mix(") + inputName + QString(
"[2], ") + inputName + QString(
"[3], gl_TessCoord.x), gl_TessCoord.y); ");
1453 mainCode.push_back(outputAssignCode);
1456 mainCode.push_back(
"}");
1462 QStringList::iterator it;
1463 for (it = tessEvalTemplate_.begin(); it != tessEvalTemplate_.end(); ++it)
1472 if (line.contains(
"SG_INPUT") || line.contains(
"SG_OUTPUT"))
1475 QStringList resolvedCode;
1477 resolvedCode.push_back(
"// ----------------------------------------");
1478 resolvedCode.push_back(
"// ShaderGen: resolve SG_OUTPUT = expression(SG_INPUT);");
1480 int numOccurrences = 0;
1488 QString resolvedLine = line;
1498 for (
int k = 0; k < 2; ++k)
1500 const QString stringToReplace = k ?
"SG_OUTPUT" :
"SG_INPUT";
1501 const int lenStringToReplace = stringToReplace.length();
1502 const QString replacementString = k ? outputName : inputName;
1504 int linePos = resolvedLine.indexOf(stringToReplace);
1506 while (linePos >= 0)
1508 bool replaceOcc =
true;
1510 int nextCharPos = linePos + lenStringToReplace;
1512 if (nextCharPos >= resolvedLine.size())
1515 if (nextCharPos > 0)
1517 QChar nextChar = resolvedLine.at(nextCharPos);
1519 if (nextChar ==
'_' || nextChar.isDigit() || nextChar.isLetter())
1523 linePos += lenStringToReplace;
1532 resolvedLine.replace(linePos, lenStringToReplace, replacementString);
1536 linePos = resolvedLine.indexOf(stringToReplace, linePos + 1);
1544 resolvedCode.push_back(resolvedLine);
1547 resolvedCode.push_back(
"// ----------------------------------------");
1550 mainCode.append(resolvedCode);
1552 mainCode.push_back(line);
1555 mainCode.push_back(line);
1561 void ShaderProgGenerator::buildGeometryShader()
1564 if ( desc_.geometryTemplateFile.isEmpty() )
1570 geometry_ =
new ShaderGenerator();
1575 ShaderGenerator* prevStage = tessEval_;
1578 prevStage = vertex_;
1586 for (
size_t i = 0; i < activeMods_.size(); ++i)
1587 activeMods_[i]->modifyGeometryIO(geometry_);
1593 QStringList mainCode;
1598 mainCode.push_back(
"void sg_MapIO(const int inIdx)");
1599 mainCode.push_back(
"{");
1602 mainCode.push_back(
"gl_Position = gl_in[inIdx].gl_Position;");
1603 mainCode.push_back(
"gl_PrimitiveID = gl_PrimitiveIDIn;");
1611 QString outputAssignCode = outputName + QString(
" = ") + inputName + QString(
"[inIdx];");
1613 mainCode.push_back(outputAssignCode);
1616 mainCode.push_back(
"}");
1623 foreach(it,geometryTemplate_)
1628 mainCode.push_back(it);
1636 void ShaderProgGenerator::buildFragmentShader()
1640 fragment_ =
new ShaderGenerator();
1644 ShaderGenerator* prevStage = geometry_;
1647 prevStage = tessEval_;
1649 prevStage = tessControl_;
1651 prevStage = vertex_;
1656 if (desc_.texGenDim && (desc_.texGenMode == GL_OBJECT_LINEAR || desc_.texGenMode == GL_EYE_LINEAR) && desc_.texGenPerFragment)
1659 QString uniformDecl =
"vec4 g_vTexGenPlane";
1660 if (desc_.texGenDim > 1)
1661 uniformDecl +=
"[" + QString::number(desc_.texGenDim) +
"]";
1662 fragment_->
addUniform(uniformDecl,
" // texture projection planes");
1670 if (desc_.textured())
1672 for (std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = desc_.textureTypes().begin();
1673 iter != desc_.textureTypes().end(); ++iter)
1675 QString name = QString(
"g_Texture%1").arg(iter->first);
1677 switch (iter->second.type)
1679 case GL_TEXTURE_1D: type =
"sampler1D";
break;
1680 case GL_TEXTURE_2D: type =
"sampler2D";
break;
1681 case GL_TEXTURE_3D: type =
"sampler3D";
break;
1682 case GL_TEXTURE_CUBE_MAP: type =
"samplerCube";
break;
1683 #ifdef GL_ARB_texture_rectangle //ARCH_DARWIN doesn't support all texture defines with all xcode version (xcode 5.0 seems to support all)
1684 case GL_TEXTURE_RECTANGLE_ARB: type =
"sampler2DRect";
break;
1686 #ifdef GL_ARB_texture_buffer_object
1687 case GL_TEXTURE_BUFFER_ARB: type =
"samplerBuffer";
break;
1689 #ifdef GL_EXT_texture_array
1690 case GL_TEXTURE_1D_ARRAY_EXT: type =
"sampler1DArray";
break;
1691 case GL_TEXTURE_2D_ARRAY_EXT: type =
"sampler2DArray";
break;
1693 #ifdef GL_ARB_texture_cube_map_array
1694 case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: type =
"samplerCubeArray";
break;
1696 #ifdef GL_ARB_texture_multisample
1697 case GL_TEXTURE_2D_MULTISAMPLE: type =
"sampler2DMS";
break;
1698 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: type =
"sampler2DMSArray";
break;
1700 default: std::cerr <<
"Texture Type not supported "<< iter->second.type << std::endl;
break;
1703 if (iter->second.shadow)
1710 for (
size_t i = 0; i < activeMods_.size(); ++i)
1711 activeMods_[i]->modifyFragmentIO(fragment_);
1721 if (desc_.shadeMode == SG_SHADE_PHONG)
1723 for (
int i = 0; i < desc_.numLights; ++i)
1724 fragment_->
addLight(i, desc_.lightTypes[i]);
1728 QStringList mainCode;
1730 if (!fragmentTemplate_.size())
1732 mainCode.push_back(
"void main()");
1733 mainCode.push_back(
"{");
1735 addFragmentBeginCode(&mainCode);
1736 addFragmentEndCode(&mainCode);
1738 mainCode.push_back(
"}");
1745 foreach(it,fragmentTemplate_)
1752 if (it.contains(
"SG_FRAGMENT_BEGIN"))
1753 addFragmentBeginCode(&mainCode);
1754 else if (it.contains(
"SG_FRAGMENT_END"))
1755 addFragmentEndCode(&mainCode);
1756 else if (it.contains(
"SG_FRAGMENT_LIGHTING"))
1759 mainCode.push_back(it);
1774 void ShaderProgGenerator::addFragmentBeginCode(QStringList* _code)
1777 _code->push_back(QString(
"vec4 sg_vPosCS = ") + ShaderGenerator::keywords.macro_inputPosCS + QString(
";"));
1778 _code->push_back(
"vec2 sg_vScreenPos = sg_vPosCS.xy / sg_vPosCS.w * 0.5 + vec2(0.5, 0.5);");
1780 _code->push_back(QString(
"#ifdef ") + ShaderGenerator::keywords.macro_inputPosVS);
1781 _code->push_back(QString(
"vec4 sg_vPosVS = ") + ShaderGenerator::keywords.macro_inputPosVS + QString(
";"));
1782 _code->push_back(
"#endif");
1784 _code->push_back(QString(
"#ifdef ") + ShaderGenerator::keywords.macro_inputNormalVS);
1785 _code->push_back(QString(
"vec3 sg_vNormalVS = ") + ShaderGenerator::keywords.macro_inputNormalVS + QString(
";"));
1787 _code->push_back(
"sg_vNormalVS = normalize(sg_vNormalVS);");
1788 _code->push_back(
"#endif");
1791 if (desc_.vertexColors && (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE))
1792 _code->push_back(QString(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
".xyz, SG_ALPHA);"));
1794 _code->push_back(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * g_cAmbient, SG_ALPHA);");
1796 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1797 desc_.shadeMode == SG_SHADE_FLAT ||
1798 (
ioDesc_.passColor_ && (desc_.shadeMode == SG_SHADE_UNLIT || desc_.colorMaterialMode == GL_EMISSION)))
1799 _code->push_back(QString(
"sg_cColor = ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
";"));
1801 if (desc_.shadeMode == SG_SHADE_PHONG)
1807 if (desc_.textured())
1809 std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = desc_.textureTypes().begin();
1810 _code->push_back(
"vec4 sg_cTex = texture(g_Texture"+QString::number(iter->first)+
", sg_vTexCoord);");
1812 for (++iter; iter != desc_.textureTypes().end(); ++iter)
1813 _code->push_back(
"sg_cTex += texture(g_Texture"+QString::number(iter->first)+
", sg_vTexCoord);");
1816 _code->push_back(
"sg_cTex = sg_cTex * 1.0/" + QString::number(desc_.textureTypes().size()) +
".0 ;");
1818 if (desc_.shadeMode == SG_SHADE_UNLIT)
1819 _code->push_back(
"sg_cColor += sg_cTex;");
1821 _code->push_back(
"sg_cColor *= sg_cTex;");
1826 for (
size_t i = 0; i < activeMods_.size(); ++i)
1827 activeMods_[i]->modifyFragmentBeginCode(_code);
1830 void ShaderProgGenerator::addFragmentEndCode(QStringList* _code)
1832 _code->push_back(ShaderGenerator::keywords.fs_outputFragmentColor + QString(
" = sg_cColor;"));
1835 for (
size_t i = 0; i < activeMods_.size(); ++i)
1836 activeMods_[i]->modifyFragmentEndCode(_code);
1847 for (
size_t i = 0; i < activeMods_.size() && !lightingModifier; ++i)
1849 if (activeMods_[i]->replaceDefaultLightingCode())
1850 lightingModifier = activeMods_[i];
1853 if (!lightingModifier)
1859 QString vertexColorString = (
ioDesc_.inputColor_ &&
ioDesc_.passColor_) ? (ShaderGenerator::keywords.macro_inputVertexColor + QString(
".xyz * ")) :
"";
1860 QString diffuseVertexColor = (desc_.colorMaterialMode == GL_DIFFUSE || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE) ? vertexColorString :
"";
1861 QString ambientVertexColor = (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE) ? vertexColorString :
"";
1862 QString specularVertexColor = (desc_.colorMaterialMode == GL_SPECULAR) ? vertexColorString :
"";
1864 for (
int i = 0; i < desc_.numLights; ++i)
1866 ShaderGenLightType lgt = desc_.lightTypes[i];
1870 case SG_LIGHT_DIRECTIONAL:
1872 buf = QString(
"sg_cColor.xyz += LitDirLight(sg_vPosVS.xyz, sg_vNormalVS, g_vLightDir_%1, %2 g_cLightAmbient_%1, %3 g_cLightDiffuse_%1, %4 g_cLightSpecular_%1);").arg(QString::number(i), ambientVertexColor, diffuseVertexColor, specularVertexColor);
1875 case SG_LIGHT_POINT:
1877 buf = QString(
"sg_cColor.xyz += LitPointLight(sg_vPosVS.xyz, sg_vNormalVS, g_vLightPos_%1, %2 g_cLightAmbient_%1, %3 g_cLightDiffuse_%1, %4 g_cLightSpecular_%1, g_vLightAtten_%1);").arg(QString::number(i), ambientVertexColor, diffuseVertexColor, specularVertexColor);
1882 buf = QString(
"sg_cColor.xyz += LitSpotLight(sg_vPosVS.xyz, sg_vNormalVS, g_vLightPos_%1, g_vLightDir_%1, %2 g_cLightAmbient_%1, %3 g_cLightDiffuse_%1, %4 g_cLightSpecular_%1, g_vLightAtten_%1, g_vLightAngleExp_%1);").arg(QString::number(i), ambientVertexColor, diffuseVertexColor, specularVertexColor);
1888 _code->push_back(buf);
1893 for (
size_t i = 0; i < activeMods_.size(); ++i)
1904 for (
size_t i = 0; i < activeMods_.size(); ++i)
1906 if (lightingModifier != activeMods_[i])
1915 if (!_modifier)
return;
1917 for (
int i = 0; i < desc_.numLights; ++i)
1919 ShaderGenLightType lgt = desc_.lightTypes[i];
1929 foreach(it,lightingCode_)
1930 _code->push_back(it);
1937 int texcoordVarDim = 2;
1939 !desc_.textureTypes().empty() &&
1940 desc_.textureTypes().begin()->second.type == GL_TEXTURE_3D)
1943 bool generateTexCoord = desc_.texGenDim && desc_.texGenMode && (_fragmentShader == desc_.texGenPerFragment);
1944 if (generateTexCoord)
1945 texcoordVarDim = desc_.texGenDim;
1947 QString texcoordVarInit;
1948 if (texcoordVarDim == 1)
1949 texcoordVarInit =
"float sg_vTexCoord";
1951 texcoordVarInit.sprintf(
"vec%i sg_vTexCoord", texcoordVarDim);
1955 texcoordVarInit += QString(
"= ") + ShaderGenerator::keywords.macro_inputTexcoord + QString(
";");
1956 else if (0 <= texcoordVarDim && texcoordVarDim <= 4)
1958 QString zeroVecDefs[] =
1966 texcoordVarInit += zeroVecDefs[texcoordVarDim];
1969 _code->push_back(texcoordVarInit);
1974 if (generateTexCoord)
1977 const char* texGenCoordString[] = {
"x",
"y",
"z",
"w" };
1979 switch (desc_.texGenMode)
1981 case GL_OBJECT_LINEAR:
1983 for (
int i = 0; i < desc_.texGenDim; ++i)
1985 QString assignmentInstrString;
1986 assignmentInstrString =
"sg_vTexCoord";
1987 if (desc_.texGenDim > 1)
1989 assignmentInstrString +=
".";
1990 assignmentInstrString += texGenCoordString[i];
1992 assignmentInstrString +=
" = dot(";
1993 assignmentInstrString += ShaderGenerator::keywords.macro_inputPosOS;
1994 assignmentInstrString +=
", g_vTexGenPlane";
1995 if (desc_.texGenDim > 1)
1997 assignmentInstrString +=
"[";
1998 assignmentInstrString += QString::number(i);
1999 assignmentInstrString +=
"]";
2001 assignmentInstrString +=
");";
2002 _code->push_back(assignmentInstrString);
2008 for (
int i = 0; i < desc_.texGenDim; ++i)
2010 QString assignmentInstrString;
2011 assignmentInstrString =
"sg_vTexCoord";
2012 if (desc_.texGenDim > 1)
2014 assignmentInstrString +=
".";
2015 assignmentInstrString += texGenCoordString[i];
2017 assignmentInstrString +=
" = dot(sg_vPosVS, g_vTexGenPlane";
2018 if (desc_.texGenDim > 1)
2020 assignmentInstrString +=
"[";
2021 assignmentInstrString += QString::number(i);
2022 assignmentInstrString +=
"]";
2024 assignmentInstrString +=
");";
2025 _code->push_back(assignmentInstrString);
2032 _code->push_back(
"vec3 sg_vPosVS_unit = normalize(sg_vPosVS.xyz);");
2033 _code->push_back(
"vec3 sg_TexGenRefl = reflect(sg_vPosVS_unit, sg_vNormalVS);");
2034 _code->push_back(
"vec3 sg_TexGenRefl2 = sg_TexGenRefl; sg_TexGenRefl2.z += 1.0;");
2035 _code->push_back(
"float sg_TexGenMRcp = 0.5 * inversesqrt(dot(sg_TexGenRefl2, sg_TexGenRefl2));");
2036 for (
int i = 0; i < desc_.texGenDim; ++i)
2038 QString assignmentInstrString;
2039 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_TexGenRefl.%s * sg_TexGenMRcp + 0.5;", texGenCoordString[i], texGenCoordString[i]);
2040 _code->push_back(assignmentInstrString);
2046 for (
int i = 0; i < desc_.texGenDim; ++i)
2048 QString assignmentInstrString;
2049 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_vNormalVS.%s;", texGenCoordString[i], texGenCoordString[i]);
2050 _code->push_back(assignmentInstrString);
2054 case GL_REFLECTION_MAP:
2056 _code->push_back(
"vec3 sg_vPosVS_unit = normalize(sg_vPosVS.xyz);");
2057 _code->push_back(
"vec3 sg_TexGenRefl = reflect(sg_vPosVS_unit, sg_vNormalVS);");
2058 for (
int i = 0; i < desc_.texGenDim; ++i)
2060 QString assignmentInstrString;
2061 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_TexGenRefl.%s;", texGenCoordString[i], texGenCoordString[i]);
2062 _code->push_back(assignmentInstrString);
2079 if (desc_.shadeMode != SG_SHADE_UNLIT)
2082 if (desc_.textured())
2089 int maxTexGenDim = 4;
2091 switch (desc_.texGenMode)
2094 case GL_OBJECT_LINEAR: maxTexGenDim = 4;
break;
2096 case GL_SPHERE_MAP: maxTexGenDim = 2;
break;
2099 case GL_REFLECTION_MAP: maxTexGenDim = 3;
break;
2101 default: maxTexGenDim = 0;
break;
2104 desc_.texGenDim = std::max(std::min(desc_.texGenDim, maxTexGenDim), 0);
2107 if (desc_.texGenDim && desc_.texGenMode)
2110 if (!desc_.texGenPerFragment)
2114 if (desc_.texGenMode == GL_REFLECTION_MAP || desc_.texGenMode == GL_SPHERE_MAP || desc_.texGenMode == GL_NORMAL_MAP)
2118 if (desc_.texGenPerFragment)
2120 switch (desc_.texGenMode)
2122 case GL_OBJECT_LINEAR:
ioDesc_.passPosOS_ =
true;
break;
2125 case GL_NORMAL_MAP:
ioDesc_.passNormalVS_ =
true;
break;
2133 if (desc_.vertexColors)
2136 if (desc_.shadeMode == SG_SHADE_PHONG)
2142 if (desc_.shadeMode == SG_SHADE_FLAT || desc_.shadeMode == SG_SHADE_GOURAUD || desc_.vertexColors)
2150 for (
size_t i = 0; i < activeMods_.size(); ++i)
2162 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestPosVS))
2164 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestTexcoord))
2169 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestVertexColor))
2174 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestNormalVS))
2179 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestNormalOS))
2184 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestPosOS))
2187 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestRenormalize))
2195 buildVertexShader();
2196 buildTessControlShader();
2197 buildTessEvalShader();
2198 buildGeometryShader();
2199 buildFragmentShader();
2229 void ShaderProgGenerator::saveVertexShToFile(
const char* _fileName)
2234 void ShaderProgGenerator::saveGeometryShToFile(
const char* _fileName)
2239 void ShaderProgGenerator::saveFragmentShToFile(
const char* _fileName)
2247 if (!desc_.vertexTemplateFile.isEmpty())
2252 if (!desc_.fragmentTemplateFile.isEmpty())
2257 if (!desc_.geometryTemplateFile.isEmpty())
2262 if (!desc_.tessControlTemplateFile.isEmpty())
2267 if (!desc_.tessEvaluationTemplateFile.isEmpty())
2270 scanShaderTemplate(tessEvalTemplate_, desc_.tessEvaluationTemplateFile, &tessEvalLayout_);
2275 tessControlShaderFile_ = desc_.tessControlTemplateFile;
2276 tessEvalShaderFile_ = desc_.tessEvaluationTemplateFile;
2277 geometryShaderFile_ = desc_.geometryTemplateFile;
2278 fragmentShaderFile_ = desc_.fragmentTemplateFile;
2286 QString filePath =
getPathName(_templateFilename);
2288 QStringList::iterator it;
2289 for (it = _templateSrc.begin(); it != _templateSrc.end(); ++it)
2298 it = _templateSrc.erase(it);
2300 int offset = it - _templateSrc.begin();
2305 foreach(importLine,
import)
2307 it = _templateSrc.insert(it, importLine);
2313 it = _templateSrc.begin() + offset;
2317 QString trimmedLine = it->trimmed();
2320 QByteArray lineBytes = trimmedLine.toUtf8();
2322 int templateVersion = 0;
2323 if (sscanf(lineBytes.constData(),
"#version %d", &templateVersion) == 1)
2325 desc_.version = std::max(templateVersion, desc_.version);
2328 it = _templateSrc.erase(it);
2331 else if (trimmedLine.startsWith(
"layout(") || trimmedLine.startsWith(
"layout ("))
2333 if (_outLayoutDirectives)
2335 _outLayoutDirectives->push_back(trimmedLine);
2338 it = _templateSrc.erase(it);
2345 if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestPosVS))
2347 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestTexcoord))
2352 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestVertexColor))
2357 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestNormalVS))
2362 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestNormalOS))
2367 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestPosOS))
2369 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestRenormalize))
2371 else if (trimmedLine.startsWith(
"SG_FRAGMENT_LIGHTING"))
2375 desc_.shadeMode = SG_SHADE_PHONG;
2387 return fileInfo.absolutePath();
2392 QString absFilename;
2393 if ( QDir(_strFileName).isRelative() )
2394 absFilename =
getShaderDir() + QDir::separator() + _strFileName;
2396 absFilename = _strFileName;
2398 return QDir::cleanPath(absFilename);
2408 return shaderDir_ + QString(
"/");
2414 if (!_modifier)
return 0;
2419 if (registeredModifiers_[i] == _modifier)
2422 return registeredModifiers_[i]->getID();
2426 _modifier->modifierID_ = (
unsigned int)(numRegisteredModifiers_++);
2428 registeredModifiers_.push_back(_modifier);
2429 return _modifier->modifierID_;
2434 if (_i >= 0 && _i <=
int(activeMods_.size()))
2435 return activeMods_[_i];
2443 return int(activeMods_.size());
2449 return !desc_.geometryTemplateFile.isEmpty();
2454 return !desc_.tessControlTemplateFile.isEmpty();
2459 return !desc_.tessEvaluationTemplateFile.isEmpty();
2465 ShaderModifier::ShaderModifier(
void )
2469 ShaderModifier::~ShaderModifier(
void )
2496 const QString& filename()
const {
return filename_;}
2497 const QDateTime& filetime()
const {
return filetime_;}
2498 void filetime(
const QDateTime& _newtime) {filetime_ = _newtime;}
2504 for (
int i = 0; i < 5; ++i)
2507 vertexBeginCode_.clear();
2508 vertexEndCode_.clear();
2509 fragmentBeginCode_.clear();
2510 fragmentEndCode_.clear();
2513 static ShaderModifierFile* loadFromFile(QString _filename)
2515 ShaderModifierFile* res = 0;
2519 QDateTime lastmod = QFileInfo(absFilename).lastModified();
2522 QHash<QString, ShaderModifierFile>::iterator cacheEntry = fileCache_.find(_filename);
2524 bool reload =
false;
2525 bool firstLoad =
false;
2527 if (cacheEntry != fileCache_.end())
2530 res = &cacheEntry.value();
2532 if (lastmod != res->filetime())
2552 res = &fileCache_[_filename];
2554 res->loadBlocks(lines);
2555 res->filetime(lastmod);
2569 void loadBlocks(
const QStringList& _lines)
2571 static const char* markers [] =
2580 "FragmentBeginCode:",
2583 const int numMarkers =
sizeof(markers) /
sizeof(markers[0]);
2585 QStringList* blockTargets [] =
2594 &fragmentBeginCode_,
2598 assert(
sizeof(blockTargets) /
sizeof(blockTargets[0]) == numMarkers);
2602 QStringList* curBlock_ = 0;
2607 for (QStringList::const_iterator it = _lines.begin(); it != _lines.end(); ++it, ++curLine)
2613 if (version_ <= 0 && it->startsWith(
"#version "))
2615 const int offset = strlen(
"#version ");
2616 version_ = atoi(it->toLatin1().data() + offset);
2622 bool blockMarker =
false;
2624 for (
int i = 0; i < numMarkers && !blockMarker; ++i)
2626 if ( it->startsWith(markers[i]) )
2629 curBlock_ = blockTargets[i];
2637 curBlock_->push_back(*it);
2639 std::cerr <<
"ShaderModifierFile::loadBlocks - line belongs to unknown block in file " << filename_.toLatin1().data() <<
" at line " << curLine << std::endl;
2645 void modifyIO(
int _stage, ShaderGenerator* _shader)
2648 _shader->setGLSLVersion(version_);
2650 _shader->addRawIOBlock(io_[_stage]);
2657 QDateTime filetime_;
2666 QStringList vertexBeginCode_,
2673 static QHash<QString, ShaderModifierFile> fileCache_;
2676 QHash<QString, ShaderModifierFile> ShaderModifierFile::fileCache_;
2681 return ShaderModifierFile::loadFromFile(_filename);
2691 const char* shadeModeString[] =
2700 QTextStream resStrm(&res);
2702 resStrm <<
"version: " << version;
2704 resStrm <<
"shaderDesc.numLights: " << numLights;
2708 resStrm <<
"\nshaderDesc.lightTypes[]: {";
2710 for (
int i = 0; i < numLights; ++i)
2712 switch (lightTypes[i])
2714 case SG_LIGHT_DIRECTIONAL: resStrm <<
"DIRECTIONAL";
break;
2715 case SG_LIGHT_POINT: resStrm <<
"POINT";
break;
2716 case SG_LIGHT_SPOT: resStrm <<
"SPOT";
break;
2717 default: resStrm <<
"UNDEFINED";
break;
2720 if (i + 1 < numLights)
2728 resStrm <<
"\nshaderDesc.shadeMode: " << shadeModeString[shadeMode];
2729 resStrm <<
"\nshaderDesc.vertexColors: " << vertexColors;
2730 resStrm <<
"\nshaderDesc.textured(): " << textured();
2733 resStrm <<
"\nTexture stage: " << iter->first;
2734 resStrm <<
"\nTexture Type: ";
2735 switch (iter->second.type)
2737 case GL_TEXTURE_1D: resStrm <<
"GL_TEXTURE_1D";
break;
2738 case GL_TEXTURE_2D: resStrm <<
"GL_TEXTURE_2D";
break;
2739 case GL_TEXTURE_3D: resStrm <<
"GL_TEXTURE_3D";
break;
2740 case GL_TEXTURE_CUBE_MAP: resStrm <<
"GL_TEXTURE_CUBE_MAP";
break;
2741 #ifdef GL_ARB_texture_rectangle //ARCH_DARWIN doesn't support all texture defines with all xcode version (xcode 5.0 seems to support all)
2742 case GL_TEXTURE_RECTANGLE_ARB: resStrm <<
"GL_TEXTURE_RECTANGLE";
break;
2744 #ifdef GL_ARB_texture_buffer_object
2745 case GL_TEXTURE_BUFFER_ARB: resStrm <<
"GL_TEXTURE_BUFFER";
break;
2747 #ifdef GL_EXT_texture_array
2748 case GL_TEXTURE_1D_ARRAY_EXT: resStrm <<
"GL_TEXTURE_1D_ARRAY";
break;
2749 case GL_TEXTURE_2D_ARRAY_EXT: resStrm <<
"GL_TEXTURE_2D_ARRAY";
break;
2751 #ifdef GL_ARB_texture_cube_map_array
2752 case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: resStrm <<
"GL_TEXTURE_CUBE_MAP_ARRAY";
break;
2754 #ifdef GL_ARB_texture_multisample
2755 case GL_TEXTURE_2D_MULTISAMPLE: resStrm <<
"GL_TEXTURE_2D_MULTISAMPLE";
break;
2756 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: resStrm <<
"GL_TEXTURE_2D_MULTISAMPLE_ARRAY";
break;
2758 default: std::cerr <<
"Texture Type with number "<< iter->second.type <<
" on stage "<< iter->first <<
" is not supported " << std::endl;
break;
2761 resStrm <<
"\nShadowTexture: " << iter->second.shadow;
2764 resStrm <<
"\nshaderDesc.texGenDim: " << texGenDim;
2768 case GL_OBJECT_LINEAR: resStrm <<
"\nshaderDesc.texGenMode: GL_OBJECT_LINEAR";
break;
2769 case GL_EYE_LINEAR: resStrm <<
"\nshaderDesc.texGenMode: GL_EYE_LINEAR";
break;
2770 case GL_SPHERE_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_SPHERE_MAP";
break;
2771 case GL_NORMAL_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_NORMAL_MAP";
break;
2772 case GL_REFLECTION_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_REFLECTION_MAP";
break;
2773 default: resStrm <<
"\nshaderDesc.texGenMode: unknown";
break;
2776 resStrm <<
"\nshaderDesc.texGenPerFragment: " << texGenPerFragment;
2778 if (!vertexTemplateFile.isEmpty())
2779 resStrm <<
"\nshaderDesc.vertexTemplateFile: " << vertexTemplateFile;
2781 if (!tessControlTemplateFile.isEmpty())
2782 resStrm <<
"\nshaderDesc.tessControlTemplateFile: " << tessControlTemplateFile;
2784 if (!tessEvaluationTemplateFile.isEmpty())
2785 resStrm <<
"\nshaderDesc.tessEvaluationTemplateFile: " << tessEvaluationTemplateFile;
2787 if (!geometryTemplateFile.isEmpty())
2788 resStrm <<
"\nshaderDesc.geometryTemplateFile: " << geometryTemplateFile;
2790 if (!fragmentTemplateFile.isEmpty())
2791 resStrm <<
"\nshaderDesc.fragmentTemplateFile: " << fragmentTemplateFile;
bool normalizeTexColors
Defines if the textureVariable is normalized or not, if multiple textures are used.
void init(const ShaderGenDesc *_desc, ShaderModifier *const *_modifiers, unsigned int _numActiveMods)
Called in constructor.
void initVertexShaderIO(const ShaderGenDesc *_desc, const DefaultIODesc *_iodesc)
Adds fitting vertex shader io for a given description.
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
QStringList tessControlLayout_
layout() directives scanned from loaded templates
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
virtual void modifyTessControlIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation control shader.
Namespace providing different geometric functions concerning angles.
ShaderModifier * getActiveModifier(int _i)
Get active modfiers for this program.
static int numRegisteredModifiers_
registered shader modifier
QString outputPrefix_
prefix of outputs of this shader
void modifyTessControlIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation control shader.
void addDefine(const QString &_define)
Add one define.
void addLight(int lightIndex_, ShaderGenLightType _light)
Add a light description to shader:
ShaderProgGenerator(const ShaderGenDesc *_desc)
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
static QString getAbsFilePath(QString _fileName)
Convert a filename to an absolute filename.
QString getIOMapName(int _inId) const
get corresponding output name of an input id
static QString getPathName(QString _strFileName)
returns path to _strFileName without last slash
static ShaderModifier * loadFromFile(QString _filename)
Load a modifier from file.
void addInput(const QString &_input)
Add one GLSL input specifier.
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
virtual void modifyVertexIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the vertex shader.
virtual void modifyGeometryIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the geometry shader.
bool openGLVersion(const int _major, const int _minor)
void modifyTessEvalIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation evaluation shader.
void generateShaders()
Generates the shader code.
void setGLSLVersion(int _version)
Set glsl version.
int getNumInputs() const
get number of inputs
void addOutput(const QString &_output)
Add one GLSL output specifier.
void saveToFile(const char *_fileName)
Save generated shader code to text file.
ShaderGenerator::DefaultIODesc ioDesc_
default IO descriptor for the vertex shader
void addMacros(const QStringList &_macros)
Add a list of preprocessor macros.
QString toString() const
convert ShaderGenDesc to string format for debugging
void loadShaderTemplateFromFile()
Loads external shader templates.
void initTessEvalShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting tess-evaluation shader io for a given description.
bool hasTessControlShader() const
check whether there is a tess-control shader present
virtual void modifyTessEvalIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation evaluation shader.
bool hasDefine(QString _define) const
Check for define.
bool passPosVS_
default attributes that should be passed down from vertex shader
void modifyLightingCode(QStringList *_code, ShaderModifier *_modifier)
Calls lighting modifier for each light.
void addIncludeFile(QString _fileName)
Imports another shader, same as #include.
QString vertexColorsInterpolator
interpolation qualifier for input vertex colors: "flat", "smooth", "noperspective" ...
int checkForIncludes(QString _str, ShaderGenerator *_gen, QString _includePath)
bool inputTexCoord_
default attributes that should be imported in vertex shader
const QStringList & getShaderCode()
Get result of buildShaderCode.
void addStringToList(QString _str, QStringList *_list, QString _prefix="", QString _postfix="")
void initFragmentShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting fragment shader io for a given description.
bool outputArrays_
outputs of shader are arrays (tess-control)
virtual void modifyLightingCode(QStringList *_code, int _lightId, ShaderGenLightType _lightType)
Modify the default lighting code of the shader generator.
bool inputArrays_
inputs of shader are arrays (tess-control, tess-eval, geometry)
void initDefaultUniforms()
Adds frequently used uniform parameters.
static bool loadStringListFromFile(QString _fileName, QStringList *_out)
Load a text file as string list.
void initTessControlShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting tess-control shader io for a given description.
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
std::map< size_t, TextureType > textureTypes_
holds the texture types (second) and the stage id (first). if empty, shader does not support textures...
static void setShaderDir(QString _dir)
void modifyVertexIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the vertex shader.
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
void addLightingFunctions(QStringList *_code)
Adds lighting definition functions.
bool renormalizeLighting_
renormalize before lighting, default false, can be activated via "#define SG_REQUEST_RENORMALIZE" ...
void scanShaderTemplate(QStringList &_templateSrc, QString _templateFilename, QStringList *_outLayoutDirectives=0)
Scans loaded shader template for requested inputs, glsl version or includes.
void addTexGenCode(QStringList *_code, bool _fragmentShader)
Add texture coordinate generation code.
QString getInputName(int _id) const
get variable name of input
int getNumActiveModifiers() const
Get the number of active modifiers.
void addLightingCode(QStringList *_code)
Adds lighting function calls to code.
void initGeometryShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting geometry shader io for a given description.
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void modifyGeometryIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the geometry shader.
QString inputPrefix_
prefix of inputs to this shader, same as prefix of ouputs of previous stage
void modifyVertexBeginCode(QStringList *_code)
Append code the the vertex shader.
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
void modifyVertexEndCode(QStringList *_code)
Append code the the vertex shader.
void initGenDefines(ShaderGenerator *_gen)
provide generated defines to shader
static QString getShaderDir()
void addLayout(QString _layout)
Add a layout directive.
bool hasGeometryShader() const
check whether there is a geometry shader present
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
virtual void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
void buildShaderCode(QStringList *_pMainCode, const QStringList &_defaultLightingFunctions)
Shader assembly function.
QString vertexShaderFile_
path + filename to shader templates