--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/layers/gridlayer.cpp Sun Jun 26 21:00:06 2022 +0300 @@ -0,0 +1,129 @@ +/* + * 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 "../gl/partrenderer.h" +#include "gridlayer.h" + +constexpr char vertexShaderSource[] = R"( +#version 330 core + +layout (location = 0) in vec2 in_position; +uniform mat4 mvp; +smooth out vec2 ex_uv; +uniform mat4 grid; + +void main() +{ + gl_Position = mvp * grid * vec4(in_position, 0.0, 1.0); + ex_uv = in_position; +} +)"; + +constexpr char fragmentShaderSource[] = R"( +#version 330 core + +out vec4 color; +smooth in vec2 ex_uv; +uniform vec4 gridColor; + +void main(void) +{ + float dx = fract(ex_uv.y); + float dy = fract(ex_uv.x); + /* fade the grid towards extreme co-ordinates */ + float d = (1.0f - 0.015 * max(abs(ex_uv.x), abs(ex_uv.y))); + color = vec4(gridColor.xyz, gridColor.w * d); +} +)"; + +template<int extent> +constexpr auto calcGridData() +{ + std::array<glm::vec2, 8 * extent + 4> result; + std::size_t ix = 0; + for (int i = -extent; i <= extent; i += 1) { + result[ix++] = {i, -extent}; + result[ix++] = {i, extent}; + } + for (int i = -extent; i <= extent; i += 1) { + result[ix++] = {-extent, i}; + result[ix++] = {extent, i}; + } + return result; +} + +void GridLayer::setGridMatrix(const glm::mat4& newGridMatrix) +{ + this->gridMatrix = newGridMatrix; + if (this->isInitialized) { + this->shader.setUniformMatrix("grid", newGridMatrix); + } +} + +void GridLayer::setGridColor(const QColor& newGridColor) +{ + this->gridColor = gl::colorToVector4(newGridColor); + if (this->isInitialized) { + this->shader.setUniformVector("gridColor", this->gridColor); + } +} + +void GridLayer::settingsChanged() +{ + this->setGridColor(this->renderer->isDark() ? Qt::white : Qt::black); +} + +void GridLayer::initializeGL() +{ + this->shader.initialize( + ::vertexShaderSource, + ::fragmentShaderSource, + QOpenGLBuffer::StaticDraw, + { + GLAttributeSpec{ + .type = GL_FLOAT, + .offset = 0, + .tuplesize = 2, + .stride = 0, + }, + } + ); + this->isInitialized = true; + constexpr auto data = calcGridData<50>(); + this->shader.setUniformVector("gridColor", this->gridColor); + this->setGridMatrix(this->gridMatrix); + this->settingsChanged(); + this->shader.bufferData(data.data(), data.size(), sizeof data[0]); +} + +void GridLayer::paintGL() +{ + glLineWidth(1); + glEnable(GL_BLEND); + glLineStipple(1, 0x8888); + glEnable(GL_LINE_STIPPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + this->shader.draw(GL_LINES); + glDisable(GL_BLEND); + glDisable(GL_LINE_STIPPLE); +} + +void GridLayer::mvpMatrixChanged(const glm::mat4& mvpMatrix) +{ + this->shader.setMvpMatrix(mvpMatrix); +}