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