From 123f6d30fe82a8d0ac5681022d03fe20873aa9c8 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 4 Aug 2025 22:56:06 +0100 Subject: [PATCH] feat: opengl point rendering --- CMakeLists.txt | 1 + src/Gui/Viewport/GLCamera.cpp | 4 + src/Gui/Viewport/GLCamera.h | 1 + src/Gui/Viewport/GLPoints.cpp | 211 ++++++++++++++++++++++++++ src/Gui/Viewport/GLPoints.h | 43 ++++++ src/Gui/Viewport/ViewportGLWidget.cpp | 42 +++-- src/Gui/Viewport/ViewportGLWidget.h | 4 +- src/Gui/main.cpp | 2 +- 8 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 src/Gui/Viewport/GLPoints.cpp create mode 100644 src/Gui/Viewport/GLPoints.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c759eb3..ad55f02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(GUI_SOURCES src/Gui/Viewport/GLCamera.cpp src/Gui/Viewport/GLMesh.cpp src/Gui/Viewport/GLGrid.cpp + src/Gui/Viewport/GLPoints.cpp src/Gui/Network/NetworkGraphicsView.cpp src/Gui/Network/NetworkGraphicsScene.cpp src/Gui/Network/Network.cpp diff --git a/src/Gui/Viewport/GLCamera.cpp b/src/Gui/Viewport/GLCamera.cpp index d226a14..ead83e7 100644 --- a/src/Gui/Viewport/GLCamera.cpp +++ b/src/Gui/Viewport/GLCamera.cpp @@ -123,6 +123,10 @@ void GLCamera::changeRadius(float delta) } +glm::vec3 GLCamera::getPos() +{ + return camPos_; +}; glm::vec3 GLCamera::getRight() { diff --git a/src/Gui/Viewport/GLCamera.h b/src/Gui/Viewport/GLCamera.h index f353e9a..b3a940a 100644 --- a/src/Gui/Viewport/GLCamera.h +++ b/src/Gui/Viewport/GLCamera.h @@ -16,6 +16,7 @@ public: void setCenter(float x, float y, float z); void setUniform(uint uniformLocation); + glm::vec3 getPos(); glm::vec3 getForward(); glm::vec3 getRight(); glm::vec3 getUp(); diff --git a/src/Gui/Viewport/GLPoints.cpp b/src/Gui/Viewport/GLPoints.cpp new file mode 100644 index 0000000..c5d7fd1 --- /dev/null +++ b/src/Gui/Viewport/GLPoints.cpp @@ -0,0 +1,211 @@ + +#include "Gui/Viewport/GLPoints.h" +#include +#include +#include +#include +#include +#include +#include "Engine/Types.h" +#include "Gui/Viewport/GLCamera.h" +#include "icecream.hpp" + +#define GLM_ENABLE_EXPERIMENTAL +#include + + +GLPoints::GLPoints() +{ + initializeOpenGLFunctions(); + init(); +} + +void GLPoints::init() +{ + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + initBuffers(); + initShaderProgram(); + + // unbind vertex array + glBindVertexArray(0); +} + +void GLPoints::initBuffers() +{ + const GLfloat billboardVertexPositions[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + }; + + points_ = {}; + pointCount = points_.size(); + + glGenBuffers(1, &billboardVertexBuffer_); + glBindBuffer(GL_ARRAY_BUFFER, billboardVertexBuffer_); + glBufferData(GL_ARRAY_BUFFER, sizeof(billboardVertexPositions), billboardVertexPositions, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glGenBuffers(1, &pointDataBuffer_); + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)0); + glVertexAttribDivisor(1, 1); +} + + +void GLPoints::setPoints(enzo::geo::Geometry& geometry, GLCamera& camera) +{ + const enzo::ga::Offset numPoints = geometry.getNumPoints(); + const glm::vec3 camPosGlm = camera.getPos(); + const enzo::bt::Vector3 camPos(camPosGlm.x, camPosGlm.y, camPosGlm.z); + + points_ = std::vector(numPoints); + + for(enzo::ga::Offset ptOffset=0; ptOffset((pos-camPos).norm())*0.005f}; + } + pointCount = points_.size(); + + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); +} + +void GLPoints::updatePointSize(GLCamera& camera) +{ + const glm::vec3 camPosGlm = camera.getPos(); + + for(Point& point : points_) + { + point = {point.position, glm::distance(point.position,camPosGlm)*0.005f}; + } + + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); +} + + + +void GLPoints::initShaderProgram() +{ + // vertex shader + const std::string vertexShaderSource = R"( + #version 330 core + uniform mat4 uView; + uniform mat4 uProj; + layout(location = 0) in vec3 aPos; + layout(location = 1) in vec4 aOffsetScale; + + out vec2 vLocal; + + void main() + { + vec3 right = vec3(uView[0][0], uView[1][0], uView[2][0]); + vec3 up = vec3(uView[0][1], uView[1][1], uView[2][1]); + + vLocal = aPos.xy; + vec3 worldPos = aOffsetScale.xyz + + (right * aPos.x + up * aPos.y) * aOffsetScale.w; + + gl_Position = uProj * uView * vec4(worldPos, 1.0); + } + )"; + // shader type + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + // convert source + const GLchar* vertexShaderSourceC = vertexShaderSource.c_str(); + // create shader object + glShaderSource(vertexShader, 1, &vertexShaderSourceC, NULL); + // compile shader object + glCompileShader(vertexShader); + + + // log shader error + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if(!success) + { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + } + else + { + std::cout << "success\n"; + + } + + + // fragment shader + const std::string fragmentShaderSource = R"( + #version 330 core + in vec2 vLocal; + out vec4 FragColor; + + void main() + { + if (length(vLocal) > 0.5) discard; + FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } + )"; + + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar* fragmentShaderSourceC = fragmentShaderSource.c_str(); + glShaderSource(fragmentShader, 1, &fragmentShaderSourceC, NULL); + glCompileShader(fragmentShader); + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if(!success) + { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; + } + else + { + std::cout << "success\n"; + + } + + // create shader program + shaderProgram = glCreateProgram(); + // attach shaders + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + // link program + glLinkProgram(shaderProgram); + + // delete shaders now that the program is complete + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); +} + + + +void GLPoints::bind() +{ + glBindVertexArray(vao); +} + +void GLPoints::useProgram() +{ + glUseProgram(shaderProgram); +} + + +void GLPoints::unbind() +{ + glBindVertexArray(0); +} + +void GLPoints::draw() +{ + bind(); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, pointCount); +} diff --git a/src/Gui/Viewport/GLPoints.h b/src/Gui/Viewport/GLPoints.h new file mode 100644 index 0000000..57fe0cc --- /dev/null +++ b/src/Gui/Viewport/GLPoints.h @@ -0,0 +1,43 @@ +#pragma once +#include "Engine/Types.h" +#include +#include +#include +#include +#include "Engine/Operator/Geometry.h" +#include "Gui/Viewport/GLCamera.h" + +struct Point +{ + glm::vec3 position; + float scale; +}; + +class GLPoints +: protected QOpenGLFunctions_3_3_Core +{ +public: + GLPoints(); + GLuint vao; + + GLuint billboardVertexBuffer_; + GLuint pointDataBuffer_; + GLuint shaderProgram; + + + + std::vector faceIndexData; + std::vector points_; + + enzo::ga::Offset pointCount; + + void init(); + void initBuffers(); + void initShaderProgram(); + void setPoints(enzo::geo::Geometry& geometry, GLCamera& camera); + void updatePointSize(GLCamera& camera); + void useProgram(); + void bind(); + void unbind(); + void draw(); +}; diff --git a/src/Gui/Viewport/ViewportGLWidget.cpp b/src/Gui/Viewport/ViewportGLWidget.cpp index 14c8ff4..167bec5 100644 --- a/src/Gui/Viewport/ViewportGLWidget.cpp +++ b/src/Gui/Viewport/ViewportGLWidget.cpp @@ -2,6 +2,7 @@ #include "Engine/Operator/AttributeHandle.h" #include "Engine/Types.h" #include "Gui/Viewport/GLMesh.h" +#include "Gui/Viewport/GLPoints.h" #include #include #include @@ -21,9 +22,9 @@ void ViewportGLWidget::initializeGL() glEnable(GL_MULTISAMPLE); enzo::geo::Geometry geo = enzo::geo::Geometry(); - // triangleMesh_ = meshFromGeo(geo); triangleMesh_ = std::make_unique(); gridMesh_ = std::make_unique(); + points_ = std::make_unique(); QSurfaceFormat fmt = context()->format(); std::cout << "format: " << (fmt.renderableType() == QSurfaceFormat::OpenGLES ? "GLES" : "Desktop") << "\n"; @@ -154,9 +155,10 @@ void ViewportGLWidget::paintGL() 1000.0f // far plane ); + gridMesh_->useProgram(); - glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); - curCamera.setUniform(glGetUniformLocation(shaderProgram, "uView")); + glUniformMatrix4fv(glGetUniformLocation(gridMesh_->shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); + curCamera.setUniform(glGetUniformLocation(gridMesh_->shaderProgram, "uView")); gridMesh_->draw(); @@ -170,26 +172,36 @@ void ViewportGLWidget::paintGL() triangleMesh_->draw(); + points_->useProgram(); + points_->bind(); + points_->updatePointSize(curCamera); + glUniformMatrix4fv(glGetUniformLocation(points_->shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); + curCamera.setUniform(glGetUniformLocation(points_->shaderProgram, "uView")); + + glUniform3fv(glGetUniformLocation(points_->shaderProgram, "uCameraRight"), 1, glm::value_ptr(curCamera.getRight())); + glUniform3fv(glGetUniformLocation(points_->shaderProgram, "uCameraUp"), 1, glm::value_ptr(curCamera.getUp())); + points_->draw(); + } -std::unique_ptr ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geometry) -{ - using namespace enzo; +// std::unique_ptr ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geometry) +// { +// using namespace enzo; - auto mesh = std::make_unique(); - - std::shared_ptr PAttr = geometry.getAttribByName(ga::AttrOwner::POINT, "P"); - ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); +// auto mesh = std::make_unique(); +// +// std::shared_ptr PAttr = geometry.getAttribByName(ga::AttrOwner::POINT, "P"); +// ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); - mesh->setPosBuffer(geometry); - mesh->setIndexBuffer(geometry); +// mesh->setPosBuffer(geometry); +// mesh->setIndexBuffer(geometry); - return mesh; -} +// return mesh; +// } void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry) { @@ -199,4 +211,6 @@ void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry) triangleMesh_->setPosBuffer(geometry); triangleMesh_->setIndexBuffer(geometry); + + points_->setPoints(geometry, curCamera); } diff --git a/src/Gui/Viewport/ViewportGLWidget.h b/src/Gui/Viewport/ViewportGLWidget.h index 2917873..22c3b43 100644 --- a/src/Gui/Viewport/ViewportGLWidget.h +++ b/src/Gui/Viewport/ViewportGLWidget.h @@ -6,6 +6,7 @@ #include "Gui/Viewport/GLCamera.h" #include "Gui/Viewport/GLMesh.h" #include "Gui/Viewport/GLGrid.h" +#include "Gui/Viewport/GLPoints.h" #include "Engine/Operator/Geometry.h" class ViewportGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_2_Core @@ -17,8 +18,9 @@ public: GLCamera curCamera; std::unique_ptr triangleMesh_ ; std::unique_ptr gridMesh_ ; + std::unique_ptr points_ ; - std::unique_ptr meshFromGeo(enzo::geo::Geometry& geometry); + // std::unique_ptr meshFromGeo(enzo::geo::Geometry& geometry); protected: void initializeGL() override; diff --git a/src/Gui/main.cpp b/src/Gui/main.cpp index 48f0933..fcf5f90 100644 --- a/src/Gui/main.cpp +++ b/src/Gui/main.cpp @@ -10,7 +10,7 @@ int main(int argc, char **argv) // set up rendering QSurfaceFormat format; format.setRenderableType(QSurfaceFormat::OpenGL); - format.setVersion(3, 2); + format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); format.setSamples(4); QSurfaceFormat::setDefaultFormat(format);