I’ve just started writing my own game engine in C and I’m stuck in the beginning with rendering a cube.
The problem is that the front face of the cube renders at the back of the back face of the cube. (See image below)
Here is the source code (main.c):
#include <stdio.h>
#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "quantum/QUANTUM_utils.h"
#include "quantum/gfx/QUANTUM_shader.h"
#include "quantum/gfx/QUANTUM_texture.h"
#include "quantum/gfx/objects/QUANTUM_VAO.h"
#include "quantum/gfx/objects/QUANTUM_VBO.h"
#include "quantum/gfx/objects/QUANTUM_EBO.h"
#include "quantum/math/QUANTUM_math.h"
#define QUANTUM_WND_W 1720.0f
#define QUANTUM_WND_H 880.0f
#define QUANTUM_WND_X 100.0f
#define QUANTUM_WND_Y 100.0f
#define QUANTUM_WND_TITLE "Quantum Engine"
#define QUANTUM_OPENGL_VERSION_MAJOR 4
#define QUANTUM_OPENGL_VERSION_MINOR 6
#define QUANTUM_WIREFRAME_RENDERER 0
static void error_callback(GLint error, const GLchar *description) {
fprintf(stderr, "Error, %i: %s", error, description);
}
static void framebuffer_callback(__attribute__((unused)) GLFWwindow *window, GLint width, GLint height) {
glViewport(0, 0, width, height);
}
int main() {
glfwSetErrorCallback(error_callback);
if (!glfwInit()) {
QUANTUM_LOG_ERROR("GLFW initialization failed\n");
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, QUANTUM_OPENGL_VERSION_MAJOR);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, QUANTUM_OPENGL_VERSION_MINOR);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(QUANTUM_WND_W, QUANTUM_WND_H, QUANTUM_WND_TITLE, NULL, NULL);
if (!window) {
QUANTUM_LOG_ERROR("GLFW window initialization failed\n");
return -2;
}
glfwMakeContextCurrent(window);
glfwSetWindowPos(window, QUANTUM_WND_X, QUANTUM_WND_Y);
glfwSetFramebufferSizeCallback(window, framebuffer_callback);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
QUANTUM_LOG_ERROR("GLAD initialization failed\n");
glfwTerminate();
return -3;
}
glEnable(GL_DEPTH_TEST);
QUANTUM_shader shader = QUANTUM_shader_create("vertex.vert", "fragment.frag");
QUANTUM_shader_compile(&shader);
GLfloat vertices[] = {
/* @formatter:off */
/* Positions */ /* UV */
/* Back */
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
/* Front */
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
/* Left */
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
/* Right */
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
/* Down */
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
/* Up */
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
/* @formatter:on */
};
QUANTUM_VAO VAO = QUANTUM_VAO_create(false);
QUANTUM_VBO VBO = QUANTUM_VBO_create(false);
QUANTUM_VAO_bind(&VAO);
QUANTUM_VBO_bind(&VBO);
QUANTUM_VBO_upload(&VBO, sizeof(vertices), vertices);
QUANTUM_VAO_attrib(&VAO, 0, 3, GL_FLOAT, 5 * sizeof(GLfloat), 0);
QUANTUM_VAO_attrib(&VAO, 1, 2, GL_FLOAT, 5 * sizeof(GLfloat), 3 * sizeof(GLfloat));
QUANTUM_VAO_unbind(&VAO);
QUANTUM_VBO_unbind(&VBO);
QUANTUM_texture texture = QUANTUM_texture_create("cat.png");
#if QUANTUM_WIREFRAME_RENDERER > 0
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLint width = 0, height = 0;
glfwGetWindowSize(window, &width, &height);
QUANTUM_texture_bind(&texture);
QUANTUM_shader_bind(&shader);
QUANTUM_mat4x4f model = QUANTUM_mat4x4f_create_identity_matrix();
QUANTUM_mat4x4f view = QUANTUM_mat4x4f_create_identity_matrix();
QUANTUM_mat4x4f projection = QUANTUM_mat4x4f_create_identity_matrix();
view = QUANTUM_mat4x4f_translate(&view, QUANTUM_vec3f_new(0.0f, 0.0f, -3.0f));
projection = QUANTUM_mat4x4f_perspective(RAD(45.0f), (GLfloat) width / (GLfloat) height, 0.1f, 100.0f);
QUANTUM_shader_uniform_mat4x4f(&shader, "u_model", &model);
QUANTUM_shader_uniform_mat4x4f(&shader, "u_view", &view);
QUANTUM_shader_uniform_mat4x4f(&shader, "u_projection", &projection);
QUANTUM_VAO_bind(&VAO);
glDrawArrays(GL_TRIANGLES, 0, (sizeof(vertices) / sizeof(GLfloat)) / 5);
glfwSwapBuffers(window);
}
QUANTUM_shader_delete(&shader);
QUANTUM_VAO_delete(&VAO);
QUANTUM_VBO_delete(&VBO);
glfwTerminate();
return 0;
}
I think there is no logic errors. When I was googling about this problem, I found that I should enable depth test, however it is enabled in my program.
Here is my matrix perspective function:
QUANTUM_mat4x4f QUANTUM_mat4x4f_perspective(GLfloat fov, GLfloat aspect, GLfloat far, GLfloat near) {
return (QUANTUM_mat4x4f) {
1.0f / (aspect * tanf(fov * 0.5f)), 0, 0, 0,
0, 1.0f / (tanf(fov * 0.5f)), 0, 0,
0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near),
0, 0, -1, 0
};
}
And if you need, here is matrix struct defenition:
typedef struct QUANTUM_mat4x4f {
GLfloat mat[4][4];
} QUANTUM_mat4x4f;
Here are my shader programs, in case there’s something wrong with them, but I don’t think so.
Vertex:
#version 460 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uv;
out vec2 v_uv;
uniform mat4x4 u_model, u_view, u_projection;
void main() {
gl_Position = u_projection * u_view * u_model * vec4(position, 1.0f);
v_uv = uv;
}
Fragment:
#version 460 core
out vec4 frag_color;
in vec2 v_uv;
uniform sampler2D u_texture;
void main() {
frag_color = texture(u_texture, v_uv);
}
P.S Sorry for my english, I’m not a native speaker.