m2-ar-projet/src/opengl_widget.cc

144 lines
3.7 KiB
C++

#include "opengl_widget.hh"
static const GLchar *vertex_shader_source = R"glsl(
#version 330 core
layout(location = 0) in vec3 pos;
uniform mat4 proj;
uniform mat4 view;
uniform mat4 model;
void main() {
gl_Position = proj * view * model * vec4(pos, 1.0);
}
)glsl";
static const GLchar *fragment_shader_source = R"glsl(
#version 330 core
out vec4 final_col;
void main() {
final_col = vec4(0, 0, 0, 1);
}
)glsl";
static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar* message,
const void* userParam) {
(void) source; (void) type; (void) id; (void) severity; (void) length;
(void) userParam;
qDebug() << "OpenGL debug output:" << message;
}
OpenGLWidget *OpenGLWidget::instance = nullptr;
OpenGLWidget::OpenGLWidget(QWidget *parent)
:QOpenGLWidget(parent) {
OpenGLWidget::instance = this;
}
OpenGLWidget::~OpenGLWidget() {
OpenGLWidget::instance = nullptr;
}
void OpenGLWidget::initializeGL() {
initializeOpenGLFunctions();
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
qDebug("OpenGL version %d.%d", major, minor);
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);
}
/* 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);
}
/* Link the shader program. */
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glBindFragDataLocation(shader_program, 0, "out_color");
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);
}
/* 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());
glClearColor(1, 1, 1, 0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
emit initialized();
}
void OpenGLWidget::resizeGL(int w, int h) {
QMatrix4x4 projection;
projection.perspective(FOV, (float) w/h, .1, 100);
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
}
void OpenGLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (const OpenGLMesh &mesh : meshes) {
glUniformMatrix4fv(model_attr, 1, GL_FALSE, mesh.mat.data());
glBindVertexArray(mesh.vao);
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
}
}