diff -r 6de5ac1fb471 -r 3a9e761e4faa src/gl/partrenderer.cpp
--- a/src/gl/partrenderer.cpp Sun Jan 19 14:25:57 2020 +0200
+++ b/src/gl/partrenderer.cpp Wed Jan 22 00:23:29 2020 +0200
@@ -16,19 +16,54 @@
* along with this program. If not, see .
*/
+#include
#include
-#include
+#include
#include "partrenderer.h"
-PartRenderer::PartRenderer(Model* model, DocumentManager* documents, QWidget* parent) :
+
+static const char* vertexShaderSource = R"(
+#version 330 core
+
+layout(location=0) in vec3 position;
+layout(location=1) in vec4 color;
+out vec4 vColor;
+uniform mat4 CameraTransformation;
+
+void main()
+{
+ vColor = color;
+ gl_Position = CameraTransformation * vec4(position, 1.0);
+}
+)";
+
+static const char* fragmentShaderSource = R"(
+#version 330 core
+
+in vec4 vColor;
+out vec4 fColor;
+
+void main()
+{
+ fColor = vColor;
+}
+)";
+
+PartRenderer::PartRenderer(Model* model, DocumentManager* documents, const ColorTable& colorTable, QWidget* parent) :
QOpenGLWidget{parent},
model{model},
documents{documents},
- compiler{new gl::Compiler{this}}
+ colorTable{colorTable},
+ compiler{new gl::Compiler{this->colorTable, this}}
{
this->setMouseTracking(true);
}
+PartRenderer::~PartRenderer()
+{
+ delete this->objects.program;
+}
+
void PartRenderer::initializeGL()
{
this->initializeOpenGLFunctions();
@@ -36,12 +71,64 @@
{
abort();
}
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ //this->compiler->initialize();
+ //this->compiler->build(this->model, this->documents);
this->initializeLighting();
this->initialized = true;
this->rotation = QQuaternion::fromAxisAndAngle({1, 0, 0}, 30);
this->rotation *= QQuaternion::fromAxisAndAngle({0, 1, 0}, 330);
- this->compiler->build(this->model, this->documents);
glLineWidth(2.0);
+ this->objects.program = new QOpenGLShaderProgram;
+ this->objects.program->create();
+ this->checkForGLErrors();
+ this->objects.program->addShaderFromSourceCode(QOpenGLShader::Vertex, ::vertexShaderSource);
+ this->checkForGLErrors();
+ this->objects.program->addShaderFromSourceCode(QOpenGLShader::Fragment, ::fragmentShaderSource);
+ this->checkForGLErrors();
+ this->objects.program->link();
+ this->checkForGLErrors();
+ this->objects.program->bind();
+ this->checkForGLErrors();
+ this->objects.buffer.create();
+ this->checkForGLErrors();
+ this->objects.buffer.bind();
+ this->checkForGLErrors();
+ this->objects.buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
+ this->checkForGLErrors();
+ /*
+ GLfloat data[] = {
+ 20.0f, 20.0f, 6.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 30.0f, 20.0f, 6.0f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 30.0f, 30.0f, 6.0f, 0.0f, 0.0f, 1.0f, 1.0f,
+ };
+ */
+ GLfloat data[] = {
+ 0.00f, 0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ -0.75f, -0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.75f, -0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f
+ };
+ this->objects.buffer.allocate(data, sizeof data);
+ this->checkForGLErrors();
+ this->objects.vertexArray.create();
+ this->checkForGLErrors();
+ this->objects.vertexArray.bind();
+ this->checkForGLErrors();
+ this->objects.program->enableAttributeArray(0);
+ this->checkForGLErrors();
+ this->objects.program->enableAttributeArray(1);
+ this->checkForGLErrors();
+ this->objects.program->setAttributeBuffer(0, GL_FLOAT, 0, 3);
+ this->checkForGLErrors();
+ this->objects.program->setAttributeBuffer(1, GL_FLOAT, 3, 4);
+ this->checkForGLErrors();
+ this->objects.vertexArray.release();
+ this->checkForGLErrors();
+ this->objects.buffer.release();
+ this->checkForGLErrors();
+ this->objects.program->release();
+ this->checkForGLErrors();
}
/*
@@ -85,29 +172,27 @@
glMatrixMode(GL_MODELVIEW);
}
-static GLenum getGlTypeForVboClass(const gl::VboClass vboClass)
+static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass)
{
switch (vboClass)
{
- case gl::VboClass::Lines:
- case gl::VboClass::ConditionalLines:
+ case gl::ArrayClass::Lines:
+ case gl::ArrayClass::ConditionalLines:
return GL_LINES;
- case gl::VboClass::Triangles:
+ case gl::ArrayClass::Triangles:
return GL_TRIANGLES;
- case gl::VboClass::Quads:
+ case gl::ArrayClass::Quads:
return GL_QUADS;
}
throw std::runtime_error{"Bad vbo class passed to getGlTypeForVboClass"};
}
-// https://www.codemiles.com/c-opengl-examples/drawing-teapot-using-opengl-t9010.html?mobile=on
-#include
void PartRenderer::paintGL()
{
+ /*
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_POLYGON_OFFSET_FILL);
- glPolygonOffset (1.0f, 1.0f);
+ */
glEnable (GL_DEPTH_TEST);
glShadeModel (GL_SMOOTH);
glEnable (GL_MULTISAMPLE);
@@ -118,6 +203,20 @@
void PartRenderer::renderScene()
{
+ glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_MODELVIEW);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ glLoadIdentity();
+ //glTranslated(0.0, 0.0, -4.5 * this->compiler->modelDistance());
+ //glTranslated(0.0, 0.0, -4.5);
+ //glMultMatrixf(padMatrix(this->rotation.toRotationMatrix()).constData());
+ //xyz(glTranslatef, -this->compiler->modelCenter());
+ auto rotationMatrix = padMatrix(this->rotation.toRotationMatrix());
+ rotationMatrix(2, 3) = 0;
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(1.0f, 1.0f);
switch (this->renderStyle)
{
case gl::RenderStyle::Normal:
@@ -128,60 +227,58 @@
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
}
- glMatrixMode(GL_MODELVIEW);
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glLoadIdentity();
- glTranslatef(0.0, 0.0, -4.5 * this->compiler->modelDistance());
- glMultMatrixf(padMatrix(this->rotation.toRotationMatrix()).constData());
- xyz(glTranslatef, -this->compiler->modelCenter());
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- for (const gl::VboClass vboClass : {gl::VboClass::Lines, gl::VboClass::Triangles, gl::VboClass::Quads})
- {
- const GLuint vboSurfaces = this->compiler->vbo({vboClass, gl::VboSubclass::Surfaces});
- const GLuint vboColors = this->compiler->vbo({vboClass, gl::VboSubclass::RegularColors});
- const GLuint vboNormals = this->compiler->vbo({vboClass, gl::VboSubclass::Normals});
- const std::size_t count = this->compiler->vboSize({vboClass, gl::VboSubclass::Surfaces}) / 3_z;
- glBindBuffer(GL_ARRAY_BUFFER, vboSurfaces);
- glVertexPointer(3, GL_FLOAT, 0, nullptr);
- glBindBuffer(GL_ARRAY_BUFFER, vboColors);
- glColorPointer(4, GL_FLOAT, 0, nullptr);
- glBindBuffer(GL_ARRAY_BUFFER, vboNormals);
- glNormalPointer(GL_FLOAT, 0, nullptr);
- glDrawArrays(getGlTypeForVboClass(vboClass), 0, static_cast(count));
- }
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- const GLenum glError = this->glGetError();
- if (glError != GL_NO_ERROR)
+ this->objects.program->bind();
+ this->checkForGLErrors();
+ const int cameraTransformationUniform = glGetUniformLocation(this->objects.program->programId(), "CameraTransformation");
+ this->checkForGLErrors();
+ this->objects.program->setUniformValue(cameraTransformationUniform, rotationMatrix);
+ this->checkForGLErrors();
+ this->objects.vertexArray.bind();
+ this->checkForGLErrors();
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ this->checkForGLErrors();
+ this->objects.vertexArray.release();
+ this->checkForGLErrors();
+ this->objects.program->release();
+ this->checkForGLErrors();
+#if 0
+ // Lines need to be rendered last so that anti-aliasing does not interfere with polygon rendering.
+ renderVao(gl::ArrayClass::Triangles);
+ renderVao(gl::ArrayClass::Quads);
+ renderVao(gl::ArrayClass::Lines);
+#endif
+ glDisable(GL_POLYGON_OFFSET_FILL);
+}
+
+void PartRenderer::renderVao(const gl::ArrayClass /*arrayClass*/)
+{
+ /*
+ this->compiler->bindVertexArray(arrayClass);
+ const std::size_t vertexCount = this->compiler->vboSize({arrayClass, gl::VboSubclass::VertexData}) / gl::FLOATS_PER_VERTEX;
+ glDrawArrays(getGlTypeForArrayClass(arrayClass), 0, static_cast(vertexCount));
+ this->compiler->releaseVertexArray(arrayClass);
+ this->checkForGLErrors();
+ */
+}
+
+void PartRenderer::checkForGLErrors()
+{
+ GLenum glError;
+ QStringList errors;
+ while ((glError = glGetError()) != GL_NO_ERROR)
{
const QString glErrorString = QString::fromLatin1(reinterpret_cast(::gluErrorString(glError)));
+ errors.append(glErrorString);
+ }
+ if (not errors.isEmpty())
+ {
QMessageBox::critical(
this,
tr("Rendering error"),
- QString{"Failed to render: %1"}.arg(glErrorString));
+ QString{"Failed to render.\n%1"}.arg(errors.join("\n")));
}
- glDisable(GL_CULL_FACE);
}
-static QPointF pointToPointF(const QPoint& point)
-{
- return {static_cast(point.x()), static_cast(point.y())};
-}
-
-/*
-static QPoint pointFToPoint(const QPointF& point)
-{
- return {static_cast(std::round(point.x())), static_cast(std::round(point.y()))};
-}
-*/
-
void PartRenderer::mouseMoveEvent(QMouseEvent* event)
{
const bool left = event->buttons() & Qt::LeftButton;