feat: add model matrix transformation hierarchy and delta time tracking
This commit is contained in:
@@ -20,7 +20,9 @@ add_executable(BeyondDepth src/main.c
|
|||||||
external/glad/src/glad.c
|
external/glad/src/glad.c
|
||||||
src/engine/renderer/shaders/shader.c
|
src/engine/renderer/shaders/shader.c
|
||||||
src/engine/renderer/shaders/shader.h
|
src/engine/renderer/shaders/shader.h
|
||||||
src/engine/renderer/data/engine_data.h)
|
src/engine/renderer/data/engine_data.h
|
||||||
|
src/engine/renderer/mesh/mesh.c
|
||||||
|
src/engine/renderer/mesh/mesh.h)
|
||||||
|
|
||||||
set_target_properties(BeyondDepth PROPERTIES WIN32_EXECUTABLE FALSE)
|
set_target_properties(BeyondDepth PROPERTIES WIN32_EXECUTABLE FALSE)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "../..//core/logger/log.h"
|
#include "../..//core/logger/log.h"
|
||||||
|
#include <cglm/cglm.h>
|
||||||
|
#include "../shaders/shader.h"
|
||||||
|
|
||||||
void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
||||||
// copy initial_pos vector
|
// copy initial_pos vector
|
||||||
@@ -16,9 +18,11 @@ void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
|||||||
glm_vec3_copy((vec3){0.0f, 1.0f, 0.0f}, self->Up);
|
glm_vec3_copy((vec3){0.0f, 1.0f, 0.0f}, self->Up);
|
||||||
|
|
||||||
// initialize controls and viewport
|
// initialize controls and viewport
|
||||||
self->speed = 0.1f;
|
self->speed = 0.9f;
|
||||||
self->sensitivity = 100.0f;
|
self->sensitivity = 3.5f;
|
||||||
self->FOV_deg = 45.0f;
|
self->FOV_deg = 45.0f;
|
||||||
|
self->yaw = -90.0f;
|
||||||
|
self->pitch = 0.0f;
|
||||||
|
|
||||||
self->width = width;
|
self->width = width;
|
||||||
self->height = height;
|
self->height = height;
|
||||||
@@ -27,13 +31,6 @@ void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
|||||||
glm_mat4_identity(self->View);
|
glm_mat4_identity(self->View);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Camera l_camera = {
|
|
||||||
.Position = { 0.0f, 0.0f, 0.0f },
|
|
||||||
.Orientation = { 0.0f, 0.0f, -1.0f },
|
|
||||||
.Up = { 0.0f, 1.0f, 0.0f }
|
|
||||||
};*/
|
|
||||||
|
|
||||||
void camera_update_view_matrix(Camera *self) {
|
void camera_update_view_matrix(Camera *self) {
|
||||||
// calc the center or target point (Pos + Orientation)
|
// calc the center or target point (Pos + Orientation)
|
||||||
vec3 target;
|
vec3 target;
|
||||||
@@ -50,31 +47,81 @@ void camera_update_projection(Camera *self, float nearPlane, float farPlane, mat
|
|||||||
|
|
||||||
// TODO: Update matrix function signature to accept camera entity?
|
// TODO: Update matrix function signature to accept camera entity?
|
||||||
// change name to camera_upload_matrix for clarity?
|
// change name to camera_upload_matrix for clarity?
|
||||||
void camera_matrix_to_shader(Camera *self, GLuint shader_program_ID, const char *uniform_name) {
|
void camera_matrix_to_shader(Camera *self, Shader *shader, const char *uniform_name) {
|
||||||
// update the view matrix first, camera position might have moved
|
// update the view matrix first, camera position might have moved
|
||||||
camera_update_view_matrix(self);
|
camera_update_view_matrix(self);
|
||||||
|
|
||||||
// calculate projection matrix (P) with temporary matrix 'projection' for the result
|
// calculate projection matrix (P) with temporary matrix 'projection' for the result
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
camera_update_projection(self, 0.1f, 100.0f, projection);
|
camera_update_projection(self, 0.001f, 100.0f, projection);
|
||||||
|
|
||||||
// combine the matrices -- P * V -> PV
|
// combine the matrices -- P * V -> PV
|
||||||
mat4 view_projection;
|
mat4 view_projection;
|
||||||
glm_mat4_mul(projection, self->View, view_projection);
|
glm_mat4_mul(projection, self->View, view_projection);
|
||||||
|
|
||||||
// get uniform location
|
// get uniform location
|
||||||
GLint uniform_location = glGetUniformLocation(shader_program_ID, uniform_name);
|
GLint uniform_location = shader->camMatrixLocation;
|
||||||
|
|
||||||
if (uniform_location == -1) {
|
if (uniform_location == -1) {
|
||||||
log_error("Warning: Uniform '%s' not found in shader program %u.\n", uniform_name, shader_program_ID);
|
// log_error("Warning: Uniform '%s' not found in shader program %u.\n", uniform_name, shader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// upload combined matrix to the shader
|
// upload combined matrix to the shader
|
||||||
// view_projection[0] array pointer decays to first value
|
// view_projection[0] array pointer decays to first value
|
||||||
glUniformMatrix4fv(uniform_location, 1, GL_FALSE, view_projection[0]);
|
glUniformMatrix4fv(uniform_location, 1, GL_FALSE, *view_projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void camera_inputs(Camera *self, SDL_Event *event) {
|
void camera_process_keyboard(Camera *self, const Uint8 *keyState, float deltaTime) {
|
||||||
// TODO: implementation for handling keyboard/mouse inputs for camera
|
vec3 move;
|
||||||
|
float current_speed = self->speed * deltaTime;
|
||||||
|
|
||||||
|
// forward/back
|
||||||
|
if (keyState[SDL_SCANCODE_W]) {
|
||||||
|
glm_vec3_scale(self->Orientation, current_speed, move);
|
||||||
|
glm_vec3_add(self->Position, move, self->Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyState[SDL_SCANCODE_S]) {
|
||||||
|
glm_vec3_scale(self->Orientation, current_speed, move);
|
||||||
|
glm_vec3_sub(self->Position, move, self->Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// strafe left/right
|
||||||
|
vec3 right;
|
||||||
|
glm_vec3_cross(self->Orientation, self->Up, right);
|
||||||
|
glm_vec3_normalize(right);
|
||||||
|
|
||||||
|
if (keyState[SDL_SCANCODE_A]) {
|
||||||
|
glm_vec3_scale(right, current_speed, move);
|
||||||
|
glm_vec3_sub(self->Position, move, self->Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyState[SDL_SCANCODE_D]) {
|
||||||
|
glm_vec3_scale(right, current_speed, move);
|
||||||
|
glm_vec3_add(self->Position, move, self->Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add deltaTime arg for smoother rotation
|
||||||
|
void camera_process_mouse(Camera *self, float xoffset, float yoffset, float deltaTime) {
|
||||||
|
float effective_sensitivity = self->sensitivity * deltaTime;
|
||||||
|
xoffset *= effective_sensitivity;
|
||||||
|
yoffset *= effective_sensitivity;
|
||||||
|
|
||||||
|
self->yaw += xoffset;
|
||||||
|
self->pitch += yoffset;
|
||||||
|
|
||||||
|
// clamps the pitch to prevent camera from flipping upside down
|
||||||
|
if (self->pitch > 89.0f)
|
||||||
|
self->pitch = 89.0f;
|
||||||
|
if (self->pitch < -89.0f)
|
||||||
|
self->pitch = -89.0f;
|
||||||
|
|
||||||
|
// calc new orientation vector from yaw and pitch
|
||||||
|
vec3 new_orientation;
|
||||||
|
new_orientation[0] = cos(glm_rad(self->yaw)) * cos(glm_rad(self->pitch));
|
||||||
|
new_orientation[1] = sin(glm_rad(self->pitch));
|
||||||
|
new_orientation[2] = sin(glm_rad(self->yaw)) * cos(glm_rad(self->pitch));
|
||||||
|
glm_vec3_normalize_to(new_orientation, self->Orientation);
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,8 @@ typedef struct {
|
|||||||
vec3 Position;
|
vec3 Position;
|
||||||
vec3 Orientation;
|
vec3 Orientation;
|
||||||
vec3 Up;
|
vec3 Up;
|
||||||
|
float yaw;
|
||||||
|
float pitch;
|
||||||
float speed;
|
float speed;
|
||||||
float sensitivity;
|
float sensitivity;
|
||||||
float FOV_deg;
|
float FOV_deg;
|
||||||
@@ -32,9 +34,12 @@ void camera_update_view_matrix(Camera *self);
|
|||||||
void camera_update_projection(Camera *self, float nearPlane, float forPlane, mat4 dest);
|
void camera_update_projection(Camera *self, float nearPlane, float forPlane, mat4 dest);
|
||||||
|
|
||||||
// generates (projection * view) and uploads to the shader program
|
// generates (projection * view) and uploads to the shader program
|
||||||
void camera_matrix_to_shader(Camera *self, GLuint shader_program_ID, const char *uniform_name);
|
void camera_matrix_to_shader(Camera *self, Shader *shader, const char *uniform_name);
|
||||||
|
|
||||||
// TODO: Input handling (needs full SDL context later)
|
// TODO: Input handling (needs full SDL context later)
|
||||||
void camera_inputs(Camera *self, SDL_Event *event);
|
void camera_inputs(Camera *self, SDL_Event *event);
|
||||||
|
|
||||||
|
void camera_process_keyboard(Camera *self, const Uint8 *keystate, float deltaTime);
|
||||||
|
void camera_process_mouse(Camera *self, float xoffset, float yoffset, float deltaTime);
|
||||||
|
|
||||||
#endif //CAMERA_H
|
#endif //CAMERA_H
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include "../camera/camera.h"
|
#include "../camera/camera.h"
|
||||||
|
#include "../mesh/mesh.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Camera instance
|
// Camera instance
|
||||||
@@ -15,10 +16,17 @@ typedef struct {
|
|||||||
// Shader program instance
|
// Shader program instance
|
||||||
Shader shader;
|
Shader shader;
|
||||||
|
|
||||||
|
// Mesh instance
|
||||||
|
Mesh triangle_mesh;
|
||||||
|
mat4 pyramidModel;
|
||||||
|
|
||||||
// Keep track of window size
|
// Keep track of window size
|
||||||
int window_width;
|
int window_width;
|
||||||
int window_height;
|
int window_height;
|
||||||
|
|
||||||
|
float lastFrameTime; // time of the previous frame
|
||||||
|
float deltaTime; // time elapsed since the last frame
|
||||||
|
|
||||||
// TODO: Add other components, SDL_Window* or Meshes, etc...
|
// TODO: Add other components, SDL_Window* or Meshes, etc...
|
||||||
} Engine_Data;
|
} Engine_Data;
|
||||||
|
|
||||||
|
|||||||
93
src/engine/renderer/mesh/mesh.c
Normal file
93
src/engine/renderer/mesh/mesh.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
//
|
||||||
|
// Created by Tristan on 10/17/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "../../core/logger/log.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// Position // Color
|
||||||
|
// X Y Z R G B // Index
|
||||||
|
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 0: Apex
|
||||||
|
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 1: Base Corner 1 (Red)
|
||||||
|
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // 2: Base Corner 2 (Green)
|
||||||
|
0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f // 3: Base Corner 3 (Blue)
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t vertices_size = sizeof(vertices);
|
||||||
|
|
||||||
|
GLuint indices[] = {
|
||||||
|
// side 1: (Apex, C1, C2)
|
||||||
|
0, 1, 2, // vertices that form the triangle
|
||||||
|
|
||||||
|
// side2: (Apex, C2, C3)
|
||||||
|
0, 2, 3,
|
||||||
|
|
||||||
|
// side 3: (Apex, C3, C1)
|
||||||
|
0, 3, 1,
|
||||||
|
|
||||||
|
// base: (C1, C3, C2) - order is crucial for culling
|
||||||
|
1, 3, 2
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void mesh_init(Mesh *self, GLfloat *vertices, GLsizei vertices_size, GLuint *indices, GLsizei num_indices) {
|
||||||
|
self->num_indices = num_indices;
|
||||||
|
|
||||||
|
// generate buffers, vao, vbo, ebo
|
||||||
|
glGenVertexArrays(1, &self->VAO);
|
||||||
|
glGenBuffers(1, &self->VBO);
|
||||||
|
glGenBuffers(1, &self->EBO);
|
||||||
|
|
||||||
|
// bind the VAO
|
||||||
|
glBindVertexArray(self->VAO);
|
||||||
|
|
||||||
|
// bind and upload VBO data
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, self->VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// bind and upload ebo data
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->EBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * num_indices, indices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// configure vertex attributes
|
||||||
|
// a. Position attribute (layout = 0)
|
||||||
|
// 3 floats per pos, stride = 6 floats total (3 pos + 3 colour), offset is 0
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// b. Color attribute (layout = 1)
|
||||||
|
// 3 floats per color, stride = 6 floats total, offset is 3 floats (after pos)
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
// TODO: hader also expects layout = 2 but lazy, pray no crash
|
||||||
|
|
||||||
|
// unbind the VAO (so it can't be modified)
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
log_info("Mesh initialized with VAO: %u", self->VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh_draw(Mesh *self) {
|
||||||
|
// bind the vao
|
||||||
|
glBindVertexArray(self->VAO);
|
||||||
|
|
||||||
|
// draw the triangle
|
||||||
|
glDrawElements(GL_TRIANGLES, self->num_indices, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// unbind
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh_delete(Mesh *self) {
|
||||||
|
glDeleteVertexArrays(1, &self->VAO);
|
||||||
|
glDeleteBuffers(1, &self->VBO);
|
||||||
|
glDeleteBuffers(1, &self->EBO);
|
||||||
|
self->VAO = 0;
|
||||||
|
self->VBO = 0;
|
||||||
|
self->EBO = 0;
|
||||||
|
}
|
||||||
43
src/engine/renderer/mesh/mesh.h
Normal file
43
src/engine/renderer/mesh/mesh.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// Created by Tristan on 10/17/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MESH_H
|
||||||
|
#define MESH_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <cglm/cglm.h>
|
||||||
|
|
||||||
|
// Vertices for a simple 2D triangle (x, y, z)
|
||||||
|
// Add (r, g, b) color data after each pos
|
||||||
|
// X, Y, Z, R, G, B
|
||||||
|
extern GLfloat vertices[];
|
||||||
|
extern const size_t vertices_size;
|
||||||
|
// Indices define the order vertices are drawn
|
||||||
|
extern GLuint indices[];
|
||||||
|
|
||||||
|
#define INDICES_COUNT 12
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Vertex Array Object
|
||||||
|
GLuint VAO;
|
||||||
|
|
||||||
|
// Vertex Buffer Object
|
||||||
|
GLuint VBO;
|
||||||
|
|
||||||
|
// Element Buffer Object
|
||||||
|
GLuint EBO;
|
||||||
|
|
||||||
|
// Number of indices to draw
|
||||||
|
GLsizei num_indices;
|
||||||
|
} Mesh;
|
||||||
|
|
||||||
|
// initializes and uploads mesh data to gpu
|
||||||
|
void mesh_init(Mesh *self, GLfloat *vertices, GLsizei vertices_size, GLuint *indices, GLsizei num_indices);
|
||||||
|
|
||||||
|
// Draws the mesh
|
||||||
|
void mesh_draw(Mesh *self);
|
||||||
|
|
||||||
|
void mesh_delete(Mesh *self);
|
||||||
|
|
||||||
|
#endif //MESH_H
|
||||||
@@ -64,9 +64,9 @@ Shader shader_create(const char *vertexFile, const char *fragmentFile) {
|
|||||||
char *vertexSource = get_file_contents(vertexFile);
|
char *vertexSource = get_file_contents(vertexFile);
|
||||||
char *fragmentSource = get_file_contents(fragmentFile);
|
char *fragmentSource = get_file_contents(fragmentFile);
|
||||||
|
|
||||||
if (!vertexSource || !fragmentSource) {
|
if (vertexSource == NULL || fragmentSource == NULL) {
|
||||||
log_error("Failed to load shader files. Returning empty shader\n");
|
log_error("Failed to load shader files. Returning empty shader\n");
|
||||||
Shader emptyShader = { .ID = 0};
|
Shader emptyShader = { .ID = 0, .camMatrixLocation = -1};
|
||||||
if (vertexSource)
|
if (vertexSource)
|
||||||
free(vertexSource);
|
free(vertexSource);
|
||||||
if (fragmentSource)
|
if (fragmentSource)
|
||||||
@@ -101,7 +101,19 @@ Shader shader_create(const char *vertexFile, const char *fragmentFile) {
|
|||||||
glDeleteShader(vertexShader);
|
glDeleteShader(vertexShader);
|
||||||
glDeleteShader(fragmentShader);
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
Shader newShader = { .ID = programID };
|
GLint camMatrixLocation = glGetUniformLocation(programID, "camMatrix");
|
||||||
|
if (camMatrixLocation == -1) {
|
||||||
|
log_error("Uniform 'camMatrix' not found after linking shader program %u. Is it used in default.vert?", programID);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint modelMatrixLocation = glGetUniformLocation(programID, "modelMatrix");
|
||||||
|
if (modelMatrixLocation == -1) {
|
||||||
|
log_warn("Uniform 'modelMatrix' not found in shader program %u. Is it used in default.vert?", programID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader newShader = { .ID = programID,
|
||||||
|
.camMatrixLocation = camMatrixLocation,
|
||||||
|
.modelMatrixLocation = modelMatrixLocation };
|
||||||
return newShader;
|
return newShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
// Reference ID of the shader program
|
// Reference ID of the shader program
|
||||||
GLuint ID;
|
GLuint ID;
|
||||||
|
// Location of the camera matrix uniform, set at creation
|
||||||
|
GLint camMatrixLocation;
|
||||||
|
GLint modelMatrixLocation;
|
||||||
} Shader;
|
} Shader;
|
||||||
|
|
||||||
char *get_file_contents(const char *filename);
|
char *get_file_contents(const char *filename);
|
||||||
|
|||||||
115
src/main.c
115
src/main.c
@@ -17,6 +17,7 @@
|
|||||||
#include "engine/renderer/camera/camera.h"
|
#include "engine/renderer/camera/camera.h"
|
||||||
#include "engine/renderer/data/engine_data.h"
|
#include "engine/renderer/data/engine_data.h"
|
||||||
#include "engine/renderer/shaders/shader.h"
|
#include "engine/renderer/shaders/shader.h"
|
||||||
|
#include "engine/renderer/mesh/mesh.h"
|
||||||
|
|
||||||
static SDL_Window *window = NULL;
|
static SDL_Window *window = NULL;
|
||||||
static SDL_GLContext gl_context = NULL;
|
static SDL_GLContext gl_context = NULL;
|
||||||
@@ -28,6 +29,9 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
log_info("Starting program and initializing SDL...");
|
log_info("Starting program and initializing SDL...");
|
||||||
/* Create the window */
|
/* Create the window */
|
||||||
|
|
||||||
|
int win_width = 1280;
|
||||||
|
int win_height = 720;
|
||||||
|
|
||||||
// TODO: make use of arena allocators potentially? see: digital grove repo
|
// TODO: make use of arena allocators potentially? see: digital grove repo
|
||||||
Engine_Data *state = (Engine_Data*)malloc(sizeof(Engine_Data));
|
Engine_Data *state = (Engine_Data*)malloc(sizeof(Engine_Data));
|
||||||
if (state == NULL) {
|
if (state == NULL) {
|
||||||
@@ -35,25 +39,22 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass allocated state back to the SDL loop
|
state->window_width = win_width;
|
||||||
*appstate = state;
|
state->window_height = win_height;
|
||||||
|
|
||||||
int win_width = 1280;
|
|
||||||
int win_height = 720;
|
|
||||||
|
|
||||||
// use of SDL_WINDOW_OPENGL flag to create a context-compatible window with shaders
|
|
||||||
window = SDL_CreateWindow("Beyond Depth", win_width, win_height, SDL_WINDOW_OPENGL);
|
|
||||||
if (!window) {
|
|
||||||
log_error("Couldn't create SDL window: %s", SDL_GetError());
|
|
||||||
free(state);
|
|
||||||
return SDL_APP_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create openGL context with openGL 3.3 core profile
|
// create openGL context with openGL 3.3 core profile
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
|
||||||
|
// use of SDL_WINDOW_OPENGL flag to create a context-compatible window with shaders
|
||||||
|
window = SDL_CreateWindow("Beyond Depth", win_width, win_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||||
|
if (!window) {
|
||||||
|
log_error("Couldn't create SDL window: %s", SDL_GetError());
|
||||||
|
free(state);
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
gl_context = SDL_GL_CreateContext(window);
|
gl_context = SDL_GL_CreateContext(window);
|
||||||
if (!gl_context) {
|
if (!gl_context) {
|
||||||
log_error("Failed to create OpenGL context: %s", SDL_GetError());
|
log_error("Failed to create OpenGL context: %s", SDL_GetError());
|
||||||
@@ -72,22 +73,27 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: if still crashing on initial startup, ensure all of OpenGL, GLAD is properly initialized
|
// z-buffer
|
||||||
state->window_width = win_width;
|
glEnable(GL_DEPTH_TEST);
|
||||||
state->window_height = win_height;
|
|
||||||
|
|
||||||
vec3 initial_pos = {0.0f, 0.0f, 3.0f};
|
|
||||||
camera_init(&state->camera, initial_pos, state->window_width, state->window_height);
|
|
||||||
|
|
||||||
state->shader = shader_create("default.vert", "default.frag");
|
state->shader = shader_create("default.vert", "default.frag");
|
||||||
|
|
||||||
if (state->shader.ID == 0) {
|
if (state->shader.ID == 0) {
|
||||||
log_error("Failed to initialize shader program");
|
log_error("Failed to initialize shader program");
|
||||||
// TODO: cleanup memory
|
// TODO: cleanup memory
|
||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 initial_pos = {0.0f, 0.0f, 2.0f};
|
||||||
|
camera_init(&state->camera, initial_pos, state->window_width, state->window_height);
|
||||||
|
|
||||||
|
mesh_init(&state->triangle_mesh, vertices, (GLsizei)vertices_size, indices, INDICES_COUNT);
|
||||||
|
|
||||||
|
glm_mat4_identity(state->pyramidModel);
|
||||||
|
|
||||||
|
SDL_SetWindowRelativeMouseMode(window, true);
|
||||||
|
|
||||||
|
// pass allocated state back to the SDL loop
|
||||||
|
*appstate = state;
|
||||||
|
|
||||||
log_info("Camera, Shaders and App State initialized");
|
log_info("Camera, Shaders and App State initialized");
|
||||||
|
|
||||||
@@ -97,11 +103,24 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
|
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
|
||||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
if (event->type == SDL_EVENT_KEY_DOWN ||
|
Engine_Data *state = (Engine_Data *)appstate;
|
||||||
event->type == SDL_EVENT_QUIT) {
|
|
||||||
log_info("User pressed a key");
|
// handles quitting
|
||||||
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
if (event->type == SDL_EVENT_QUIT) {
|
||||||
|
return SDL_APP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handles esc key to quit
|
||||||
|
if (event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_ESCAPE) {
|
||||||
|
return SDL_APP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle mouse motion for camera look
|
||||||
|
if (event->type == SDL_EVENT_MOUSE_MOTION) {
|
||||||
|
// y movement inverted?
|
||||||
|
camera_process_mouse(&state->camera, event->motion.xrel, -event->motion.yrel, state->deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +130,13 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
|||||||
{
|
{
|
||||||
Engine_Data *state = (Engine_Data *)appstate; // good practice
|
Engine_Data *state = (Engine_Data *)appstate; // good practice
|
||||||
|
|
||||||
|
float currentTime = (float)SDL_GetTicks() / 1000.0f;
|
||||||
|
state->deltaTime = currentTime - state->lastFrameTime;
|
||||||
|
state->lastFrameTime = currentTime;
|
||||||
|
|
||||||
|
const Uint8 *keyState = SDL_GetKeyboardState(NULL);
|
||||||
|
camera_process_keyboard(&state->camera, keyState, state->deltaTime);
|
||||||
|
|
||||||
// set viewport
|
// set viewport
|
||||||
glViewport(0, 0, 1280, 720);
|
glViewport(0, 0, 1280, 720);
|
||||||
|
|
||||||
@@ -119,7 +145,39 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
|||||||
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
|
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// TODO: add drawing logic
|
// calculate "orbit" angle for total rotation overtime
|
||||||
|
float rotation_speed_deg = 45.0f;
|
||||||
|
float rotation_amount = glm_rad(rotation_speed_deg * state->deltaTime);
|
||||||
|
|
||||||
|
// accumulate total rotation
|
||||||
|
static float total_rotation = 0.0f;
|
||||||
|
total_rotation += rotation_amount;
|
||||||
|
|
||||||
|
shader_activate(&state->shader);
|
||||||
|
|
||||||
|
// upload camera matrix (P*V) to the shader
|
||||||
|
camera_matrix_to_shader(&state->camera, &state->shader, "camMatrix");
|
||||||
|
|
||||||
|
float rotation = (float)SDL_GetTicks() / 1000.0f;
|
||||||
|
glm_mat4_identity(state->pyramidModel);
|
||||||
|
// rotate around the y-axis
|
||||||
|
glm_rotate(state->pyramidModel, total_rotation * 0.5f, (vec3){0.0f, 1.0f, 0.0f});
|
||||||
|
|
||||||
|
mat4 orbitModel; // temporary object
|
||||||
|
glm_mat4_identity(orbitModel);
|
||||||
|
|
||||||
|
glm_rotate(orbitModel, total_rotation, (vec3){0.0f, 1.0f, 0.0f});
|
||||||
|
|
||||||
|
glm_translate(orbitModel, (vec3){3.0f, 0.0f, 0.0f});
|
||||||
|
|
||||||
|
glm_rotate(orbitModel, total_rotation * 2.0f, (vec3){0.5f, 1.0f, 0.0f});
|
||||||
|
|
||||||
|
// upload model matrix to shader
|
||||||
|
glUniformMatrix4fv(state->shader.modelMatrixLocation, 1, GL_FALSE, *state->pyramidModel);
|
||||||
|
mesh_draw(&state->triangle_mesh);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(state->shader.modelMatrixLocation, 1, GL_FALSE, *orbitModel);
|
||||||
|
mesh_draw(&state->triangle_mesh);
|
||||||
|
|
||||||
// swap front and back buffers to display rendered frame
|
// swap front and back buffers to display rendered frame
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
@@ -134,7 +192,12 @@ void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
|||||||
|
|
||||||
// cleanup all resources
|
// cleanup all resources
|
||||||
if (state) {
|
if (state) {
|
||||||
shader_delete(&state->shader);
|
mesh_delete(&state->triangle_mesh);
|
||||||
|
|
||||||
|
if (state->shader.ID != 0) {
|
||||||
|
shader_delete(&state->shader);
|
||||||
|
}
|
||||||
|
|
||||||
free(state);
|
free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user