147 lines
4.7 KiB
C++
147 lines
4.7 KiB
C++
/*
|
|
QGLView
|
|
Copyright (C) 2020 Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#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;
|
|
}
|