--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gl/gridprogram.cpp Thu Feb 13 12:51:27 2020 +0200 @@ -0,0 +1,136 @@ +/* + * 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 vec2 in_position; +uniform mat4 view; +uniform mat4 projection; +uniform mat4 model; +smooth out vec2 ex_uv; +const mat4 stretch = mat4(vec4(10000, 0, 0, 0), vec4(0, 10000, 0, 0), vec4(0, 0, 10000, 0), vec4(0, 0, 0, 1)); + +void main() +{ + gl_Position = projection * view * model * stretch * vec4(in_position, 0.0, 1.0); + ex_uv = in_position; +} +)"; + +const char fragmentShaderSource[] = R"( +#version 330 core + +out vec4 color; +smooth in vec2 ex_uv; +const vec4 lineColor = vec4(1.0, 1.0, 1.0, 0.75); + +void main(void) +{ + if(fract(ex_uv.x / 0.001f) < 0.01f || fract(ex_uv.y / 0.001f) < 0.01f) + color = lineColor; + else + color = vec4(0); +} +)"; + +static const glm::vec2 data[] = {{-1, -1}, {-1, 1}, {1, 1}, {1, -1}}; + +GridProgram::GridProgram(QObject* parent) : + QObject{parent}, + buffer{QOpenGLBuffer::VertexBuffer}, + vertexShader{QOpenGLShader::Vertex}, + fragmentShader{QOpenGLShader::Fragment} +{ +} + +void GridProgram::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->vertexArrayObject.release(); + this->buffer.release(); + this->program->release(); + this->checkForGLErrors(); + } +} + +void GridProgram::setViewMatrix(const glm::mat4& newViewMatrix) +{ + Q_ASSERT(this->isInitialized); + this->program->bind(); + this->program->setUniformMatrix("view", newViewMatrix); + this->program->release(); + this->checkForGLErrors(); +} + +void GridProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix) +{ + Q_ASSERT(this->isInitialized); + this->program->bind(); + this->program->setUniformMatrix("projection", newProjectionMatrix); + this->program->release(); + this->checkForGLErrors(); +} + +void GridProgram::setModelMatrix(const glm::mat4& newModelMatrix) +{ + Q_ASSERT(this->isInitialized); + this->program->bind(); + this->program->setUniformMatrix("model", newModelMatrix); + this->program->release(); + this->checkForGLErrors(); +} + +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())); +}