skybox
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
img/clouds1_down (copie).jpg
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
img/clouds1_down.jpg
Normal file
After Width: | Height: | Size: 313 KiB |
BIN
img/clouds1_east.jpg
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
img/clouds1_north.jpg
Normal file
After Width: | Height: | Size: 199 KiB |
BIN
img/clouds1_south.jpg
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
img/clouds1_up (copie).jpg
Normal file
After Width: | Height: | Size: 238 KiB |
BIN
img/clouds1_up.jpg
Normal file
After Width: | Height: | Size: 494 KiB |
BIN
img/clouds1_west.jpg
Normal file
After Width: | Height: | Size: 202 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 6.5 MiB After Width: | Height: | Size: 6.5 MiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
30
mdl/cube.obj
Normal file
@ -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
|
@ -11,8 +11,10 @@ SOURCES += src/main_window.cc
|
|||||||
SOURCES += src/opengl_mesh.cc
|
SOURCES += src/opengl_mesh.cc
|
||||||
SOURCES += src/opengl_widget.cc
|
SOURCES += src/opengl_widget.cc
|
||||||
SOURCES += src/drone_controller.cc
|
SOURCES += src/drone_controller.cc
|
||||||
|
SOURCES += src/load_obj.cc
|
||||||
|
|
||||||
HEADERS += src/main_window.hh
|
HEADERS += src/main_window.hh
|
||||||
HEADERS += src/opengl_mesh.hh
|
HEADERS += src/opengl_mesh.hh
|
||||||
HEADERS += src/opengl_widget.hh
|
HEADERS += src/opengl_widget.hh
|
||||||
HEADERS += src/drone_controller.hh
|
HEADERS += src/drone_controller.hh
|
||||||
|
HEADERS += src/load_obj.hh
|
||||||
|
@ -3,10 +3,20 @@
|
|||||||
<qresource>
|
<qresource>
|
||||||
<file>mdl/dji600.obj</file>
|
<file>mdl/dji600.obj</file>
|
||||||
<file>mdl/dji600.mtl</file>
|
<file>mdl/dji600.mtl</file>
|
||||||
<file>mdl/dji600.jpg</file>
|
<file>mdl/cube.obj</file>
|
||||||
<file>mdl/test.obj</file>
|
|
||||||
<file>mdl/test.mtl</file>
|
<file>img/dji600.jpg</file>
|
||||||
<file>mdl/black.jpg</file>
|
<file>img/ground.jpg</file>
|
||||||
<file>mdl/ground.jpg</file>
|
<file>img/clouds1_up.jpg</file>
|
||||||
|
<file>img/clouds1_down.jpg</file>
|
||||||
|
<file>img/clouds1_north.jpg</file>
|
||||||
|
<file>img/clouds1_east.jpg</file>
|
||||||
|
<file>img/clouds1_south.jpg</file>
|
||||||
|
<file>img/clouds1_west.jpg</file>
|
||||||
|
|
||||||
|
<file>shaders/main.vert</file>
|
||||||
|
<file>shaders/main.frag</file>
|
||||||
|
<file>shaders/skybox.vert</file>
|
||||||
|
<file>shaders/skybox.frag</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
20
shaders/main.frag
Normal file
@ -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);
|
||||||
|
}
|
20
shaders/main.vert
Normal file
@ -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));
|
||||||
|
}
|
23
shaders/skybox.frag
Normal file
@ -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);
|
||||||
|
}
|
28
shaders/skybox.vert
Normal file
@ -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;
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
#include "drone_controller.hh"
|
#include "drone_controller.hh"
|
||||||
#include "opengl_widget.hh"
|
#include "opengl_widget.hh"
|
||||||
|
#include "load_obj.hh"
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION
|
|
||||||
#include "tiny_obj_loader.h"
|
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@ -26,62 +24,8 @@ OpenGLMesh *Drone::mesh = nullptr;
|
|||||||
|
|
||||||
Drone::Drone() {
|
Drone::Drone() {
|
||||||
if (!mesh_initialized) {
|
if (!mesh_initialized) {
|
||||||
QFile obj_file(":/mdl/dji600.obj");
|
QVector<GLfloat> verts = load_obj(":/mdl/dji600.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS);
|
||||||
QFile mtl_file(":/mdl/dji600.mtl");
|
QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/img/dji600.jpg").mirrored());
|
||||||
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<float> 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());
|
|
||||||
// texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
|
// texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
|
||||||
// texture->setMagnificationFilter(QOpenGLTexture::Linear);
|
// texture->setMagnificationFilter(QOpenGLTexture::Linear);
|
||||||
mesh = new OpenGLMesh(verts, texture);
|
mesh = new OpenGLMesh(verts, texture);
|
||||||
@ -147,7 +91,7 @@ DroneController::DroneController(const QJsonObject &json)
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpenGLWidget::instance->makeCurrent();
|
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({
|
OpenGLMesh *ground = new OpenGLMesh({
|
||||||
-100, 0, -100, 0, 1, 0, 0, 0,
|
-100, 0, -100, 0, 1, 0, 0, 0,
|
||||||
100, 0, -100, 0, 1, 0, 1, 0,
|
100, 0, -100, 0, 1, 0, 1, 0,
|
||||||
@ -158,6 +102,7 @@ DroneController::DroneController(const QJsonObject &json)
|
|||||||
}, ground_tex);
|
}, ground_tex);
|
||||||
OpenGLWidget::instance->meshes.append(*ground);
|
OpenGLWidget::instance->meshes.append(*ground);
|
||||||
OpenGLWidget::instance->doneCurrent();
|
OpenGLWidget::instance->doneCurrent();
|
||||||
|
|
||||||
connect(&timer, &QTimer::timeout, this, &DroneController::step);
|
connect(&timer, &QTimer::timeout, this, &DroneController::step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
src/load_obj.cc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "load_obj.hh"
|
||||||
|
|
||||||
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
|
#include "tiny_obj_loader.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
QVector<GLfloat> 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<GLfloat> 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;
|
||||||
|
}
|
13
src/load_obj.hh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef LOAD_OBJ_HH
|
||||||
|
#define LOAD_OBJ_HH
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
|
#define LOAD_OBJ_NORMALS 1 << 0
|
||||||
|
#define LOAD_OBJ_UVS 1 << 1
|
||||||
|
|
||||||
|
QVector<GLfloat> load_obj(const char *path, int flags);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -10,8 +10,8 @@ OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex)
|
|||||||
QOpenGLFunctions_4_4_Core *glf = OpenGLWidget::instance;
|
QOpenGLFunctions_4_4_Core *glf = OpenGLWidget::instance;
|
||||||
nverts = verts.size() / 8;
|
nverts = verts.size() / 8;
|
||||||
glf->glGenVertexArrays(1, &vao);
|
glf->glGenVertexArrays(1, &vao);
|
||||||
glf->glGenBuffers(1, &vbo);
|
|
||||||
glf->glBindVertexArray(vao);
|
glf->glBindVertexArray(vao);
|
||||||
|
glf->glGenBuffers(1, &vbo);
|
||||||
glf->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glf->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
glf->glBufferData(GL_ARRAY_BUFFER, nverts * 8 * sizeof (float), verts.data(), GL_STATIC_DRAW);
|
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);
|
glf->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof (float), 0);
|
||||||
|
@ -1,53 +1,9 @@
|
|||||||
#include "opengl_widget.hh"
|
#include "opengl_widget.hh"
|
||||||
|
|
||||||
|
#include "load_obj.hh"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QOpenGLBuffer>
|
||||||
|
|
||||||
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";
|
|
||||||
|
|
||||||
|
|
||||||
static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
|
static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
|
||||||
@ -56,8 +12,11 @@ static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
|
|||||||
const void* userParam) {
|
const void* userParam) {
|
||||||
(void) source; (void) type; (void) id; (void) severity; (void) length;
|
(void) source; (void) type; (void) id; (void) severity; (void) length;
|
||||||
(void) userParam;
|
(void) userParam;
|
||||||
|
// Those are a bit too verbose
|
||||||
|
if (!QString((const char *) message).startsWith("Shader Stats:")) {
|
||||||
qDebug() << "OpenGL debug output:" << message;
|
qDebug() << "OpenGL debug output:" << message;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenGLWidget *OpenGLWidget::instance = nullptr;
|
OpenGLWidget *OpenGLWidget::instance = nullptr;
|
||||||
@ -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<GLfloat> 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<QImage> 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() {
|
void OpenGLWidget::initializeGL() {
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
GLint major, minor;
|
GLint major, minor;
|
||||||
@ -84,67 +130,22 @@ void OpenGLWidget::initializeGL() {
|
|||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
glDebugMessageCallback(opengl_debug_cb, 0);
|
glDebugMessageCallback(opengl_debug_cb, 0);
|
||||||
|
|
||||||
/* Compile the vertex shader. */
|
if (!main_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/main.vert")) {
|
||||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
qFatal("Error compiling main.vert: %s", main_program.log().toLocal8Bit().constData());
|
||||||
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::Fragment, ":/shaders/main.frag")) {
|
||||||
/* Compile the fragment shader. */
|
qFatal("Error compiling main.frag: %s", main_program.log().toLocal8Bit().constData());
|
||||||
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.link()) {
|
||||||
/* Link the shader program. */
|
qFatal("Error linking the main shader program: %s", main_program.log().toLocal8Bit().constData());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
main_program.bind();
|
||||||
|
main_program.setUniformValue("tex", 0);
|
||||||
|
main_program.release();
|
||||||
|
|
||||||
/* Use it. */
|
loadSkybox();
|
||||||
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);
|
|
||||||
|
|
||||||
glClearColor(1, 1, 1, 0);
|
glClearColor(1, 1, 1, 0);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
@ -153,9 +154,8 @@ void OpenGLWidget::initializeGL() {
|
|||||||
|
|
||||||
|
|
||||||
void OpenGLWidget::resizeGL(int w, int h) {
|
void OpenGLWidget::resizeGL(int w, int h) {
|
||||||
QMatrix4x4 projection;
|
proj.setToIdentity();
|
||||||
projection.perspective(FOV, (float) w/h, .01, 1000);
|
proj.perspective(FOV, (float) w/h, .01, 1000);
|
||||||
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -164,14 +164,55 @@ void OpenGLWidget::paintGL() {
|
|||||||
QMatrix4x4 trans;
|
QMatrix4x4 trans;
|
||||||
trans.translate(0, 0, -cam_dist);
|
trans.translate(0, 0, -cam_dist);
|
||||||
QMatrix4x4 view = trans * rot;
|
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);
|
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) {
|
for (const OpenGLMesh &mesh : meshes) {
|
||||||
glUniformMatrix4fv(model_attr, 1, GL_FALSE, mesh.mat.data());
|
main_program.setUniformValue("model", mesh.mat);
|
||||||
glBindVertexArray(mesh.vao);
|
glBindVertexArray(mesh.vao);
|
||||||
mesh.tex->bind();
|
mesh.tex->bind();
|
||||||
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
|
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
|
||||||
|
mesh.tex->release();
|
||||||
}
|
}
|
||||||
|
main_program.release();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QOpenGLFunctions_4_4_Core>
|
#include <QOpenGLFunctions_4_4_Core>
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
|
#include <QOpenGLVertexArrayObject>
|
||||||
|
#include <QOpenGLBuffer>
|
||||||
|
|
||||||
#define FOV 70
|
#define FOV 70
|
||||||
|
|
||||||
@ -14,12 +16,21 @@
|
|||||||
class OpenGLWidget : public QOpenGLWidget, public QOpenGLFunctions_4_4_Core {
|
class OpenGLWidget : public QOpenGLWidget, public QOpenGLFunctions_4_4_Core {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
GLuint pos_attr, proj_attr, view_attr, model_attr;
|
QMatrix4x4 rot, rot_start, proj;
|
||||||
|
|
||||||
QMatrix4x4 rot, rot_start;
|
|
||||||
GLfloat cam_dist = 1;
|
GLfloat cam_dist = 1;
|
||||||
QPoint mouse_pos;
|
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:
|
protected:
|
||||||
virtual void mousePressEvent(QMouseEvent *e);
|
virtual void mousePressEvent(QMouseEvent *e);
|
||||||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|