/* QGLEngineShaders Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "gltypes.h" #include "qglview.h" #include "glshaders.h" #include "glshaders_headers.h" using namespace QGLEngineShaders; bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file, bool add_qgl, const QString & defs) { if (type == 0 || content.isEmpty()) { content.clear(); return true; } //qDebug() << "[QGLEngine] Shader" << file << "found" << (QOpenGLShader::ShaderTypeBit)(int)type << "section ..."; if (add_qgl) { switch (type) { case QOpenGLShader::Fragment: content.prepend(qgl_fragment_head); content.prepend(qgl_uniform); content.prepend(qgl_structs); break; case QOpenGLShader::Vertex : content.prepend(qgl_vertex_head ); break; case QOpenGLShader::Geometry: content.prepend(qgl_geometry_head); break; } } content.prepend(defs); content.prepend(qgl_common_head); bool ret = prog->addShaderFromSourceCode(type, content.toLatin1()); if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log(); content.clear(); return ret; } QString prepareDefines(const QStringList & defines) { if (defines.isEmpty()) return QString(); QString ret; foreach (QString s, defines) ret.append("#define " + s + "\n"); return ret; } bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl, const QStringList & defines) { if (!prog) prog = new QOpenGLShaderProgram(); prog->removeAllShaders(); QFile f(file); if (!f.open(QIODevice::ReadOnly)) { qDebug() << "[QGLEngine] Shader" << file << "Error: can`t open file!"; return false; } QTextStream ts(&f); QString cur_shader, line, pl, defs = prepareDefines(defines); QOpenGLShader::ShaderType type = 0; while (!ts.atEnd()) { line = ts.readLine(); pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower(); pl.chop(2); if (pl == "vertex" || pl == "vert") { if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; type = QOpenGLShader::Vertex; continue; } if (pl == "fragment" || pl == "frag") { if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; type = QOpenGLShader::Fragment; continue; } if (pl == "geometry" || pl == "geom") { if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; type = QOpenGLShader::Geometry; continue; } if (pl == "tessellation_control") { if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; type = QOpenGLShader::TessellationControl; continue; } if (pl == "tessellation_evaluation") { if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; type = QOpenGLShader::TessellationEvaluation; continue; } cur_shader.append("\n"); cur_shader.append(line); } if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; if (!prog->link()) { qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log(); return false; } qDebug() << "[QGLEngine] Shader" << file << "ok"; return true; } bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl, const QStringList & defines) { if (!prog) prog = new QOpenGLShaderProgram(); prog->removeAllShaders(); QString cur_shader, defs = prepareDefines(defines); foreach (QString f, files) { QFileInfo fi(f); QOpenGLShader::ShaderType type = 0; if (fi.suffix().toLower() == "vert") type = QOpenGLShader::Vertex ; if (fi.suffix().toLower() == "frag") type = QOpenGLShader::Fragment; if (fi.suffix().toLower() == "geom") type = QOpenGLShader::Geometry; if (type == 0) continue; QFile file(f); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "[QGLEngine] Shader" << f << "Error: can`t open file!"; return false; } cur_shader = file.readAll(); if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false; } if (!prog->link()) { qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log(); return false; } qDebug() << "[QGLEngine] Shader" << files << "ok"; return true; }