This commit is contained in:
ccolin 2020-12-28 17:36:45 +01:00
parent ef37119f4e
commit f3a3466597
25 changed files with 388 additions and 177 deletions

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
img/clouds1_down.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

BIN
img/clouds1_east.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
img/clouds1_north.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
img/clouds1_south.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

BIN
img/clouds1_up (copie).jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

BIN
img/clouds1_up.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

BIN
img/clouds1_west.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 6.5 MiB

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

30
mdl/cube.obj Normal file
View 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

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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;
}

View File

@ -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
View 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
View 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

View File

@ -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);

View File

@ -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();
} }

View File

@ -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);