diff --git a/mdl/black.jpg b/img/black.jpg
similarity index 100%
rename from mdl/black.jpg
rename to img/black.jpg
diff --git a/img/clouds1_down (copie).jpg b/img/clouds1_down (copie).jpg
new file mode 100644
index 0000000..de818e6
Binary files /dev/null and b/img/clouds1_down (copie).jpg differ
diff --git a/img/clouds1_down.jpg b/img/clouds1_down.jpg
new file mode 100644
index 0000000..e34c8af
Binary files /dev/null and b/img/clouds1_down.jpg differ
diff --git a/img/clouds1_east.jpg b/img/clouds1_east.jpg
new file mode 100644
index 0000000..fdf2cb5
Binary files /dev/null and b/img/clouds1_east.jpg differ
diff --git a/img/clouds1_north.jpg b/img/clouds1_north.jpg
new file mode 100644
index 0000000..9a27454
Binary files /dev/null and b/img/clouds1_north.jpg differ
diff --git a/img/clouds1_south.jpg b/img/clouds1_south.jpg
new file mode 100644
index 0000000..84d0fca
Binary files /dev/null and b/img/clouds1_south.jpg differ
diff --git a/img/clouds1_up (copie).jpg b/img/clouds1_up (copie).jpg
new file mode 100644
index 0000000..ac8ead2
Binary files /dev/null and b/img/clouds1_up (copie).jpg differ
diff --git a/img/clouds1_up.jpg b/img/clouds1_up.jpg
new file mode 100644
index 0000000..f45663a
Binary files /dev/null and b/img/clouds1_up.jpg differ
diff --git a/img/clouds1_west.jpg b/img/clouds1_west.jpg
new file mode 100644
index 0000000..8c8306b
Binary files /dev/null and b/img/clouds1_west.jpg differ
diff --git a/mdl/dji600.jpg b/img/dji600.jpg
similarity index 100%
rename from mdl/dji600.jpg
rename to img/dji600.jpg
diff --git a/mdl/ground.jpg b/img/ground.jpg
similarity index 100%
rename from mdl/ground.jpg
rename to img/ground.jpg
diff --git a/mdl/mdl.jpg b/img/mdl.jpg
similarity index 100%
rename from mdl/mdl.jpg
rename to img/mdl.jpg
diff --git a/mdl/cube.obj b/mdl/cube.obj
new file mode 100644
index 0000000..de4003f
--- /dev/null
+++ b/mdl/cube.obj
@@ -0,0 +1,30 @@
+# Blender v2.90.1 OBJ File: ''
+# www.blender.org
+o Cube
+v -1.000000 -1.000000 1.000000
+v -1.000000 1.000000 1.000000
+v -1.000000 -1.000000 -1.000000
+v -1.000000 1.000000 -1.000000
+v 1.000000 -1.000000 1.000000
+v 1.000000 1.000000 1.000000
+v 1.000000 -1.000000 -1.000000
+v 1.000000 1.000000 -1.000000
+vn -1.0000 0.0000 0.0000
+vn 0.0000 0.0000 -1.0000
+vn 1.0000 0.0000 0.0000
+vn 0.0000 0.0000 1.0000
+vn 0.0000 -1.0000 0.0000
+vn 0.0000 1.0000 0.0000
+s off
+f 2//1 3//1 1//1
+f 4//2 7//2 3//2
+f 8//3 5//3 7//3
+f 6//4 1//4 5//4
+f 7//5 1//5 3//5
+f 4//6 6//6 8//6
+f 2//1 4//1 3//1
+f 4//2 8//2 7//2
+f 8//3 6//3 5//3
+f 6//4 2//4 1//4
+f 7//5 5//5 1//5
+f 4//6 2//6 6//6
diff --git a/projet.pro b/projet.pro
index 78954f1..f7e12ef 100644
--- a/projet.pro
+++ b/projet.pro
@@ -11,8 +11,10 @@ SOURCES += src/main_window.cc
SOURCES += src/opengl_mesh.cc
SOURCES += src/opengl_widget.cc
SOURCES += src/drone_controller.cc
+SOURCES += src/load_obj.cc
HEADERS += src/main_window.hh
HEADERS += src/opengl_mesh.hh
HEADERS += src/opengl_widget.hh
HEADERS += src/drone_controller.hh
+HEADERS += src/load_obj.hh
diff --git a/resources.qrc b/resources.qrc
index 8facd60..2ff2adf 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -3,10 +3,20 @@
mdl/dji600.obj
mdl/dji600.mtl
- mdl/dji600.jpg
- mdl/test.obj
- mdl/test.mtl
- mdl/black.jpg
- mdl/ground.jpg
+ mdl/cube.obj
+
+ img/dji600.jpg
+ img/ground.jpg
+ img/clouds1_up.jpg
+ img/clouds1_down.jpg
+ img/clouds1_north.jpg
+ img/clouds1_east.jpg
+ img/clouds1_south.jpg
+ img/clouds1_west.jpg
+
+ shaders/main.vert
+ shaders/main.frag
+ shaders/skybox.vert
+ shaders/skybox.frag
diff --git a/shaders/main.frag b/shaders/main.frag
new file mode 100644
index 0000000..8eb47ec
--- /dev/null
+++ b/shaders/main.frag
@@ -0,0 +1,20 @@
+#version 330 core
+
+in vec3 norm;
+in vec2 uv;
+in vec3 frag_pos;
+
+out vec4 final_col;
+
+uniform sampler2D tex;
+
+void main() {
+ vec3 light_col = vec3(1, .964, .783);
+ vec3 ambient = light_col * .2;
+
+ vec3 light_dir = normalize(vec3(5, 10, -8));
+ float diff = max(dot(normalize(norm), light_dir), 0.0);
+ vec3 diffuse = diff * light_col;
+
+ final_col = texture(tex, uv) * vec4(ambient + diffuse, 1);
+}
diff --git a/shaders/main.vert b/shaders/main.vert
new file mode 100644
index 0000000..33e6849
--- /dev/null
+++ b/shaders/main.vert
@@ -0,0 +1,20 @@
+#version 330 core
+
+layout(location = 0) in vec3 in_pos;
+layout(location = 1) in vec3 in_norm;
+layout(location = 2) in vec2 in_uv;
+
+out vec3 norm;
+out vec2 uv;
+out vec3 frag_pos;
+
+uniform mat4 proj;
+uniform mat4 view;
+uniform mat4 model;
+
+void main() {
+ gl_Position = proj * view * model * vec4(in_pos, 1.0);
+ norm = in_norm;
+ uv = in_uv;
+ frag_pos = vec3(model * vec4(in_pos, 1.0));
+}
diff --git a/shaders/skybox.frag b/shaders/skybox.frag
new file mode 100644
index 0000000..f5f8edb
--- /dev/null
+++ b/shaders/skybox.frag
@@ -0,0 +1,23 @@
+#version 330 core
+
+// in vec3 tex_coord;
+
+// out vec4 final_col;
+
+// uniform samplerCube skybox;
+
+// void main() {
+// // final_col = texture(skybox, tex_coord);
+// final_col = vec4(0, 0, 0, 1);
+// }
+
+in vec3 tex_coords;
+
+out vec4 final_col;
+
+uniform samplerCube tex;
+
+void main() {
+ final_col = texture(tex, tex_coords);
+ // final_col = vec4(1, 0, 1, 1);
+}
diff --git a/shaders/skybox.vert b/shaders/skybox.vert
new file mode 100644
index 0000000..ac4ac5e
--- /dev/null
+++ b/shaders/skybox.vert
@@ -0,0 +1,28 @@
+#version 330 core
+
+// layout(location = 0) in vec3 in_pos;
+
+// out vec3 tex_coords;
+
+// uniform mat4 proj;
+// uniform mat4 view;
+
+// void main() {
+// // vec4 pos = proj * view * vec4(in_pos, 1.0);
+// // gl_Position = pos.xyww;
+// gl_Position = proj * vec4(in_pos, 1.0);
+// tex_coords = in_pos;
+// }
+
+layout(location = 0) in vec3 in_pos;
+
+out vec3 tex_coords;
+
+uniform mat4 proj;
+uniform mat4 view;
+
+void main() {
+ tex_coords = in_pos;
+ vec4 pos = proj * mat4(mat3(view)) * vec4(in_pos, 1.0);
+ gl_Position = pos.xyww;
+}
diff --git a/src/drone_controller.cc b/src/drone_controller.cc
index c41721e..9a6c5db 100644
--- a/src/drone_controller.cc
+++ b/src/drone_controller.cc
@@ -1,8 +1,6 @@
#include "drone_controller.hh"
#include "opengl_widget.hh"
-
-#define TINYOBJLOADER_IMPLEMENTATION
-#include "tiny_obj_loader.h"
+#include "load_obj.hh"
#include
#include
@@ -26,62 +24,8 @@ OpenGLMesh *Drone::mesh = nullptr;
Drone::Drone() {
if (!mesh_initialized) {
- QFile obj_file(":/mdl/dji600.obj");
- QFile mtl_file(":/mdl/dji600.mtl");
- obj_file.open(QIODevice::ReadOnly | QIODevice::Text);
- mtl_file.open(QIODevice::ReadOnly | QIODevice::Text);
- std::string obj = obj_file.readAll().toStdString();
- std::string mtl = mtl_file.readAll().toStdString();
- tinyobj::ObjReaderConfig cfg;
- cfg.triangulate = true;
- cfg.vertex_color = false;
- tinyobj::ObjReader reader;
- if (!reader.ParseFromString(obj, mtl, cfg)) {
- if (!reader.Error().empty()) {
- qWarning() << "Erreur lors de la lecture de du modèle";
- }
- exit(1);
- }
- // if (!reader.Warning().empty()) {
- // qWarning() << "TinyObjReader: " << reader.Warning();
- // }
- auto& attrib = reader.GetAttrib();
- auto& shapes = reader.GetShapes();
-
- QVector verts;
-
- for (size_t s = 0; s < shapes.size(); s++) {
- // Loop over faces(polygon)
- size_t index_offset = 0;
- for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
- size_t fv = shapes[s].mesh.num_face_vertices[f];
-
- // Loop over vertices in the face.
- for (size_t v = 0; v < fv; v++) {
- tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
- tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
- tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
- tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
- tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
- tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
- tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
- tinyobj::real_t ts = attrib.texcoords[2*idx.texcoord_index+0];
- tinyobj::real_t tt = attrib.texcoords[2*idx.texcoord_index+1];
- verts.append(vx);
- verts.append(vy);
- verts.append(vz);
- verts.append(nx);
- verts.append(ny);
- verts.append(nz);
- verts.append(ts);
- verts.append(tt);
- // qDebug() << "vert" << vx << vy << vz << "tex" << ts << tt;
- }
- index_offset += fv;
- }
- }
-
- QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/mdl/dji600.jpg").mirrored());
+ QVector verts = load_obj(":/mdl/dji600.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS);
+ QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/img/dji600.jpg").mirrored());
// texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
// texture->setMagnificationFilter(QOpenGLTexture::Linear);
mesh = new OpenGLMesh(verts, texture);
@@ -147,7 +91,7 @@ DroneController::DroneController(const QJsonObject &json)
}
OpenGLWidget::instance->makeCurrent();
- QOpenGLTexture *ground_tex = new QOpenGLTexture(QImage(":/mdl/ground.jpg").mirrored());
+ QOpenGLTexture *ground_tex = new QOpenGLTexture(QImage(":/img/ground.jpg").mirrored());
OpenGLMesh *ground = new OpenGLMesh({
-100, 0, -100, 0, 1, 0, 0, 0,
100, 0, -100, 0, 1, 0, 1, 0,
@@ -158,6 +102,7 @@ DroneController::DroneController(const QJsonObject &json)
}, ground_tex);
OpenGLWidget::instance->meshes.append(*ground);
OpenGLWidget::instance->doneCurrent();
+
connect(&timer, &QTimer::timeout, this, &DroneController::step);
}
diff --git a/src/load_obj.cc b/src/load_obj.cc
new file mode 100644
index 0000000..2e079f0
--- /dev/null
+++ b/src/load_obj.cc
@@ -0,0 +1,68 @@
+#include "load_obj.hh"
+
+#define TINYOBJLOADER_IMPLEMENTATION
+#include "tiny_obj_loader.h"
+#include
+#include
+
+
+QVector load_obj(const char *path, int flags) {
+ QFile obj_file(path);
+ obj_file.open(QIODevice::ReadOnly | QIODevice::Text);
+ std::string obj = obj_file.readAll().toStdString();
+ tinyobj::ObjReaderConfig cfg;
+ cfg.triangulate = true;
+ cfg.vertex_color = false;
+ tinyobj::ObjReader reader;
+ if (!reader.ParseFromString(obj, "", cfg)) {
+ if (!reader.Error().empty()) {
+ qWarning() << "Erreur lors de la lecture de du modèle";
+ }
+ exit(1);
+ }
+ // if (!reader.Warning().empty()) {
+ // qWarning() << "TinyObjReader: " << reader.Warning();
+ // }
+ auto& attrib = reader.GetAttrib();
+ auto& shapes = reader.GetShapes();
+
+ QVector verts;
+
+ for (size_t s = 0; s < shapes.size(); s++) {
+ // Loop over faces(polygon)
+ size_t index_offset = 0;
+ for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
+ size_t fv = shapes[s].mesh.num_face_vertices[f];
+
+ // Loop over vertices in the face.
+ for (size_t v = 0; v < fv; v++) {
+ tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
+ tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
+ tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
+ tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
+ verts.append(vx);
+ verts.append(vy);
+ verts.append(vz);
+
+ if (flags & LOAD_OBJ_NORMALS) {
+ tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
+ tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
+ tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
+ verts.append(nx);
+ verts.append(ny);
+ verts.append(nz);
+ }
+
+ if (flags & LOAD_OBJ_UVS) {
+ tinyobj::real_t ts = attrib.texcoords[2*idx.texcoord_index+0];
+ tinyobj::real_t tt = attrib.texcoords[2*idx.texcoord_index+1];
+ verts.append(ts);
+ verts.append(tt);
+ }
+ // qDebug() << "vert" << vx << vy << vz << "tex" << ts << tt;
+ }
+ index_offset += fv;
+ }
+ }
+ return verts;
+}
diff --git a/src/load_obj.hh b/src/load_obj.hh
new file mode 100644
index 0000000..089d4b5
--- /dev/null
+++ b/src/load_obj.hh
@@ -0,0 +1,13 @@
+#ifndef LOAD_OBJ_HH
+#define LOAD_OBJ_HH
+
+#include
+#include
+
+#define LOAD_OBJ_NORMALS 1 << 0
+#define LOAD_OBJ_UVS 1 << 1
+
+QVector load_obj(const char *path, int flags);
+
+
+#endif
diff --git a/src/opengl_mesh.cc b/src/opengl_mesh.cc
index 6e1ff72..f2f0981 100644
--- a/src/opengl_mesh.cc
+++ b/src/opengl_mesh.cc
@@ -10,8 +10,8 @@ OpenGLMesh::OpenGLMesh(QVector verts, QOpenGLTexture *tex)
QOpenGLFunctions_4_4_Core *glf = OpenGLWidget::instance;
nverts = verts.size() / 8;
glf->glGenVertexArrays(1, &vao);
- glf->glGenBuffers(1, &vbo);
glf->glBindVertexArray(vao);
+ glf->glGenBuffers(1, &vbo);
glf->glBindBuffer(GL_ARRAY_BUFFER, vbo);
glf->glBufferData(GL_ARRAY_BUFFER, nverts * 8 * sizeof (float), verts.data(), GL_STATIC_DRAW);
glf->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof (float), 0);
diff --git a/src/opengl_widget.cc b/src/opengl_widget.cc
index 42bc612..8d7cab5 100644
--- a/src/opengl_widget.cc
+++ b/src/opengl_widget.cc
@@ -1,53 +1,9 @@
#include "opengl_widget.hh"
+#include "load_obj.hh"
+
#include
-
-
-static const GLchar *vertex_shader_source = R"glsl(
-#version 330 core
-
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_norm;
-layout(location = 2) in vec2 in_uv;
-
-out vec3 norm;
-out vec2 uv;
-out vec3 frag_pos;
-
-uniform mat4 proj;
-uniform mat4 view;
-uniform mat4 model;
-
-void main() {
- gl_Position = proj * view * model * vec4(in_pos, 1.0);
- norm = in_norm;
- uv = in_uv;
- frag_pos = vec3(model * vec4(in_pos, 1.0));
-}
-)glsl";
-
-static const GLchar *fragment_shader_source = R"glsl(
-#version 330 core
-
-in vec3 norm;
-in vec2 uv;
-in vec3 frag_pos;
-
-out vec4 final_col;
-
-uniform sampler2D tex;
-
-void main() {
- vec3 light_col = vec3(1, .964, .783);
- vec3 ambient = light_col * .2;
-
- vec3 light_dir = normalize(vec3(5, 10, -8));
- float diff = max(dot(normalize(norm), light_dir), 0.0);
- vec3 diffuse = diff * light_col;
-
- final_col = texture(tex, uv) * vec4(ambient + diffuse, 1);
-}
-)glsl";
+#include
static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
@@ -56,7 +12,10 @@ static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
const void* userParam) {
(void) source; (void) type; (void) id; (void) severity; (void) length;
(void) userParam;
- qDebug() << "OpenGL debug output:" << message;
+ // Those are a bit too verbose
+ if (!QString((const char *) message).startsWith("Shader Stats:")) {
+ qDebug() << "OpenGL debug output:" << message;
+ }
}
@@ -74,6 +33,93 @@ OpenGLWidget::~OpenGLWidget() {
}
+void OpenGLWidget::loadSkybox() {
+ if (!skybox_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/skybox.vert")) {
+ qFatal("Error compiling skybox.vert: %s", skybox_program.log().toLocal8Bit().constData());
+ }
+ if (!skybox_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/skybox.frag")) {
+ qFatal("Error compiling skybox.frag: %s", skybox_program.log().toLocal8Bit().constData());
+ }
+ if (!skybox_program.link()) {
+ qFatal("Error linking the skybox shader program: %s", skybox_program.log().toLocal8Bit().constData());
+ }
+ skybox_program.bind();
+ skybox_program.setUniformValue("skybox", 0);
+
+ // GLfloat skybox_verts[] = {
+ // -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
+ // -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0,
+ // 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
+ // -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
+ // -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
+ // -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0
+ // };
+ QVector skybox_verts = load_obj(":/mdl/cube.obj", 0);
+
+ // OpenGL native VAO version
+ glGenVertexArrays(1, &skybox_vao);
+ glBindVertexArray(skybox_vao);
+ glGenBuffers(1, &skybox_vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, skybox_vbo);
+ glBufferData(GL_ARRAY_BUFFER, skybox_verts.size() * sizeof (GLfloat), skybox_verts.data(), GL_STATIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ glEnableVertexAttribArray(0);
+ glBindVertexArray(0);
+
+ // // QOpenGLVertexArrayObject version
+ // skybox_vao.create();
+ // skybox_vao.bind();
+ // QOpenGLBuffer skybox_vbo(QOpenGLBuffer::VertexBuffer);
+ // skybox_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
+ // skybox_vbo.allocate((void *) skybox_verts.data(), skybox_verts.size() * sizeof (GLfloat));
+ // skybox_program.setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);
+ // skybox_program.enableAttributeArray(0);
+
+ // Skybox texture images
+ QVector skybox_img {
+ QImage(":/img/clouds1_west.jpg").convertToFormat(QImage::Format_RGB888),
+ QImage(":/img/clouds1_east.jpg").convertToFormat(QImage::Format_RGB888),
+ QImage(":/img/clouds1_up.jpg").convertToFormat(QImage::Format_RGB888),
+ QImage(":/img/clouds1_down.jpg").convertToFormat(QImage::Format_RGB888),
+ QImage(":/img/clouds1_south.jpg").convertToFormat(QImage::Format_RGB888),
+ QImage(":/img/clouds1_north.jpg").convertToFormat(QImage::Format_RGB888)
+ };
+ size_t width = skybox_img[0].width();
+ size_t height = skybox_img[0].height();
+
+ // OpenGL native texture version
+ glGenTextures(1, &skybox_tex);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_tex);
+ for (int i = 0; i < 6; i++) {
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,
+ (const GLvoid *) skybox_img[i].constBits());
+ }
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+
+ // // QOpenGLTexture skybox texture version
+ // skybox_tex = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap);
+ // skybox_tex->create();
+ // skybox_tex->setSize(width, skybox_img[0].height(), height);
+ // skybox_tex->setFormat(QOpenGLTexture::RGBA8_UNorm);
+ // skybox_tex->allocateStorage();
+ // for (int i = 0; i < 6; i++) {
+ // skybox_tex->setData(0, 0, (QOpenGLTexture::CubeMapFace) (QOpenGLTexture::CubeMapPositiveX + i),
+ // QOpenGLTexture::RGBA, QOpenGLTexture::UInt8,
+ // (const void*) skybox_img[i].constBits(), 0);
+ // }
+ // skybox_tex->setWrapMode(QOpenGLTexture::ClampToEdge);
+ // skybox_tex->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
+ // skybox_tex->setMagnificationFilter(QOpenGLTexture::LinearMipMapLinear);
+
+ skybox_program.release();
+}
+
+
void OpenGLWidget::initializeGL() {
initializeOpenGLFunctions();
GLint major, minor;
@@ -84,67 +130,22 @@ void OpenGLWidget::initializeGL() {
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);
+ if (!main_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/main.vert")) {
+ qFatal("Error compiling main.vert: %s", main_program.log().toLocal8Bit().constData());
}
-
- /* 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);
+ if (!main_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/main.frag")) {
+ qFatal("Error compiling main.frag: %s", main_program.log().toLocal8Bit().constData());
}
-
- /* Link the shader program. */
- GLuint shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glBindFragDataLocation(shader_program, 0, "final_col");
- 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 (!main_program.link()) {
+ qFatal("Error linking the main shader program: %s", main_program.log().toLocal8Bit().constData());
}
+ main_program.bind();
+ main_program.setUniformValue("tex", 0);
+ main_program.release();
- /* Use it. */
- glUseProgram(shader_program);
-
- /* Get the position attribute. */
- pos_attr = glGetAttribLocation(shader_program, "pos");
-
- proj_attr = glGetUniformLocation(shader_program, "proj");
- view_attr = glGetUniformLocation(shader_program, "view");
- model_attr = glGetUniformLocation(shader_program, "model");
-
- QMatrix4x4 view;
- view.translate(0, 0, 5);
- glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
-
- QMatrix4x4 trans;
- trans.translate(0, 0, -5);
- glUniformMatrix4fv(view_attr, 1, GL_FALSE, trans.data());
-
- glUniform1i(glGetUniformLocation(shader_program, "tex"), 0);
+ loadSkybox();
glClearColor(1, 1, 1, 0);
-
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
@@ -153,9 +154,8 @@ void OpenGLWidget::initializeGL() {
void OpenGLWidget::resizeGL(int w, int h) {
- QMatrix4x4 projection;
- projection.perspective(FOV, (float) w/h, .01, 1000);
- glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
+ proj.setToIdentity();
+ proj.perspective(FOV, (float) w/h, .01, 1000);
}
@@ -164,14 +164,55 @@ void OpenGLWidget::paintGL() {
QMatrix4x4 trans;
trans.translate(0, 0, -cam_dist);
QMatrix4x4 view = trans * rot;
- glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
+
+ // skybox_vao.bind();
+ // glActiveTexture(GL_TEXTURE0);
+ // glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_tex);
+ // // skybox_tex->bind();
+ // glDrawArrays(GL_TRIANGLES, 0, 36);
+ // // skybox_tex->release();
+ // skybox_vao.release();
+
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_LEQUAL);
+ skybox_program.bind();
+ skybox_program.setUniformValue("proj", proj);
+ skybox_program.setUniformValue("view", view);
+ // skybox_program.setUniformValue("model", QMatrix4x4());
+ glBindVertexArray(skybox_vao);
glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_tex);
+ // skybox_tex->bind();
+ // skybox_vao.bind();
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ // skybox_tex->release();
+ skybox_program.release();
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LESS);
+
+ main_program.bind();
+ main_program.setUniformValue("proj", proj);
+ main_program.setUniformValue("view", view);
+ glActiveTexture(GL_TEXTURE0);
+
+ // main_program.setUniformValue("model", QMatrix4x4());
+ // skybox_vao.bind();
+ // glDrawArrays(GL_TRIANGLES, 0, 36);
+
+ // skybox_program.bind();
+ // skybox_program.setUniformValue("proj", proj);
+ // skybox_program.setUniformValue("view", view);
+
for (const OpenGLMesh &mesh : meshes) {
- glUniformMatrix4fv(model_attr, 1, GL_FALSE, mesh.mat.data());
+ main_program.setUniformValue("model", mesh.mat);
glBindVertexArray(mesh.vao);
mesh.tex->bind();
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
+ mesh.tex->release();
}
+ main_program.release();
+
}
diff --git a/src/opengl_widget.hh b/src/opengl_widget.hh
index 9259784..5bd4a07 100644
--- a/src/opengl_widget.hh
+++ b/src/opengl_widget.hh
@@ -7,6 +7,8 @@
#include
#include
#include
+#include
+#include
#define FOV 70
@@ -14,12 +16,21 @@
class OpenGLWidget : public QOpenGLWidget, public QOpenGLFunctions_4_4_Core {
Q_OBJECT
- GLuint pos_attr, proj_attr, view_attr, model_attr;
-
- QMatrix4x4 rot, rot_start;
+ QMatrix4x4 rot, rot_start, proj;
GLfloat cam_dist = 1;
QPoint mouse_pos;
+ QOpenGLShaderProgram main_program;
+ QOpenGLShaderProgram skybox_program;
+ // QOpenGLTexture *skybox_tex;
+ GLuint skybox_tex;
+ // QOpenGLVertexArrayObject skybox_vao;
+ // QOpenGLBuffer skybox_vbo;
+ GLuint skybox_vao;
+ GLuint skybox_vbo;
+
+ void loadSkybox();
+
protected:
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);