diff -r 910890292639 -r 9f435f66bd0c src/gl/abstractshaderprogram.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gl/abstractshaderprogram.cpp Wed Feb 17 16:49:35 2021 +0200 @@ -0,0 +1,113 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2020 Teemu Piippo + * + * 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 . + */ + +#include "abstractshaderprogram.h" + +AbstractShaderProgram::AbstractBasicShaderProgram(const QVector& arraySpecifications, QObject* parent) : + QObject{parent}, + buffer{QOpenGLBuffer::VertexBuffer}, + vertexShader{QOpenGLShader::Vertex}, + fragmentShader{QOpenGLShader::Fragment} +{ + this->arrays.reserve(arraySpecifications.size()); + for (const ArraySpecification& arraySpecification : arraySpecifications) + { + this->arrays.emplace_back({arraySpecification}); + } +} + +void AbstractShaderProgram::initialize() +{ + if (not this->isInitialized) + { + this->initializeOpenGLFunctions(); + this->isInitialized = true; + this->program.emplace(this); + gl::buildShaders(&*this->program, this->vertexShaderSource(), this->fragmentShaderSource()); + this->program->bind(); + for (auto& array : this->arrays) + { + array.buffer.create(); + array.buffer.bind(); + array.buffer.setUsagePattern(array.specification.bufferUsagePattern); + array.vertexArrayObject.create(); + array.vertexArrayObject.bind(); + } + this->setupVertexArrays(); + this->vertexArrayObject.release(); + this->releaseBuffers(); + this->buffer.release(); + this->program->release(); + this->checkForGLErrors(); + } +} + +void AbstractShaderProgram::setViewMatrix(const glm::mat4& newViewMatrix) +{ + this->setMatrix("view", newViewMatrix); +} + +void AbstractShaderProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix) +{ + this->setMatrix("projection", newProjectionMatrix); +} + +void AbstractShaderProgram::setModelMatrix(const glm::mat4& newModelMatrix) +{ + this->setMatrix("model", newModelMatrix); +} + +void AbstractShaderProgram::setMatrix(const char* name, const glm::mat4& matrix) +{ + Q_ASSERT(this->isInitialized); + this->program->bind(); + this->program->setUniformMatrix(name, matrix); + this->program->release(); + this->checkForGLErrors(); +} + +void AbstractShaderProgram::draw() +{ + this->program->bind(); + for (Array& array : this->arrays) + { + array.vertexArrayObject.bind(); + glDrawArrays(array.specification.drawMode, 0, array.count); + this->vertexArrayObject.release(); + } + this->program->release(); + this->checkForGLErrors(); +} + +void AbstractShaderProgram::teardown() +{ + this->vertexArrayObject.destroy(); + this->buffer.destroy(); + this->program.reset(); +} + +void AbstractShaderProgram::checkForGLErrors() +{ + gl::checkForGLErrors(qobject_cast(this->parent())); +} + +void AbstractShaderProgram::upload(Array* array, const void* data, int count) +{ + array->count = count; + array->buffer->buffer.allocate(data, count * array->specification.vertexSize); +}