--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gl/axesprogram.cpp Fri Mar 06 16:08:53 2020 +0200 @@ -0,0 +1,168 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "gridprogram.h" + +// Based on https://stackoverflow.com/q/30842755 +const char vertexShaderSource[] = R"( +#version 330 core + +layout (location = 0) in vec3 in_position; +layout (location = 1) in vec3 in_color; +uniform mat4 view; +uniform mat4 projection; +uniform mat4 model; +smooth out vec3 ex_color; + +void main() +{ + gl_Position = projection * view * model * vec4(in_position, 0.0, 1.0); + ex_uv = ex_color; +} +)"; + +const char fragmentShaderSource[] = R"( +#version 330 core + +out vec4 color; +smooth in vec3 ex_color; + +void main(void) +{ + color = vec4(ex_color, 1) +} +)"; + +namespace +{ + struct AxesVertex + { + glm::vec3 position; + glm::vec3 color; + }; +} + +static AxesVertex data[] = +{ + AxesVertex{{-10000, 0, 0}, {1, 0, 0}}, + AxesVertex{{10000, 0, 0}, {1, 0, 0}}, + AxesVertex{{0, -10000, 0}, {0, 1, 0}}, + AxesVertex{{0, 10000, 0}, {0, 1, 0}}, + AxesVertex{{0, 0, -10000}, {0, 0, 1}}, + AxesVertex{{0, 0, 10000}, {0, 0, 1}}, +}; + +AxesProgram::AxesProgram(QObject* parent) : + QObject{parent}, + buffer{QOpenGLBuffer::VertexBuffer}, + vertexShader{QOpenGLShader::Vertex}, + fragmentShader{QOpenGLShader::Fragment} +{ +} + +void AxesProgram::initialize() +{ + if (not isInitialized) + { + this->initializeOpenGLFunctions(); + this->isInitialized = true; + this->program.emplace(this); + gl::buildShaders(&*this->program, ::vertexShaderSource, ::fragmentShaderSource); + this->program->bind(); + this->buffer.create(); + this->buffer.bind(); + this->buffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + this->buffer.allocate(data, countof(data) * sizeof data[0]); + this->vertexArrayObject.create(); + this->vertexArrayObject.bind(); + this->program->enableAttributeArray(0); + this->program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0); + this->program->setUniformVector("gridColor", this->gridColor); + this->vertexArrayObject.release(); + this->buffer.release(); + this->program->release(); + this->checkForGLErrors(); + } +} + +void AxesProgram::setViewMatrix(const glm::mat4& newViewMatrix) +{ + this->setMatrix("view", newViewMatrix); +} + +void AxesProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix) +{ + this->setMatrix("projection", newProjectionMatrix); +} + +void AxesProgram::setModelMatrix(const glm::mat4& newModelMatrix) +{ + this->setMatrix("model", newModelMatrix); +} + +void AxesProgram::setGridMatrix(const glm::mat4& newGridMatrix) +{ + this->setMatrix("grid", newGridMatrix); +} + +void AxesProgram::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 GridProgram::setGridColor(const QColor& newGridColor) +{ + const glm::vec4 vec = gl::colorToVector4(newGridColor); + if (this->isInitialized) + { + this->program->bind(); + this->program->setUniformVector("gridColor", vec); + this->program->release(); + this->checkForGLErrors(); + } + else + { + this->gridColor = vec; + } +} + +void GridProgram::draw() +{ + this->program->bind(); + this->vertexArrayObject.bind(); + glDrawArrays(GL_QUADS, 0, countof(data)); + this->vertexArrayObject.release(); + this->program->release(); + this->checkForGLErrors(); +} + +void GridProgram::teardown() +{ + this->vertexArrayObject.destroy(); + this->buffer.destroy(); + this->program.reset(); +} + +void GridProgram::checkForGLErrors() +{ + gl::checkForGLErrors(qobject_cast<QWidget*>(this->parent())); +}