44 #include <ACG/GL/acg_glew.hh> 45 #include "ShaderGenerator.hh" 52 #include <QTextStream> 60 std::vector<ShaderModifier*> ShaderProgGenerator::registeredModifiers_;
70 ShaderGenerator::Keywords::Keywords()
72 : macro_requestPosVS(
"#define SG_REQUEST_POSVS"),
73 macro_requestPosOS(
"#define SG_REQUEST_POSOS"),
74 macro_requestTexcoord(
"#define SG_REQUEST_TEXCOORD"),
75 macro_requestVertexColor(
"#define SG_REQUEST_VERTEXCOLOR"),
76 macro_requestNormalVS(
"#define SG_REQUEST_NORMALVS"),
77 macro_requestNormalOS(
"#define SG_REQUEST_NORMALOS"),
81 macro_inputPosVS(
"SG_INPUT_POSVS"),
82 macro_inputPosOS(
"SG_INPUT_POSOS"),
83 macro_inputPosCS(
"SG_INPUT_POSCS"),
84 macro_inputNormalVS(
"SG_INPUT_NORMALVS"),
85 macro_inputNormalOS(
"SG_INPUT_NORMALOS"),
86 macro_inputTexcoord(
"SG_INPUT_TEXCOORD"),
87 macro_inputVertexColor(
"SG_INPUT_VERTEXCOLOR"),
89 macro_outputPosVS(
"SG_OUTPUT_POSVS"),
90 macro_outputPosOS(
"SG_OUTPUT_POSOS"),
91 macro_outputPosCS(
"SG_OUTPUT_POSCS"),
92 macro_outputNormalVS(
"SG_OUTPUT_NORMALVS"),
93 macro_outputNormalOS(
"SG_OUTPUT_NORMALOS"),
94 macro_outputTexcoord(
"SG_OUTPUT_TEXCOORD"),
95 macro_outputVertexColor(
"SG_OUTPUT_VERTEXCOLOR"),
100 ioNormalVS(
"NormalVS"),
101 ioNormalOS(
"NormalOS"),
102 ioTexcoord(
"TexCoord"),
105 vs_inputPrefix(
"in"),
106 vs_outputPrefix(
"outVertex"),
107 tcs_outputPrefix(
"outTc"),
108 tes_outputPrefix(
"outTe"),
109 gs_outputPrefix(
"outGeometry"),
110 fs_outputPrefix(
"outFragment"),
112 vs_inputPosition(vs_inputPrefix +
"Position"),
113 vs_inputNormal(vs_inputPrefix +
"Normal"),
114 vs_inputTexCoord(vs_inputPrefix + ioTexcoord),
115 vs_inputColor(vs_inputPrefix + ioColor),
117 vs_outputPosCS(vs_outputPrefix + ioPosCS),
118 vs_outputPosVS(vs_outputPrefix + ioPosVS),
119 vs_outputPosOS(vs_outputPrefix + ioPosOS),
120 vs_outputTexCoord(vs_outputPrefix + ioTexcoord),
121 vs_outputNormalVS(vs_outputPrefix + ioNormalVS),
122 vs_outputNormalOS(vs_outputPrefix + ioNormalOS),
123 vs_outputVertexColor(vs_outputPrefix + ioColor),
124 fs_outputFragmentColor(fs_outputPrefix)
128 const ShaderGenerator::Keywords ShaderGenerator::keywords;
131 ShaderGenerator::ShaderGenerator()
132 : version_(150), inputArrays_(false), outputArrays_(false)
136 ShaderGenerator::~ShaderGenerator()
145 inputArrays_ =
false;
146 outputArrays_ =
false;
147 inputPrefix_ = keywords.vs_inputPrefix;
148 outputPrefix_ = keywords.vs_outputPrefix;
150 addInput(
"vec4", keywords.vs_inputPosition);
151 addOutput(
"vec4", keywords.vs_outputPosCS);
153 if (_iodesc->inputNormal_)
154 addInput(
"vec3", keywords.vs_inputNormal);
156 if (_desc->textured())
158 std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = _desc->textureTypes().begin();
161 if (iter->second.type == GL_TEXTURE_3D) {
162 addInput(
"vec3", keywords.vs_inputTexCoord);
163 addOutput(
"vec3", keywords.vs_outputTexCoord);
165 addInput(
"vec2", keywords.vs_inputTexCoord);
166 addOutput(
"vec2", keywords.vs_outputTexCoord);
170 if (_iodesc->inputColor_)
171 addInput(
"vec4", keywords.vs_inputColor);
173 if (_iodesc->passNormalVS_)
176 if (_iodesc->passNormalOS_)
184 if (_desc->shadeMode == SG_SHADE_FLAT)
186 if (!_desc->geometryTemplateFile.isEmpty())
187 strColorOut = keywords.vs_outputVertexColor;
191 addStringToList(
"vec4 " + keywords.vs_outputVertexColor, &outputs_,
"flat out ",
"; ");
194 else if (_desc->shadeMode == SG_SHADE_GOURAUD || _desc->vertexColors || _iodesc->inputColor_)
195 strColorOut = keywords.vs_outputVertexColor;
197 if (strColorOut.size())
198 addOutput(
"vec4", strColorOut);
201 addStringToList(
"vec4 " + keywords.vs_outputVertexColor, &outputs_, _desc->vertexColorsInterpolator +
" out ",
";");
207 if (_iodesc->passPosVS_)
208 addOutput(
"vec4", keywords.vs_outputPosVS);
210 if (_iodesc->passPosOS_)
211 addOutput(
"vec4", keywords.vs_outputPosOS);
213 if (_iodesc->passTexCoord_ && !_desc->textured())
218 if (_desc->texGenMode && _desc->texGenDim > 0 && _desc->texGenDim <= 4 && !_desc->texGenPerFragment)
219 texdim = _desc->texGenDim;
221 QString texcoordType;
223 texcoordType.sprintf(
"vec%i", texdim);
225 texcoordType =
"float";
227 addInput(texcoordType, keywords.vs_inputTexCoord);
228 addOutput(texcoordType, keywords.vs_outputTexCoord);
232 defineIOAbstraction(_iodesc,
true,
false);
239 outputArrays_ =
true;
241 outputPrefix_ = keywords.tcs_outputPrefix;
243 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
245 defineIOAbstraction(_iodesc,
false,
false);
252 outputArrays_ =
false;
254 outputPrefix_ = keywords.tes_outputPrefix;
256 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
258 defineIOAbstraction(_iodesc,
false,
false);
265 outputArrays_ =
false;
267 outputPrefix_ = keywords.gs_outputPrefix;
269 matchInputs(_prevStage,
true, inputPrefix_, outputPrefix_);
271 defineIOAbstraction(_iodesc,
false,
false);
279 inputArrays_ =
false;
280 outputArrays_ =
false;
282 outputPrefix_ = keywords.fs_outputPrefix;
284 matchInputs(_prevStage,
false);
285 addOutput(
"vec4", keywords.fs_outputFragmentColor);
287 defineIOAbstraction(_iodesc,
false,
true);
297 addIODefine(keywords.macro_inputPosOS, keywords.vs_inputPosition);
300 addIODefine(keywords.macro_inputTexcoord, keywords.vs_inputTexCoord);
302 if (_iodesc->inputNormal_)
303 addIODefine(keywords.macro_inputNormalOS, keywords.vs_inputNormal);
305 if (_iodesc->inputColor_)
306 addIODefine(keywords.macro_inputVertexColor, keywords.vs_inputColor);
312 addIODefine(keywords.macro_outputPosCS, keywords.vs_outputPosCS);
315 addIODefine(keywords.macro_outputPosVS, keywords.vs_outputPosVS);
317 if (_iodesc->passPosOS_)
318 addIODefine(keywords.macro_outputPosOS, keywords.vs_outputPosOS);
320 if (_iodesc->passTexCoord_)
321 addIODefine(keywords.macro_outputTexcoord, keywords.vs_outputTexCoord);
323 if (_iodesc->passNormalVS_)
324 addIODefine(keywords.macro_outputNormalVS, keywords.vs_outputNormalVS);
326 if (_iodesc->passNormalOS_)
327 addIODefine(keywords.macro_outputNormalOS, keywords.vs_outputNormalOS);
329 if (_iodesc->passColor_)
330 addIODefine(keywords.macro_outputVertexColor, keywords.vs_outputVertexColor);
336 addIODefine(keywords.macro_inputPosVS, inputPrefix_ + keywords.ioPosVS);
338 addIODefine(keywords.macro_outputPosVS, outputPrefix_ + keywords.ioPosVS);
341 if (_iodesc->passPosOS_)
343 addIODefine(keywords.macro_inputPosOS, inputPrefix_ + keywords.ioPosOS);
345 addIODefine(keywords.macro_outputPosOS, outputPrefix_ + keywords.ioPosOS);
348 addIODefine(keywords.macro_inputPosCS, inputPrefix_ + keywords.ioPosCS);
350 addIODefine(keywords.macro_outputPosCS, outputPrefix_ + keywords.ioPosCS);
352 if (_iodesc->passNormalVS_)
354 addIODefine(keywords.macro_inputNormalVS, inputPrefix_ + keywords.ioNormalVS);
356 addIODefine(keywords.macro_outputNormalVS, outputPrefix_ + keywords.ioNormalVS);
359 if (_iodesc->passNormalOS_)
361 addIODefine(keywords.macro_inputNormalOS, inputPrefix_ + keywords.ioNormalOS);
363 addIODefine(keywords.macro_outputNormalOS, outputPrefix_ + keywords.ioNormalOS);
366 if (_iodesc->passTexCoord_)
368 addIODefine(keywords.macro_inputTexcoord, inputPrefix_ + keywords.ioTexcoord);
370 addIODefine(keywords.macro_outputTexcoord, outputPrefix_ + keywords.ioTexcoord);
373 if (_iodesc->passColor_)
375 addIODefine(keywords.macro_inputVertexColor, inputPrefix_ + keywords.ioColor);
377 addIODefine(keywords.macro_outputVertexColor, outputPrefix_ + keywords.ioColor);
388 addUniform(
"mat4 g_mWVP" ,
" // Projection * Modelview");
389 addUniform(
"mat4 g_mWV" ,
" // Modelview matrix");
390 addUniform(
"mat3 g_mWVIT" ,
" // Modelview inverse transposed");
391 addUniform(
"mat4 g_mP",
" // Projection matrix");
393 addUniform(
"vec3 g_vCamPos");
394 addUniform(
"vec3 g_vCamDir");
396 addUniform(
"vec3 g_cDiffuse");
397 addUniform(
"vec3 g_cAmbient");
398 addUniform(
"vec3 g_cEmissive");
399 addUniform(
"vec3 g_cSpecular");
400 addUniform(
"vec4 g_vMaterial");
401 addUniform(
"vec3 g_cLightModelAmbient");
405 #define ADDLIGHT(x) (sz.sprintf(x"_%d", lightIndex_), addUniform(sz)) 411 ADDLIGHT(
"vec3 g_cLightDiffuse");
412 ADDLIGHT(
"vec3 g_cLightAmbient");
413 ADDLIGHT(
"vec3 g_cLightSpecular");
415 if (_light == SG_LIGHT_POINT ||
416 _light == SG_LIGHT_SPOT)
418 ADDLIGHT(
"vec3 g_vLightPos");
419 ADDLIGHT(
"vec3 g_vLightAtten");
422 if (_light == SG_LIGHT_DIRECTIONAL ||
423 _light == SG_LIGHT_SPOT)
424 ADDLIGHT(
"vec3 g_vLightDir");
427 if (_light == SG_LIGHT_SPOT)
428 ADDLIGHT(
"vec2 g_vLightAngleExp");
441 if (!_str.startsWith(_prefix))
444 if (!_str.endsWith(_postfix))
449 tmp = tmp.simplified();
452 if (!_arr->contains(tmp))
453 _arr->push_back(tmp);
460 addStringToList(_input, &inputs_,
"in ",
";");
466 addStringToList(_output, &outputs_,
"out ",
";");
472 addStringToList(_def, &genDefines_,
"#define ");
478 addDefine(_macroName + QString(
" ") + _resolvedName);
486 typedef std::reverse_iterator<QStringList::const_iterator> QStringListReverseIterator;
487 QStringListReverseIterator rbegin( _macros.end() ), rend( _macros.begin() );
489 for (QStringListReverseIterator it = rbegin; it != rend; ++it)
490 genDefines_.push_front(*it);
495 if (genDefines_.contains(_define))
500 QString trimmedDef = _define.trimmed();
502 for (QStringList::const_iterator it = genDefines_.constBegin(); it != genDefines_.constEnd(); ++it)
504 QString trimmedRef = it->trimmed();
506 if (trimmedRef.startsWith(trimmedDef))
511 for (QStringList::const_iterator it = rawIO_.constBegin(); it != rawIO_.constEnd(); ++it)
513 QString trimmedRef = it->trimmed();
515 if (trimmedRef.startsWith(trimmedDef))
524 addStringToList(_def, &layouts_);
531 if (!_uniform.startsWith(
"uniform ") && !_uniform.contains(
" uniform "))
534 addStringToList(_uniform, &uniforms_, prefix,
"; " + _comment );
547 if (!it.contains(
";"))
548 code_.back().append(
";");
557 glslversion.sprintf(
"#version %d", version_);
559 code_.push_back(glslversion);
564 foreach(it, genDefines_)
568 foreach(it, layouts_)
572 addIOToCode(inputs_);
573 addIOToCode(outputs_);
574 addIOToCode(uniforms_);
577 bool requiresLightingCode =
false;
580 foreach(it, imports_)
582 if (it.contains(
"LitDirLight") || it.contains(
"LitPointLight") || it.contains(
"LitSpotLight"))
583 requiresLightingCode =
true;
586 if (requiresLightingCode)
588 foreach(it, _defaultLightingFunctions)
593 foreach(it, imports_)
599 if (!requiresLightingCode)
601 foreach(it, (*_pMainCode))
603 if (it.contains(
"LitDirLight") || it.contains(
"LitPointLight") || it.contains(
"LitSpotLight"))
604 requiresLightingCode =
true;
607 if (requiresLightingCode)
609 foreach(it, _defaultLightingFunctions)
616 code_.append(rawIO_);
620 foreach(it, (*_pMainCode))
628 QFile file(_fileName);
630 if (file.open(QIODevice::ReadOnly | QIODevice::Text))
632 QTextStream fileStream(&file);
636 imports_.push_back(
"// ==============================================================================");
637 imports_.push_back(QString(
"// ShaderGenerator - begin of imported file: ") + _fileName);
640 while (!fileStream.atEnd())
642 QString tmpLine = fileStream.readLine();
644 imports_.push_back(tmpLine.simplified());
650 imports_.push_back(QString(
"// ShaderGenerator - end of imported file #include \"") + _fileName);
651 imports_.push_back(
"// ==============================================================================");
661 QFile file(_fileName);
662 if (file.open(QIODevice::WriteOnly | QIODevice::Text))
664 QTextStream fileStream(&file);
668 fileStream << it <<
'\n';
685 bool _passToNextStage,
686 QString _inputPrefix,
687 QString _outputPrefix)
689 if (!_previousShaderStage)
691 std::cout <<
"error: ShaderGenerator::matchInputs called without providing input stage" << std::endl;
696 foreach(it, _previousShaderStage->outputs_)
700 QString outKeyword =
"out ";
701 QString inKeyword =
"in ";
704 input.replace(input.indexOf(outKeyword), outKeyword.size(), inKeyword);
710 QRegExp alphaNum(
"[a-zA-Z0-9]");
711 int lastNameChar = input.lastIndexOf(alphaNum);
712 input.insert(lastNameChar+1,
"[]");
718 addStringToList(input, &inputs_);
720 if (_passToNextStage)
724 QString output = input;
725 output.replace(output.indexOf(_inputPrefix), _inputPrefix.size(), _outputPrefix);
726 output.replace(output.indexOf(inKeyword), inKeyword.size(), outKeyword);
729 if (inputArrays_ && !outputArrays_)
731 int bracketStart = output.indexOf(
"[");
732 int bracketEnd = output.indexOf(
"]");
733 output.remove(bracketStart, bracketEnd-bracketStart+1);
735 else if (!inputArrays_ && outputArrays_)
737 QRegExp alphaNum(
"[a-zA-Z0-9]");
738 int lastNameChar = output.lastIndexOf(alphaNum);
739 output.insert(lastNameChar+1,
"[]");
745 addStringToList(output, &outputs_);
752 return outputs_.size();
757 QString output = outputs_.at(_id);
760 output.remove(
"out ");
762 int bracketStart = output.indexOf(
"[");
763 int bracketEnd = output.lastIndexOf(
"]");
765 if (bracketStart >= 0)
766 output.remove(bracketStart, bracketEnd-bracketStart+1);
769 QStringList decompOutput = output.split(
" ");
770 return decompOutput.last();
775 return inputs_.size();
780 QString input = inputs_.at(_id);
783 input.remove(
"out ");
785 int bracketStart = input.indexOf(
"[");
786 int bracketEnd = input.lastIndexOf(
"]");
788 if (bracketStart >= 0)
789 input.remove(bracketStart, bracketEnd-bracketStart+1);
792 QStringList decompInput = input.split(
" ");
793 return decompInput.last();
798 QString inputName = getInputName(_inId);
801 QString outputName = inputName;
802 outputName.replace(outputName.indexOf(inputPrefix_), inputPrefix_.size(), outputPrefix_);
808 ShaderGenerator::DefaultIODesc::DefaultIODesc()
809 : inputTexCoord_(
false),
812 passPosVS_(
false), passPosOS_(
false),
813 passTexCoord_(
false),
815 passNormalVS_(
false), passNormalOS_(
false)
822 QString ShaderProgGenerator::shaderDir_;
823 QStringList ShaderProgGenerator::lightingCode_;
827 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
833 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
835 init(_desc, _modifierIDs, _numActiveMods);
839 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
841 init(_desc, _modifierIDs.empty() ? 0 : &_modifierIDs[0], (
unsigned int)_modifierIDs.size());
845 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
847 unsigned int numMods = !_modifierIDs || _modifierIDs->empty() ? 0 : (
unsigned int)_modifierIDs->size();
848 init(_desc, numMods ? &((*_modifierIDs)[0]) : 0, numMods);
852 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
854 init(_desc, _modifiers, _numActiveMods);
858 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
860 init(_desc, _modifierIDs.empty() ? 0 : &(_modifierIDs[0]), (
unsigned int)_modifierIDs.size());
864 : vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0)
866 unsigned int numMods = !_modifierIDs || _modifierIDs->empty() ? 0 : (
unsigned int)_modifierIDs->size();
867 init(_desc, numMods ? &((*_modifierIDs)[0]) : 0, numMods);
873 if (_modifierIDs && _numActiveMods)
875 activeMods_.resize(_numActiveMods);
877 for (
unsigned int i = 0; i < _numActiveMods; ++i)
878 activeMods_[i] = registeredModifiers_[ _modifierIDs[i] ];
889 size_t numDescMods = _desc->shaderMods.size();
890 size_t numTotalMods = _numActiveMods + numDescMods;
893 activeMods_.resize(numTotalMods);
895 for (
size_t i = 0; i < numDescMods; ++i)
897 unsigned int modID = _desc->shaderMods[i];
898 activeMods_[i] = registeredModifiers_[modID];
901 if (_modifiers && _numActiveMods)
903 for (
unsigned int i = 0; i < _numActiveMods; ++i)
904 activeMods_[i + numDescMods] = _modifiers[i];
911 if (shaderDir_.isEmpty())
912 std::cout <<
"error: call ShaderProgGenerator::setShaderDir() first!" << std::endl;
920 if (!desc_.geometryTemplateFile.isEmpty())
921 std::cerr <<
"Warning: removing geometry shader from ShaderDesc" << std::endl;
923 desc_.geometryTemplateFile.clear();
929 if (!desc_.tessControlTemplateFile.isEmpty() || !desc_.tessEvaluationTemplateFile.isEmpty())
930 std::cerr <<
"Warning: removing tessellation shader from ShaderDesc" << std::endl;
932 desc_.tessControlTemplateFile.clear();
933 desc_.tessEvaluationTemplateFile.clear();
938 if (!desc_.geometryTemplateFile.isEmpty())
939 desc_.version = std::max(desc_.version, 150);
941 if (!desc_.tessControlTemplateFile.isEmpty() || !desc_.tessEvaluationTemplateFile.isEmpty())
942 desc_.version = std::max(desc_.version, 400);
945 loadLightingFunctions();
952 ShaderProgGenerator::~ShaderProgGenerator(
void)
965 bool success =
false;
970 QFile file(absFilename);
972 if (file.open(QIODevice::ReadOnly | QIODevice::Text))
974 if (!file.isReadable())
975 std::cout <<
"error: unreadable file -> \"" << absFilename.toStdString() <<
"\"" << std::endl;
978 QTextStream filestream(&file);
980 while (!filestream.atEnd())
982 QString szLine = filestream.readLine();
983 _out->push_back(szLine.trimmed());
992 std::cout <<
"error: " << file.errorString().toStdString() <<
" -> \"" << absFilename.toStdString() <<
"\"" << std::endl;
998 void ShaderProgGenerator::loadLightingFunctions()
1000 if (lightingCode_.size())
return;
1002 static const QString lightingCodeFile =
"ShaderGen/SG_LIGHTING.GLSL";
1004 QString fileName = shaderDir_ + QDir::separator() + QString(lightingCodeFile);
1006 lightingCode_.push_back(
"// ==============================================================================");
1007 lightingCode_.push_back(QString(
"// ShaderGenerator - default lighting functions imported from file: ") + fileName);
1013 lightingCode_.push_back(QString(
"// ShaderGenerator - end of default lighting functions"));
1014 lightingCode_.push_back(
"// ==============================================================================");
1021 switch (desc_.shadeMode)
1023 case SG_SHADE_GOURAUD:
1027 case SG_SHADE_UNLIT:
1029 case SG_SHADE_PHONG:
1033 std::cout << __FUNCTION__ <<
" -> unknown shade mode: " << desc_.shadeMode << std::endl;
1036 if (desc_.twoSidedLighting)
1037 _gen->
addDefine(
"TWO_SIDED_LIGHTING 1");
1039 if (desc_.textured())
1042 if (desc_.vertexColors)
1056 QString strNumLights;
1057 strNumLights.sprintf(
"SG_NUM_LIGHTS %d", desc_.numLights);
1061 const char* lightTypeNames[] = {
"SG_LIGHT_DIRECTIONAL",
1062 "SG_LIGHT_POINT",
"SG_LIGHT_SPOT"};
1064 for (
int i = 0; i < 3; ++i)
1068 for (
int i = 0; i < desc_.numLights; ++i)
1070 QString strLightType;
1071 strLightType.sprintf(
"SG_LIGHT_TYPE_%d %s", i, lightTypeNames[desc_.lightTypes[i]]);
1075 _gen->
addDefine(
"SG_ALPHA g_vMaterial.y");
1076 _gen->
addDefine(
"SG_MINALPHA g_vMaterial.z");
1085 void ShaderProgGenerator::buildVertexShader()
1097 if (desc_.texGenDim && (desc_.texGenMode == GL_OBJECT_LINEAR || desc_.texGenMode == GL_EYE_LINEAR) && !desc_.texGenPerFragment)
1100 QString uniformDecl =
"vec4 g_vTexGenPlane";
1101 if (desc_.texGenDim > 1)
1102 uniformDecl +=
"[" + QString::number(desc_.texGenDim) +
"]";
1103 vertex_->
addUniform(uniformDecl,
" // texture projection planes");
1108 for (
size_t i = 0; i < activeMods_.size(); ++i)
1109 activeMods_[i]->modifyVertexIO(vertex_);
1119 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1120 desc_.shadeMode == SG_SHADE_FLAT)
1122 for (
int i = 0; i < desc_.numLights; ++i)
1123 vertex_->
addLight(i, desc_.lightTypes[i]);
1128 QStringList mainCode;
1130 if (!vertexTemplate_.size())
1132 mainCode.push_back(
"void main()");
1133 mainCode.push_back(
"{");
1135 addVertexBeginCode(&mainCode);
1136 addVertexEndCode(&mainCode);
1138 mainCode.push_back(
"}");
1146 foreach(it,vertexTemplate_)
1153 if (it.contains(
"SG_VERTEX_BEGIN"))
1154 addVertexBeginCode(&mainCode);
1157 if (it.contains(
"SG_VERTEX_END"))
1158 addVertexEndCode(&mainCode);
1162 mainCode.push_back(it);
1176 void ShaderProgGenerator::addVertexBeginCode(QStringList* _code)
1180 _code->push_back(QString(
"vec4 sg_vPosPS = g_mWVP * ") + ShaderGenerator::keywords.macro_inputPosOS + QString(
";"));
1181 _code->push_back(
"vec4 sg_vPosVS = g_mWV * inPosition;");
1182 _code->push_back(
"vec3 sg_vNormalVS = vec3(0.0, 1.0, 0.0);");
1183 _code->push_back(
"vec3 sg_vNormalOS = vec3(0.0, 1.0, 0.0);");
1185 if (desc_.vertexColors && (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE))
1186 _code->push_back(QString(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * ")
1187 + ShaderGenerator::keywords.macro_inputVertexColor
1188 + QString(
".rgb, SG_ALPHA * ")
1189 + ShaderGenerator::keywords.macro_inputVertexColor
1192 _code->push_back(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * g_cAmbient, SG_ALPHA);");
1196 _code->push_back(
"sg_vNormalVS = normalize(g_mWVIT * inNormal);");
1197 _code->push_back(
"sg_vNormalOS = normalize(inNormal);");
1200 if (
ioDesc_.inputColor_ && (desc_.shadeMode == SG_SHADE_UNLIT || desc_.colorMaterialMode == GL_EMISSION))
1201 _code->push_back(QString(
"sg_cColor = ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
";"));
1208 for (
size_t i = 0; i < activeMods_.size(); ++i)
1209 activeMods_[i]->modifyVertexBeginCode(_code);
1213 void ShaderProgGenerator::addVertexEndCode(QStringList* _code)
1215 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1216 desc_.shadeMode == SG_SHADE_FLAT)
1223 _code->push_back(
"gl_Position = sg_vPosPS;");
1224 _code->push_back(
"outVertexPosCS = sg_vPosPS;");
1227 _code->push_back(
"outVertexTexCoord = sg_vTexCoord;");
1230 _code->push_back(
"outVertexColor = sg_cColor;");
1233 _code->push_back(ShaderGenerator::keywords.macro_outputNormalVS + QString(
" = sg_vNormalVS;"));
1236 _code->push_back(ShaderGenerator::keywords.macro_outputNormalOS + QString(
" = sg_vNormalOS;"));
1239 _code->push_back(ShaderGenerator::keywords.macro_outputPosVS + QString(
" = sg_vPosVS;"));
1242 _code->push_back(ShaderGenerator::keywords.macro_outputPosOS + QString(
" = ") + ShaderGenerator::keywords.macro_inputPosOS + QString(
";"));
1247 for (
size_t i = 0; i < activeMods_.size(); ++i)
1248 activeMods_[i]->modifyVertexEndCode(_code);
1254 if (_str.contains(
"#include "))
1256 QString strIncludeFile = _str.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
1258 if (strIncludeFile.isEmpty())
1259 std::cout <<
"wrong include syntax: " << _str.toStdString() << std::endl;
1262 QString fullPathToIncludeFile = _includePath + QDir::separator() + strIncludeFile;
1275 if (_str.contains(
"#include "))
1277 QString strIncludeFile = _str.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
1279 if (strIncludeFile.isEmpty())
1280 std::cout <<
"wrong include syntax: " << _str.toStdString() << std::endl;
1283 QString fullPathToIncludeFile = _includePath + QDir::separator() + strIncludeFile;
1286 fullPathToIncludeFile.replace(
'\\',
'/');
1289 QString cleanFilepath = QDir::cleanPath(fullPathToIncludeFile);
1300 void ShaderProgGenerator::buildTessControlShader()
1303 if ( desc_.tessControlTemplateFile.isEmpty() )
1313 delete tessControl_;
1331 for (
size_t i = 0; i < activeMods_.size(); ++i)
1332 activeMods_[i]->modifyTessControlIO(tessControl_);
1339 QStringList mainCode;
1345 mainCode.push_back(
"#define sg_MapIO(inIdx) do {\\");
1348 mainCode.push_back(
"gl_out[gl_InvocationID].gl_Position = gl_in[inIdx].gl_Position;\\");
1356 QString outputAssignCode = outputName + QString(
"[gl_InvocationID] = ") + inputName + QString(
"[inIdx];\\");
1358 mainCode.push_back(outputAssignCode);
1362 mainCode.push_back(
"} while(false)");
1368 foreach(it,tessControlTemplate_)
1373 mainCode.push_back(it);
1380 void ShaderProgGenerator::buildTessEvalShader()
1383 if ( desc_.tessEvaluationTemplateFile.isEmpty() )
1404 prevStage = vertex_;
1411 foreach(itLayout, tessEvalLayout_)
1415 for (
size_t i = 0; i < activeMods_.size(); ++i)
1416 activeMods_[i]->modifyTessControlIO(tessEval_);
1422 QStringList mainCode;
1429 mainCode.push_back(
"void sg_MapIOBarycentric()");
1430 mainCode.push_back(
"{");
1433 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;");
1441 QString outputAssignCode = outputName + QString(
" = ") +
1442 QString(
"gl_TessCoord.x*") + inputName + QString(
"[0] + ") +
1443 QString(
"gl_TessCoord.y*") + inputName + QString(
"[1] + ") +
1444 QString(
"gl_TessCoord.z*") + inputName + QString(
"[2];");
1446 mainCode.push_back(outputAssignCode);
1449 mainCode.push_back(
"}");
1454 mainCode.push_back(
"void sg_MapIOBilinear()");
1455 mainCode.push_back(
"{");
1458 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);");
1466 QString outputAssignCode = outputName + QString(
" = mix( ") +
1467 QString(
"mix(") + inputName + QString(
"[0], ") + inputName + QString(
"[1], gl_TessCoord.x), ") +
1468 QString(
"mix(") + inputName + QString(
"[2], ") + inputName + QString(
"[3], gl_TessCoord.x), gl_TessCoord.y); ");
1470 mainCode.push_back(outputAssignCode);
1473 mainCode.push_back(
"}");
1479 QStringList::iterator it;
1480 for (it = tessEvalTemplate_.begin(); it != tessEvalTemplate_.end(); ++it)
1489 if (line.contains(
"SG_INPUT") || line.contains(
"SG_OUTPUT"))
1492 QStringList resolvedCode;
1494 resolvedCode.push_back(
"// ----------------------------------------");
1495 resolvedCode.push_back(
"// ShaderGen: resolve SG_OUTPUT = expression(SG_INPUT);");
1497 int numOccurrences = 0;
1505 QString resolvedLine = line;
1515 for (
int k = 0; k < 2; ++k)
1517 const QString stringToReplace = k ?
"SG_OUTPUT" :
"SG_INPUT";
1518 const int lenStringToReplace = stringToReplace.length();
1519 const QString replacementString = k ? outputName : inputName;
1521 int linePos = resolvedLine.indexOf(stringToReplace);
1523 while (linePos >= 0)
1525 bool replaceOcc =
true;
1527 int nextCharPos = linePos + lenStringToReplace;
1529 if (nextCharPos >= resolvedLine.size())
1532 if (nextCharPos > 0)
1534 QChar nextChar = resolvedLine.at(nextCharPos);
1536 if (nextChar ==
'_' || nextChar.isDigit() || nextChar.isLetter())
1540 linePos += lenStringToReplace;
1549 resolvedLine.replace(linePos, lenStringToReplace, replacementString);
1553 linePos = resolvedLine.indexOf(stringToReplace, linePos + 1);
1561 resolvedCode.push_back(resolvedLine);
1564 resolvedCode.push_back(
"// ----------------------------------------");
1567 mainCode.append(resolvedCode);
1569 mainCode.push_back(line);
1572 mainCode.push_back(line);
1578 void ShaderProgGenerator::buildGeometryShader()
1581 if ( desc_.geometryTemplateFile.isEmpty() )
1595 prevStage = vertex_;
1603 for (
size_t i = 0; i < activeMods_.size(); ++i)
1604 activeMods_[i]->modifyGeometryIO(geometry_);
1610 QStringList mainCode;
1616 mainCode.push_back(
"#define sg_MapIO(inIdx) do {\\");
1619 mainCode.push_back(
"gl_Position = gl_in[inIdx].gl_Position;\\");
1620 mainCode.push_back(
"gl_PrimitiveID = gl_PrimitiveIDIn;\\");
1624 static int maxClipDistances = -1;
1625 if (maxClipDistances < 0)
1627 #ifdef GL_MAX_CLIP_DISTANCES 1628 glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances);
1629 maxClipDistances = std::min(maxClipDistances, 32);
1631 maxClipDistances = 32;
1634 for (
int i = 0; i < maxClipDistances; ++i)
1636 if (desc_.clipDistanceMask & (1 << i))
1637 mainCode.push_back(QString(
"gl_ClipDistance[%1] = gl_in[inIdx].gl_ClipDistance[%1];\\").arg(i));
1646 QString outputAssignCode = outputName + QString(
" = ") + inputName + QString(
"[inIdx];\\");
1648 mainCode.push_back(outputAssignCode);
1652 mainCode.push_back(
"} while(false)");
1659 foreach(it,geometryTemplate_)
1664 mainCode.push_back(it);
1672 void ShaderProgGenerator::buildFragmentShader()
1683 prevStage = tessEval_;
1685 prevStage = tessControl_;
1687 prevStage = vertex_;
1692 if (desc_.texGenDim && (desc_.texGenMode == GL_OBJECT_LINEAR || desc_.texGenMode == GL_EYE_LINEAR) && desc_.texGenPerFragment)
1695 QString uniformDecl =
"vec4 g_vTexGenPlane";
1696 if (desc_.texGenDim > 1)
1697 uniformDecl +=
"[" + QString::number(desc_.texGenDim) +
"]";
1698 fragment_->
addUniform(uniformDecl,
" // texture projection planes");
1706 if (desc_.textured())
1708 for (std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = desc_.textureTypes().begin();
1709 iter != desc_.textureTypes().end(); ++iter)
1711 QString name = QString(
"g_Texture%1").arg(iter->first);
1713 switch (iter->second.type)
1715 case GL_TEXTURE_1D: type =
"sampler1D";
break;
1716 case GL_TEXTURE_2D: type =
"sampler2D";
break;
1717 case GL_TEXTURE_3D: type =
"sampler3D";
break;
1718 case GL_TEXTURE_CUBE_MAP: type =
"samplerCube";
break;
1719 #ifdef GL_ARB_texture_rectangle //ARCH_DARWIN doesn't support all texture defines with all xcode version (xcode 5.0 seems to support all) 1720 case GL_TEXTURE_RECTANGLE_ARB: type =
"sampler2DRect";
break;
1722 case GL_TEXTURE_BUFFER: type =
"samplerBuffer";
break;
1723 #ifdef GL_EXT_texture_array 1724 case GL_TEXTURE_1D_ARRAY_EXT: type =
"sampler1DArray";
break;
1725 case GL_TEXTURE_2D_ARRAY_EXT: type =
"sampler2DArray";
break;
1727 #ifdef GL_ARB_texture_cube_map_array 1728 case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: type =
"samplerCubeArray";
break;
1730 #ifdef GL_ARB_texture_multisample 1731 case GL_TEXTURE_2D_MULTISAMPLE: type =
"sampler2DMS";
break;
1732 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: type =
"sampler2DMSArray";
break;
1734 default: std::cerr <<
"Texture Type not supported "<< iter->second.type << std::endl;
break;
1737 if (iter->second.shadow)
1744 for (
size_t i = 0; i < activeMods_.size(); ++i)
1745 activeMods_[i]->modifyFragmentIO(fragment_);
1755 if (desc_.shadeMode == SG_SHADE_PHONG)
1757 for (
int i = 0; i < desc_.numLights; ++i)
1758 fragment_->
addLight(i, desc_.lightTypes[i]);
1762 QStringList mainCode;
1764 if (!fragmentTemplate_.size())
1766 mainCode.push_back(
"void main()");
1767 mainCode.push_back(
"{");
1769 addFragmentBeginCode(&mainCode);
1770 addFragmentEndCode(&mainCode);
1772 mainCode.push_back(
"}");
1779 foreach(it,fragmentTemplate_)
1786 if (it.contains(
"SG_FRAGMENT_BEGIN"))
1787 addFragmentBeginCode(&mainCode);
1788 else if (it.contains(
"SG_FRAGMENT_END"))
1789 addFragmentEndCode(&mainCode);
1790 else if (it.contains(
"SG_FRAGMENT_LIGHTING"))
1793 mainCode.push_back(it);
1808 void ShaderProgGenerator::addFragmentBeginCode(QStringList* _code)
1811 _code->push_back(QString(
"vec4 sg_vPosCS = ") + ShaderGenerator::keywords.macro_inputPosCS + QString(
";"));
1812 _code->push_back(
"vec2 sg_vScreenPos = sg_vPosCS.xy / sg_vPosCS.w * 0.5 + vec2(0.5, 0.5);");
1814 _code->push_back(QString(
"#ifdef ") + ShaderGenerator::keywords.macro_inputPosVS);
1815 _code->push_back(QString(
"vec4 sg_vPosVS = ") + ShaderGenerator::keywords.macro_inputPosVS + QString(
";"));
1816 _code->push_back(
"#endif");
1818 _code->push_back(QString(
"#ifdef ") + ShaderGenerator::keywords.macro_inputNormalVS);
1819 _code->push_back(QString(
"vec3 sg_vNormalVS = ") + ShaderGenerator::keywords.macro_inputNormalVS + QString(
";"));
1820 _code->push_back(
"sg_vNormalVS = normalize(sg_vNormalVS);");
1821 _code->push_back(
"#endif");
1824 if (desc_.vertexColors && (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE))
1825 _code->push_back(QString(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * ")
1826 + ShaderGenerator::keywords.macro_inputVertexColor
1827 + QString(
".rgb, SG_ALPHA * ")
1828 + ShaderGenerator::keywords.macro_inputVertexColor
1831 _code->push_back(
"vec4 sg_cColor = vec4(g_cEmissive + g_cLightModelAmbient * g_cAmbient, SG_ALPHA);");
1833 if (desc_.shadeMode == SG_SHADE_GOURAUD ||
1834 desc_.shadeMode == SG_SHADE_FLAT ||
1835 (
ioDesc_.passColor_ && (desc_.shadeMode == SG_SHADE_UNLIT || desc_.colorMaterialMode == GL_EMISSION)))
1836 _code->push_back(QString(
"sg_cColor = ") + ShaderGenerator::keywords.macro_inputVertexColor + QString(
";"));
1838 _code->push_back(QString(
"if (sg_cColor.a < SG_MINALPHA) discard;"));
1839 if (desc_.shadeMode == SG_SHADE_PHONG)
1845 if (desc_.textured())
1847 std::map<size_t,ShaderGenDesc::TextureType>::const_iterator iter = desc_.textureTypes().begin();
1848 _code->push_back(
"vec4 sg_cTex = texture(g_Texture"+QString::number(iter->first)+
", sg_vTexCoord);");
1850 for (++iter; iter != desc_.textureTypes().end(); ++iter)
1851 _code->push_back(
"sg_cTex += texture(g_Texture"+QString::number(iter->first)+
", sg_vTexCoord);");
1854 _code->push_back(
"sg_cTex = sg_cTex * 1.0/" + QString::number(desc_.textureTypes().size()) +
".0 ;");
1856 if (desc_.shadeMode == SG_SHADE_UNLIT)
1857 _code->push_back(
"sg_cColor += sg_cTex;");
1859 _code->push_back(
"sg_cColor *= sg_cTex;");
1864 for (
size_t i = 0; i < activeMods_.size(); ++i)
1865 activeMods_[i]->modifyFragmentBeginCode(_code);
1868 void ShaderProgGenerator::addFragmentEndCode(QStringList* _code)
1870 _code->push_back(ShaderGenerator::keywords.fs_outputFragmentColor + QString(
" = sg_cColor;"));
1873 for (
size_t i = 0; i < activeMods_.size(); ++i)
1874 activeMods_[i]->modifyFragmentEndCode(_code);
1885 for (
size_t i = 0; i < activeMods_.size() && !lightingModifier; ++i)
1887 if (activeMods_[i]->replaceDefaultLightingCode())
1888 lightingModifier = activeMods_[i];
1891 if (!lightingModifier)
1897 QString vertexColorString = (
ioDesc_.inputColor_ &&
ioDesc_.passColor_) ? (ShaderGenerator::keywords.macro_inputVertexColor + QString(
".xyz * ")) :
"";
1898 QString diffuseVertexColor = (desc_.colorMaterialMode == GL_DIFFUSE || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE) ? vertexColorString :
"";
1899 QString ambientVertexColor = (desc_.colorMaterialMode == GL_AMBIENT || desc_.colorMaterialMode == GL_AMBIENT_AND_DIFFUSE) ? vertexColorString :
"";
1900 QString specularVertexColor = (desc_.colorMaterialMode == GL_SPECULAR) ? vertexColorString :
"";
1902 for (
int i = 0; i < desc_.numLights; ++i)
1904 ShaderGenLightType lgt = desc_.lightTypes[i];
1908 case SG_LIGHT_DIRECTIONAL:
1910 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);
1913 case SG_LIGHT_POINT:
1915 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);
1920 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);
1926 _code->push_back(buf);
1931 for (
size_t i = 0; i < activeMods_.size(); ++i)
1942 for (
size_t i = 0; i < activeMods_.size(); ++i)
1944 if (lightingModifier != activeMods_[i])
1953 if (!_modifier)
return;
1955 for (
int i = 0; i < desc_.numLights; ++i)
1957 ShaderGenLightType lgt = desc_.lightTypes[i];
1967 foreach(it,lightingCode_)
1968 _code->push_back(it);
1975 int texcoordVarDim = 2;
1977 !desc_.textureTypes().empty() &&
1978 desc_.textureTypes().begin()->second.type == GL_TEXTURE_3D)
1981 bool generateTexCoord = desc_.texGenDim && desc_.texGenMode && (_fragmentShader == desc_.texGenPerFragment);
1982 if (generateTexCoord)
1983 texcoordVarDim = desc_.texGenDim;
1985 QString texcoordVarInit;
1986 if (texcoordVarDim == 1)
1987 texcoordVarInit =
"float sg_vTexCoord";
1989 texcoordVarInit.sprintf(
"vec%i sg_vTexCoord", texcoordVarDim);
1993 texcoordVarInit += QString(
"= ") + ShaderGenerator::keywords.macro_inputTexcoord + QString(
";");
1994 else if (0 <= texcoordVarDim && texcoordVarDim <= 4)
1996 QString zeroVecDefs[] =
2004 texcoordVarInit += zeroVecDefs[texcoordVarDim];
2007 _code->push_back(texcoordVarInit);
2012 if (generateTexCoord)
2015 const char* texGenCoordString[] = {
"x",
"y",
"z",
"w" };
2017 switch (desc_.texGenMode)
2019 case GL_OBJECT_LINEAR:
2021 for (
int i = 0; i < desc_.texGenDim; ++i)
2023 QString assignmentInstrString;
2024 assignmentInstrString =
"sg_vTexCoord";
2025 if (desc_.texGenDim > 1)
2027 assignmentInstrString +=
".";
2028 assignmentInstrString += texGenCoordString[i];
2030 assignmentInstrString +=
" = dot(";
2031 assignmentInstrString += ShaderGenerator::keywords.macro_inputPosOS;
2032 assignmentInstrString +=
", g_vTexGenPlane";
2033 if (desc_.texGenDim > 1)
2035 assignmentInstrString +=
"[";
2036 assignmentInstrString += QString::number(i);
2037 assignmentInstrString +=
"]";
2039 assignmentInstrString +=
");";
2040 _code->push_back(assignmentInstrString);
2046 for (
int i = 0; i < desc_.texGenDim; ++i)
2048 QString assignmentInstrString;
2049 assignmentInstrString =
"sg_vTexCoord";
2050 if (desc_.texGenDim > 1)
2052 assignmentInstrString +=
".";
2053 assignmentInstrString += texGenCoordString[i];
2055 assignmentInstrString +=
" = dot(sg_vPosVS, g_vTexGenPlane";
2056 if (desc_.texGenDim > 1)
2058 assignmentInstrString +=
"[";
2059 assignmentInstrString += QString::number(i);
2060 assignmentInstrString +=
"]";
2062 assignmentInstrString +=
");";
2063 _code->push_back(assignmentInstrString);
2070 _code->push_back(
"vec3 sg_vPosVS_unit = normalize(sg_vPosVS.xyz);");
2071 _code->push_back(
"vec3 sg_TexGenRefl = reflect(sg_vPosVS_unit, sg_vNormalVS);");
2072 _code->push_back(
"vec3 sg_TexGenRefl2 = sg_TexGenRefl; sg_TexGenRefl2.z += 1.0;");
2073 _code->push_back(
"float sg_TexGenMRcp = 0.5 * inversesqrt(dot(sg_TexGenRefl2, sg_TexGenRefl2));");
2074 for (
int i = 0; i < desc_.texGenDim; ++i)
2076 QString assignmentInstrString;
2077 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_TexGenRefl.%s * sg_TexGenMRcp + 0.5;", texGenCoordString[i], texGenCoordString[i]);
2078 _code->push_back(assignmentInstrString);
2084 for (
int i = 0; i < desc_.texGenDim; ++i)
2086 QString assignmentInstrString;
2087 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_vNormalVS.%s;", texGenCoordString[i], texGenCoordString[i]);
2088 _code->push_back(assignmentInstrString);
2092 case GL_REFLECTION_MAP:
2094 _code->push_back(
"vec3 sg_vPosVS_unit = normalize(sg_vPosVS.xyz);");
2095 _code->push_back(
"vec3 sg_TexGenRefl = reflect(sg_vPosVS_unit, sg_vNormalVS);");
2096 for (
int i = 0; i < desc_.texGenDim; ++i)
2098 QString assignmentInstrString;
2099 assignmentInstrString.sprintf(
"sg_vTexCoord.%s = sg_TexGenRefl.%s;", texGenCoordString[i], texGenCoordString[i]);
2100 _code->push_back(assignmentInstrString);
2117 if (desc_.shadeMode != SG_SHADE_UNLIT)
2120 if (desc_.textured())
2127 int maxTexGenDim = 4;
2129 switch (desc_.texGenMode)
2132 case GL_OBJECT_LINEAR: maxTexGenDim = 4;
break;
2134 case GL_SPHERE_MAP: maxTexGenDim = 2;
break;
2137 case GL_REFLECTION_MAP: maxTexGenDim = 3;
break;
2139 default: maxTexGenDim = 0;
break;
2142 desc_.texGenDim = std::max(std::min(desc_.texGenDim, maxTexGenDim), 0);
2145 if (desc_.texGenDim && desc_.texGenMode)
2148 if (!desc_.texGenPerFragment)
2152 if (desc_.texGenMode == GL_REFLECTION_MAP || desc_.texGenMode == GL_SPHERE_MAP || desc_.texGenMode == GL_NORMAL_MAP)
2156 if (desc_.texGenPerFragment)
2158 switch (desc_.texGenMode)
2160 case GL_OBJECT_LINEAR:
ioDesc_.passPosOS_ =
true;
break;
2163 case GL_NORMAL_MAP:
ioDesc_.passNormalVS_ =
true;
break;
2171 if (desc_.vertexColors)
2174 if (desc_.shadeMode == SG_SHADE_PHONG)
2180 if (desc_.shadeMode == SG_SHADE_FLAT || desc_.shadeMode == SG_SHADE_GOURAUD || desc_.vertexColors)
2188 for (
size_t i = 0; i < activeMods_.size(); ++i)
2200 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestPosVS))
2202 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestTexcoord))
2207 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestVertexColor))
2212 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestNormalVS))
2217 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestNormalOS))
2222 if (dummy.
hasDefine(ShaderGenerator::keywords.macro_requestPosOS))
2231 buildVertexShader();
2232 buildTessControlShader();
2233 buildTessEvalShader();
2234 buildGeometryShader();
2235 buildFragmentShader();
2265 void ShaderProgGenerator::saveVertexShToFile(
const char* _fileName)
2270 void ShaderProgGenerator::saveGeometryShToFile(
const char* _fileName)
2275 void ShaderProgGenerator::saveFragmentShToFile(
const char* _fileName)
2283 if (!desc_.vertexTemplateFile.isEmpty())
2288 if (!desc_.fragmentTemplateFile.isEmpty())
2293 if (!desc_.geometryTemplateFile.isEmpty())
2298 if (!desc_.tessControlTemplateFile.isEmpty())
2303 if (!desc_.tessEvaluationTemplateFile.isEmpty())
2306 scanShaderTemplate(tessEvalTemplate_, desc_.tessEvaluationTemplateFile, &tessEvalLayout_);
2311 tessControlShaderFile_ = desc_.tessControlTemplateFile;
2312 tessEvalShaderFile_ = desc_.tessEvaluationTemplateFile;
2313 geometryShaderFile_ = desc_.geometryTemplateFile;
2314 fragmentShaderFile_ = desc_.fragmentTemplateFile;
2322 QString filePath =
getPathName(_templateFilename);
2324 QStringList::iterator it;
2325 for (it = _templateSrc.begin(); it != _templateSrc.end(); ++it)
2334 it = _templateSrc.erase(it);
2336 int offset = it - _templateSrc.begin();
2341 foreach(importLine,
import)
2343 it = _templateSrc.insert(it, importLine);
2349 it = _templateSrc.begin() + offset;
2353 QString trimmedLine = it->trimmed();
2356 QByteArray lineBytes = trimmedLine.toUtf8();
2358 if (trimmedLine.startsWith(
"#version "))
2360 QStringList tokens = trimmedLine.split(
' ');
2362 if (tokens.size() > 1)
2365 bool convOk =
false;
2366 int templateVersion = tokens.at(1).toInt(&convOk);
2370 desc_.version = std::max(templateVersion, desc_.version);
2373 it = _templateSrc.erase(it);
2378 else if (trimmedLine.startsWith(
"layout(") || trimmedLine.startsWith(
"layout ("))
2380 if (_outLayoutDirectives)
2382 _outLayoutDirectives->push_back(trimmedLine);
2385 it = _templateSrc.erase(it);
2392 if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestPosVS))
2394 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestTexcoord))
2399 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestVertexColor))
2404 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestNormalVS))
2409 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestNormalOS))
2414 else if (trimmedLine.startsWith(ShaderGenerator::keywords.macro_requestPosOS))
2416 else if (trimmedLine.startsWith(
"SG_FRAGMENT_LIGHTING"))
2420 desc_.shadeMode = SG_SHADE_PHONG;
2432 return fileInfo.absolutePath();
2437 QString absFilename;
2438 if ( QDir(_strFileName).isRelative() )
2439 absFilename =
getShaderDir() + QDir::separator() + _strFileName;
2441 absFilename = _strFileName;
2443 return QDir::cleanPath(absFilename);
2453 return shaderDir_ + QString(
"/");
2459 if (!_modifier)
return 0;
2464 if (registeredModifiers_[i] == _modifier)
2467 return registeredModifiers_[i]->getID();
2471 _modifier->modifierID_ = (
unsigned int)(numRegisteredModifiers_++);
2473 registeredModifiers_.push_back(_modifier);
2474 return _modifier->modifierID_;
2479 if (_i >= 0 && _i <=
int(activeMods_.size()))
2480 return activeMods_[_i];
2488 return int(activeMods_.size());
2494 return !desc_.geometryTemplateFile.isEmpty();
2499 return !desc_.tessControlTemplateFile.isEmpty();
2504 return !desc_.tessEvaluationTemplateFile.isEmpty();
2510 ShaderModifier::ShaderModifier(
void )
2514 ShaderModifier::~ShaderModifier(
void )
2541 const QString& filename()
const {
return filename_;}
2542 const QDateTime& filetime()
const {
return filetime_;}
2543 void filetime(
const QDateTime& _newtime) {filetime_ = _newtime;}
2549 for (
int i = 0; i < 5; ++i)
2552 vertexBeginCode_.clear();
2553 vertexEndCode_.clear();
2554 fragmentBeginCode_.clear();
2555 fragmentEndCode_.clear();
2564 QDateTime lastmod = QFileInfo(absFilename).lastModified();
2567 QHash<QString, ShaderModifierFile>::iterator cacheEntry = fileCache_.find(_filename);
2569 bool reload =
false;
2570 bool firstLoad =
false;
2572 if (cacheEntry != fileCache_.end())
2575 res = &cacheEntry.value();
2577 if (lastmod != res->filetime())
2597 res = &fileCache_[_filename];
2599 res->loadBlocks(lines);
2600 res->filetime(lastmod);
2614 void loadBlocks(
const QStringList& _lines)
2616 static const char* markers [] =
2625 "FragmentBeginCode:",
2628 const int numMarkers =
sizeof(markers) /
sizeof(markers[0]);
2630 QStringList* blockTargets [] =
2639 &fragmentBeginCode_,
2643 assert(
sizeof(blockTargets) /
sizeof(blockTargets[0]) == numMarkers);
2647 QStringList* curBlock_ = 0;
2652 for (QStringList::const_iterator it = _lines.begin(); it != _lines.end(); ++it, ++curLine)
2658 if (version_ <= 0 && it->startsWith(
"#version "))
2660 const int offset = strlen(
"#version ");
2661 version_ = atoi(it->toLatin1().data() + offset);
2667 bool blockMarker =
false;
2669 for (
int i = 0; i < numMarkers && !blockMarker; ++i)
2671 if ( it->startsWith(markers[i]) )
2674 curBlock_ = blockTargets[i];
2682 curBlock_->push_back(*it);
2684 std::cerr <<
"ShaderModifierFile::loadBlocks - line belongs to unknown block in file " << filename_.toLatin1().data() <<
" at line " << curLine << std::endl;
2702 QDateTime filetime_;
2711 QStringList vertexBeginCode_,
2718 static QHash<QString, ShaderModifierFile> fileCache_;
2721 QHash<QString, ShaderModifierFile> ShaderModifierFile::fileCache_;
2726 return ShaderModifierFile::loadFromFile(_filename);
2736 const char* shadeModeString[] =
2745 QTextStream resStrm(&res);
2747 resStrm <<
"version: " << version;
2749 resStrm <<
"\nshaderDesc.numLights: " << numLights;
2753 resStrm <<
"\nshaderDesc.lightTypes[]: {";
2755 for (
int i = 0; i < numLights; ++i)
2757 switch (lightTypes[i])
2759 case SG_LIGHT_DIRECTIONAL: resStrm <<
"DIRECTIONAL";
break;
2760 case SG_LIGHT_POINT: resStrm <<
"POINT";
break;
2761 case SG_LIGHT_SPOT: resStrm <<
"SPOT";
break;
2762 default: resStrm <<
"UNDEFINED";
break;
2765 if (i + 1 < numLights)
2771 resStrm <<
"\nshaderDesc.shadeMode: " << shadeModeString[shadeMode];
2772 resStrm <<
"\nshaderDesc.twoSidedLighting: " << (twoSidedLighting ?
"Yes" :
"No");
2773 resStrm <<
"\nshaderDesc.vertexColors: " << vertexColors;
2774 resStrm <<
"\nshaderDesc.textured(): " << textured();
2775 for (std::map<size_t,TextureType>::const_iterator iter = textureTypes_.begin(); iter != textureTypes_.end();++iter)
2777 resStrm <<
"\nTexture stage: " << iter->first;
2778 resStrm <<
"\nTexture Type: ";
2779 switch (iter->second.type)
2781 case GL_TEXTURE_1D: resStrm <<
"GL_TEXTURE_1D";
break;
2782 case GL_TEXTURE_2D: resStrm <<
"GL_TEXTURE_2D";
break;
2783 case GL_TEXTURE_3D: resStrm <<
"GL_TEXTURE_3D";
break;
2784 case GL_TEXTURE_CUBE_MAP: resStrm <<
"GL_TEXTURE_CUBE_MAP";
break;
2785 #ifdef GL_ARB_texture_rectangle //ARCH_DARWIN doesn't support all texture defines with all xcode version (xcode 5.0 seems to support all) 2786 case GL_TEXTURE_RECTANGLE_ARB: resStrm <<
"GL_TEXTURE_RECTANGLE";
break;
2788 case GL_TEXTURE_BUFFER: resStrm <<
"GL_TEXTURE_BUFFER";
break;
2789 #ifdef GL_EXT_texture_array 2790 case GL_TEXTURE_1D_ARRAY_EXT: resStrm <<
"GL_TEXTURE_1D_ARRAY";
break;
2791 case GL_TEXTURE_2D_ARRAY_EXT: resStrm <<
"GL_TEXTURE_2D_ARRAY";
break;
2793 #ifdef GL_ARB_texture_cube_map_array 2794 case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: resStrm <<
"GL_TEXTURE_CUBE_MAP_ARRAY";
break;
2796 #ifdef GL_ARB_texture_multisample 2797 case GL_TEXTURE_2D_MULTISAMPLE: resStrm <<
"GL_TEXTURE_2D_MULTISAMPLE";
break;
2798 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: resStrm <<
"GL_TEXTURE_2D_MULTISAMPLE_ARRAY";
break;
2800 default: std::cerr <<
"Texture Type with number "<< iter->second.type <<
" on stage "<< iter->first <<
" is not supported " << std::endl;
break;
2803 resStrm <<
"\nShadowTexture: " << iter->second.shadow;
2806 resStrm <<
"\nshaderDesc.texGenDim: " << texGenDim;
2810 case GL_OBJECT_LINEAR: resStrm <<
"\nshaderDesc.texGenMode: GL_OBJECT_LINEAR";
break;
2811 case GL_EYE_LINEAR: resStrm <<
"\nshaderDesc.texGenMode: GL_EYE_LINEAR";
break;
2812 case GL_SPHERE_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_SPHERE_MAP";
break;
2813 case GL_NORMAL_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_NORMAL_MAP";
break;
2814 case GL_REFLECTION_MAP: resStrm <<
"\nshaderDesc.texGenMode: GL_REFLECTION_MAP";
break;
2815 default: resStrm <<
"\nshaderDesc.texGenMode: unknown";
break;
2818 resStrm <<
"\nshaderDesc.texGenPerFragment: " << texGenPerFragment;
2820 if (!vertexTemplateFile.isEmpty())
2821 resStrm <<
"\nshaderDesc.vertexTemplateFile: " << vertexTemplateFile;
2823 if (!tessControlTemplateFile.isEmpty())
2824 resStrm <<
"\nshaderDesc.tessControlTemplateFile: " << tessControlTemplateFile;
2826 if (!tessEvaluationTemplateFile.isEmpty())
2827 resStrm <<
"\nshaderDesc.tessEvaluationTemplateFile: " << tessEvaluationTemplateFile;
2829 if (!geometryTemplateFile.isEmpty())
2830 resStrm <<
"\nshaderDesc.geometryTemplateFile: " << geometryTemplateFile;
2832 if (!fragmentTemplateFile.isEmpty())
2833 resStrm <<
"\nshaderDesc.fragmentTemplateFile: " << fragmentTemplateFile;
static void setShaderDir(QString _dir)
bool hasTessControlShader() const
check whether there is a tess-control shader present
void addInput(const QString &_input)
Add one GLSL input specifier.
Namespace providing different geometric functions concerning angles.
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
bool normalizeTexColors
Defines if the textureVariable is normalized or not, if multiple textures are used.
void addOutput(const QString &_output)
Add one GLSL output specifier.
QString getInputName(int _id) const
get variable name of input
int getNumActiveModifiers() const
Get the number of active modifiers.
void initTessControlShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting tess-control shader io for a given description.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
void init(const ShaderGenDesc *_desc, ShaderModifier *const *_modifiers, unsigned int _numActiveMods)
Called in constructor.
void addStringToList(QString _str, QStringList *_list, QString _prefix="", QString _postfix="")
bool hasGeometryShader() const
check whether there is a geometry shader present
virtual void modifyLightingCode(QStringList *_code, int _lightId, ShaderGenLightType _lightType)
Modify the default lighting code of the shader generator.
void saveToFile(const char *_fileName)
Save generated shader code to text file.
virtual void modifyTessEvalIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation evaluation shader.
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
void addRawIOBlock(QStringList _codeBlock)
Add a raw glsl IO code block.
ShaderProgGenerator(const ShaderGenDesc *_desc)
void modifyVertexEndCode(QStringList *_code)
Append code the the vertex shader.
bool passPosVS_
default attributes that should be passed down from vertex shader
void addMacros(const QStringList &_macros)
Add a list of preprocessor macros.
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
QString vertexShaderFile_
path + filename to shader templates
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.
bool hasDefine(QString _define) const
Check for define.
virtual void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
static ShaderModifier * loadFromFile(QString _filename)
Load a modifier from file.
void addDefine(const QString &_define)
Add one define.
void buildShaderCode(QStringList *_pMainCode, const QStringList &_defaultLightingFunctions)
Shader assembly function.
void addIncludeFile(QString _fileName)
Imports another shader, same as #include.
void modifyGeometryIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the geometry shader.
void addLightingCode(QStringList *_code)
Adds lighting function calls to code.
void modifyTessEvalIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation evaluation shader.
virtual void modifyTessControlIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation control shader.
void addIODefine(const QString &_macroName, const QString &_resolvedName)
Assign an opaque name to the abstract macro.
static int numRegisteredModifiers_
registered shader modifier
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
int getNumOutputs() const
get number of outputs
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
QString getOutputName(int _id) const
get variable name of output
QString getIOMapName(int _inId) const
get corresponding output name of an input id
void modifyVertexBeginCode(QStringList *_code)
Append code the the vertex shader.
void loadShaderTemplateFromFile()
Loads external shader templates.
void setGLSLVersion(int _version)
Set glsl version.
void defineIOAbstraction(const DefaultIODesc *_iodesc, bool _vs, bool _fs)
Define abstract IO names via shader defines.
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
bool ACGDLLEXPORT openGLVersionTest(const int _major, const int _minor)
int getNumInputs() const
get number of inputs
void initTessEvalShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting tess-evaluation shader io for a given description.
void initGeometryShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting geometry shader io for a given description.
static QString getShaderDir()
void initFragmentShaderIO(const ShaderGenDesc *_desc, ShaderGenerator *_prevStage, const DefaultIODesc *_iodesc)
Adds fitting fragment shader io for a given description.
int checkForIncludes(QString _str, ShaderGenerator *_gen, QString _includePath)
void initGenDefines(ShaderGenerator *_gen)
provide generated defines to shader
void modifyLightingCode(QStringList *_code, ShaderModifier *_modifier)
Calls lighting modifier for each light.
virtual void modifyVertexIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the vertex shader.
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
static QString getPathName(QString _strFileName)
returns path to _strFileName without last slash
void addLight(int lightIndex_, ShaderGenLightType _light)
Add a light description to shader:
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
ShaderModifier * getActiveModifier(int _i)
Get active modfiers for this program.
void modifyVertexIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the vertex shader.
bool outputArrays_
outputs of shader are arrays (tess-control)
void addLayout(QString _layout)
Add a layout directive.
const QStringList & getShaderCode()
Get result of buildShaderCode.
void addIOToCode(const QStringList &_cmds)
void matchInputs(const ShaderGenerator *_previousShaderStage, bool _passToNextStage, QString _inputPrefix="outVertex", QString _outputPrefix="outGeometry")
Perform name matching of outputs and inputs between two shader stages.
static bool loadStringListFromFile(QString _fileName, QStringList *_out)
Load a text file as string list.
QString toString() const
convert ShaderGenDesc to string format for debugging
QString vertexColorsInterpolator
interpolation qualifier for input vertex colors: "flat", "smooth", "noperspective" ...
bool inputTexCoord_
default attributes that should be imported in vertex shader
QString vertexNormalInterpolator
interpolation qualifier for vertex shader normal outputs: "flat", "smooth", "noperspective" ...
virtual void modifyGeometryIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the geometry shader.
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
void initVertexShaderIO(const ShaderGenDesc *_desc, const DefaultIODesc *_iodesc)
Adds fitting vertex shader io for a given description.
void addLightingFunctions(QStringList *_code)
Adds lighting definition functions.
QStringList tessControlLayout_
layout() directives scanned from loaded templates
void generateShaders()
Generates the shader code.
static QString getAbsFilePath(QString _fileName)
Convert a filename to an absolute filename.
void initDefaultUniforms()
Adds frequently used uniform parameters.
QString outputPrefix_
prefix of outputs of this shader
void modifyTessControlIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the tessellation control shader.
ShaderGenerator::DefaultIODesc ioDesc_
default IO descriptor for the vertex shader