From 7601caaadae74971d3b187fd0f738b9144d239c6 Mon Sep 17 00:00:00 2001 From: ccolin Date: Sat, 2 Oct 2021 22:51:20 +0200 Subject: [PATCH] code is all clean now (but still broken) --- resources.qrc | 6 ++ src/main.cpp | 8 ++- src/mesh_view.cpp | 75 ++++++++++---------- src/mesh_view.h | 15 ++-- src/mesh_viewer.cpp | 162 ++++++++++++-------------------------------- src/mesh_viewer.h | 3 +- src/shader.frag | 13 ++++ src/shader.vert | 13 ++++ tp.pro | 2 + 9 files changed, 124 insertions(+), 173 deletions(-) create mode 100644 resources.qrc create mode 100644 src/shader.frag create mode 100644 src/shader.vert diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 0000000..0f1d526 --- /dev/null +++ b/resources.qrc @@ -0,0 +1,6 @@ + + + src/shader.vert + src/shader.frag + + diff --git a/src/main.cpp b/src/main.cpp index 02d19ae..46736ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,9 +8,11 @@ int main(int argc, char *argv[]) { using namespace std; QSurfaceFormat format; - format.setRenderableType(QSurfaceFormat::RenderableType::OpenGL); - format.setMajorVersion(2); - format.setMinorVersion(1); + format.setRenderableType(QSurfaceFormat::OpenGL); +#ifndef QT_DEBUG + qDebug("Debug build"); + format.setOption(QSurfaceFormat::DebugContext); +#endif QSurfaceFormat::setDefaultFormat(format); QApplication app(argc, argv); MeshProcessor *mesh_processor = nullptr; diff --git a/src/mesh_view.cpp b/src/mesh_view.cpp index 277e2db..57f7ad1 100644 --- a/src/mesh_view.cpp +++ b/src/mesh_view.cpp @@ -1,14 +1,12 @@ #include "mesh_view.h" -#include +#include -MeshView::MeshView(QOpenGLExtraFunctions *glf, const MyMesh &mesh, - int pos_attr, int col_attr) - : glf(glf), +MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program) + : buffer(QOpenGLBuffer::VertexBuffer), mesh(mesh) { GLfloat *verts = new GLfloat[mesh.n_faces() * 3 * 6]; size_t i = 0; - for (const FaceHandle face : mesh.faces()) { for (const VertexHandle vec : mesh.fv_range(face)) { verts[6*i + 0] = mesh.point(vec)[0]; @@ -21,53 +19,50 @@ MeshView::MeshView(QOpenGLExtraFunctions *glf, const MyMesh &mesh, } } - delete[] verts; - - GLuint vao, vbo; - glf->glGenVertexArrays(1, &vao); - glf->glGenBuffers(1, &vbo); - - glf->glBindVertexArray(vao); - glf->glBindBuffer(GL_ARRAY_BUFFER, vbo); - glf->glBufferData(GL_ARRAY_BUFFER, nverts * 6 * sizeof (GLfloat), verts, GL_DYNAMIC_DRAW); - glf->glVertexAttribPointer(pos_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat), 0); - glf->glEnableVertexAttribArray(pos_attr); - glf->glVertexAttribPointer(col_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat), - (const void *) (3 * sizeof (GLfloat))); - glf->glEnableVertexAttribArray(col_attr); - - glf->glBindVertexArray(0); + vao.create(); + {QOpenGLVertexArrayObject::Binder binder(&vao); + buffer.create(); + buffer.bind(); + buffer.setUsagePattern(QOpenGLBuffer::StreamDraw); + buffer.allocate(verts, nverts * 6 * sizeof (GLfloat)); + delete[] verts; + program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat)); + program.enableAttributeArray("pos"); + program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat)); + program.enableAttributeArray("col"); + } } MeshView::~MeshView() { - glf->glDeleteVertexArrays(1, &vao); - glf->glDeleteBuffers(1, &vbo); + vao.destroy(); + buffer.destroy(); } -void MeshView::paint(QOpenGLContext *ctx, - int model_attr, int wireframe_attr) const { +void MeshView::paint(QOpenGLShaderProgram &program) { + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + QOpenGLExtraFunctions *glf = ctx->extraFunctions(); void (*glPolygonMode)(GLenum, GLenum) = nullptr; glPolygonMode = (typeof glPolygonMode) ctx->getProcAddress("glPolygonMode"); if (!glPolygonMode) qWarning("glPolygonMode not available"); - glf->glUniformMatrix4fv(model_attr, 1, GL_FALSE, - mesh.transform.constData()); + program.setUniformValue("model", mesh.transform); - /* Mesh */ - glf->glBindVertexArray(vao); - glf->glEnable(GL_POLYGON_OFFSET_FILL); - glf->glPolygonOffset(1.0, 2); - glf->glDrawArrays(GL_TRIANGLES, 0, nverts); - if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glf->glDisable(GL_POLYGON_OFFSET_FILL); + {QOpenGLVertexArrayObject::Binder binder(&vao); + /* Mesh */ + glf->glEnable(GL_POLYGON_OFFSET_FILL); + glf->glPolygonOffset(1.0, 2); + glf->glDrawArrays(GL_TRIANGLES, 0, nverts); + if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glf->glDisable(GL_POLYGON_OFFSET_FILL); - /* Wireframe */ - glf->glUniform1f(wireframe_attr, 1); - glf->glDrawArrays(GL_TRIANGLES, 0, nverts); - if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glf->glLineWidth(3); - glf->glUniform1f(wireframe_attr, 0); + /* Wireframe */ + program.setUniformValue("wireframe", 1); + glf->glDrawArrays(GL_TRIANGLES, 0, nverts); + if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glf->glLineWidth(3); + program.setUniformValue("wireframe", 1); + } } diff --git a/src/mesh_view.h b/src/mesh_view.h index ddd8e8e..47000c1 100644 --- a/src/mesh_view.h +++ b/src/mesh_view.h @@ -3,23 +3,22 @@ #include "my_mesh.h" #include -#include +#include +#include +#include class MeshView { - GLuint vao; - GLuint vbo; + QOpenGLVertexArrayObject vao; + QOpenGLBuffer buffer; size_t nverts; - QOpenGLExtraFunctions *glf; public: const MyMesh &mesh; - MeshView(QOpenGLExtraFunctions *glf, const MyMesh &mesh, - int pos_attr, int col_attr); + MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program); ~MeshView(); - void paint(QOpenGLContext *ctx, - int model_attr, int wireframe_attr) const; + void paint(QOpenGLShaderProgram &program); }; diff --git a/src/mesh_viewer.cpp b/src/mesh_viewer.cpp index 60128b8..c5f1f37 100644 --- a/src/mesh_viewer.cpp +++ b/src/mesh_viewer.cpp @@ -1,40 +1,9 @@ #include "mesh_viewer.h" #include -#include - - -const GLchar *vertex_shader_source = R"glsl( -attribute vec3 pos; -attribute vec3 col; - -varying vec3 frag_col; - -uniform mat4 proj; -uniform mat4 view; -uniform mat4 model; - -void main() { - gl_Position = proj * view * model * vec4(pos, 1.0); - frag_col = col; -} -)glsl"; - -const GLchar *fragment_shader_source = R"glsl( -varying vec3 frag_col; - -uniform vec3 wf_col; -uniform bool wireframe; -uniform float alpha; - -void main() { - if (!wireframe) - // gl_FragColor = vec4(wf_col, alpha); - gl_FragColor = vec4(.5, .5, .5, 1); - else - gl_FragColor = vec4(frag_col, alpha); -} -)glsl"; +#include +#include +#include MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) { @@ -48,96 +17,49 @@ QSize MeshViewer::sizeHint() const { } -void GLAPIENTRY -opengl_debug_cb(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) { - (void) source; - (void) type; - (void) id; - (void) severity; - (void) length; - (void) userParam; - qDebug() << "OpenGL debug output:" << message; -} - - void MeshViewer::initializeGL() { - // initializeOpenGLFunctions(); + QOpenGLFunctions *glf = context()->functions(); +#ifdef QT_DEBUG + QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this); + if (!logger->initialize()) { + qDebug("OpenGL debug output unavailable"); + } + connect(logger, &QOpenGLDebugLogger::messageLogged, + [](const QOpenGLDebugMessage &message) { + qDebug() << "OpenGL: " << message.message(); + }); + logger->startLogging(); +#endif - qDebug("OpenGL version %d.%d", - context()->format().majorVersion(), - context()->format().minorVersion()); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(opengl_debug_cb, 0); - - /* Compile the vertex shader. */ - GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL); - glCompileShader(vertex_shader); - GLint status; - glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { - char log[1024]; - glGetShaderInfoLog(vertex_shader, sizeof log, NULL, log); - fprintf(stderr, "Failed to compile the vertex shader: %s\n", log); - exit(1); + QOpenGLShader vertex_shader(QOpenGLShader::Vertex); + if (!vertex_shader.compileSourceFile(":/shader.vert")) { + qCritical() << vertex_shader.log(); } - /* Compile the fragment shader. */ - GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL); - glCompileShader(fragment_shader); - glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { - char log[1024]; - glGetShaderInfoLog(fragment_shader, sizeof log, NULL, log); - fprintf(stderr, "Failed to compile the fragment shader: %s\n", log); - exit(1); + QOpenGLShader fragment_shader(QOpenGLShader::Fragment); + if (fragment_shader.compileSourceFile(":/shader.frag")) { + qCritical() << fragment_shader.log(); } - - /* Link the shader program. */ - GLuint shader_program = glCreateProgram(); - glAttachShader(shader_program, vertex_shader); - glAttachShader(shader_program, fragment_shader); - glBindFragDataLocation(shader_program, 0, "out_color"); - glLinkProgram(shader_program); - glGetProgramiv(shader_program, GL_LINK_STATUS, &status); - if (status != GL_TRUE) { - char log[1024]; - glGetProgramInfoLog(shader_program, sizeof log, NULL, log); - fprintf(stderr, "Failed to link the shader program: %s\n", log); - exit(1); + if (!program.addShader(&vertex_shader)) { + qCritical() << program.log(); } + if (!program.addShader(&fragment_shader)) { + qCritical() << program.log(); + } + if (!program.link()) { + qCritical() << program.log(); + } + program.bind(); - /* Use it. */ - glUseProgram(shader_program); + program.setUniformValue("alpha", (GLfloat) 1); + program.setUniformValue("wf_col", WIREFRAME_COLOR); - /* Get the position attribute. */ - pos_attr = glGetAttribLocation(shader_program, "pos"); - col_attr = glGetAttribLocation(shader_program, "col"); + glf->glClearColor(1, 1, 1, 0); - proj_attr = glGetUniformLocation(shader_program, "proj"); - view_attr = glGetUniformLocation(shader_program, "view"); - model_attr = glGetUniformLocation(shader_program, "model"); - wf_col_attr = glGetUniformLocation(shader_program, "wf_col"); - wireframe_attr = glGetUniformLocation(shader_program, "wireframe"); - alpha_attr = glGetUniformLocation(shader_program, "alpha"); + glf->glEnable(GL_DEPTH_TEST); + glf->glEnable(GL_MULTISAMPLE); - glUniform1f(alpha_attr, 1); - glUniform3f(wf_col_attr, WIREFRAME_COLOR); - - glClearColor(1, 1, 1, 0); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_MULTISAMPLE); - - qDebug("Mesh viewer initialized"); + qDebug("Mesh viewer: initialization complete"); emit initialized(); } @@ -145,7 +67,7 @@ void MeshViewer::initializeGL() { void MeshViewer::resizeGL(int w, int h) { QMatrix4x4 projection; projection.perspective(FOV, (float) w/h, .01, 100); - glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data()); + program.setUniformValue("proj", projection); } @@ -154,17 +76,17 @@ void MeshViewer::paintGL() { QMatrix4x4 trans; trans.translate(0, 0, -cam_dist); QMatrix4x4 view = trans * rot; - glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data()); - for (const MeshView m : meshes) { - m.paint(context(), model_attr, wireframe_attr); + program.setUniformValue("view", view); + for (MeshView &m : meshes) { + m.paint(program); } } void MeshViewer::addMesh(const MyMesh &mesh) { + Q_ASSERT(isValid()); makeCurrent(); - meshes.emplace_back(context()->extraFunctions(), mesh, - pos_attr, col_attr); + meshes.emplace_back(mesh, program); doneCurrent(); update(); } diff --git a/src/mesh_viewer.h b/src/mesh_viewer.h index b2e9a76..3c7a94f 100644 --- a/src/mesh_viewer.h +++ b/src/mesh_viewer.h @@ -25,8 +25,7 @@ class MeshViewer : public QOpenGLWidget { Q_OBJECT std::list meshes; - GLint pos_attr, col_attr, proj_attr, view_attr, model_attr; - GLint wf_col_attr, wireframe_attr, alpha_attr; + QOpenGLShaderProgram program; QMatrix4x4 proj; QMatrix4x4 rot, rot_start; GLfloat cam_dist = 1; diff --git a/src/shader.frag b/src/shader.frag new file mode 100644 index 0000000..c14c16c --- /dev/null +++ b/src/shader.frag @@ -0,0 +1,13 @@ +varying vec3 frag_col; + +uniform vec3 wf_col; +uniform bool wireframe; +uniform float alpha; + +void main() { + if (!wireframe) + // gl_FragColor = vec4(wf_col, alpha); + gl_FragColor = vec4(.5, .5, .5, 1); + else + gl_FragColor = vec4(frag_col, alpha); +} diff --git a/src/shader.vert b/src/shader.vert new file mode 100644 index 0000000..e1a20e8 --- /dev/null +++ b/src/shader.vert @@ -0,0 +1,13 @@ +attribute vec3 pos; +attribute vec3 col; + +varying vec3 frag_col; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main() { + gl_Position = proj * view * model * vec4(pos, 1.0); + frag_col = col; +} diff --git a/tp.pro b/tp.pro index a4cc9e0..3ce6559 100644 --- a/tp.pro +++ b/tp.pro @@ -16,6 +16,8 @@ win32 { LIBS += $$PWD/libs/OpenMesh/libwin/OpenMeshCore.lib } +RESOURCES = resources.qrc + HEADERS += src/my_mesh.h HEADERS += src/main_window.h HEADERS += src/mesh_viewer.h