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_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
|
||||
|
@ -3,10 +3,20 @@
|
||||
<qresource>
|
||||
<file>mdl/dji600.obj</file>
|
||||
<file>mdl/dji600.mtl</file>
|
||||
<file>mdl/dji600.jpg</file>
|
||||
<file>mdl/test.obj</file>
|
||||
<file>mdl/test.mtl</file>
|
||||
<file>mdl/black.jpg</file>
|
||||
<file>mdl/ground.jpg</file>
|
||||
<file>mdl/cube.obj</file>
|
||||
|
||||
<file>img/dji600.jpg</file>
|
||||
<file>img/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>
|
||||
</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 "opengl_widget.hh"
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "tiny_obj_loader.h"
|
||||
#include "load_obj.hh"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QDebug>
|
||||
@ -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<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());
|
||||
QVector<GLfloat> 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);
|
||||
}
|
||||
|
||||
|
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;
|
||||
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);
|
||||
|
@ -1,53 +1,9 @@
|
||||
#include "opengl_widget.hh"
|
||||
|
||||
#include "load_obj.hh"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
|
||||
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 <QOpenGLBuffer>
|
||||
|
||||
|
||||
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) {
|
||||
(void) source; (void) type; (void) id; (void) severity; (void) length;
|
||||
(void) userParam;
|
||||
// Those are a bit too verbose
|
||||
if (!QString((const char *) message).startsWith("Shader Stats:")) {
|
||||
qDebug() << "OpenGL debug output:" << message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <QMatrix4x4>
|
||||
#include <QOpenGLFunctions_4_4_Core>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QOpenGLBuffer>
|
||||
|
||||
#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);
|
||||
|