added scene abstraction

This commit is contained in:
Lauchmelder 2022-10-18 18:43:15 +02:00
parent 145b9f86e6
commit 67101e29f9
16 changed files with 362 additions and 123 deletions

View file

@ -7,13 +7,19 @@ cmake_minimum_required (VERSION 3.8)
add_executable(solver
"main.c"
"application.c"
"scene.c"
"renderer/window.c"
"renderer/context.c"
"renderer/buffer.c"
"renderer/shader.c"
"renderer/camera.c"
"objects/cube.c" "renderer/object.c")
target_include_directories(solver PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(solver PRIVATE
glfw
glad

View file

@ -3,22 +3,19 @@
#include <assert.h>
#include <errno.h>
#include <GLFW/glfw3.h>
#include <cglm/affine.h>
#include "renderer/context.h"
#include "objects/cube.h"
static void on_window_size_change(Application* app, int width, int height)
{
set_camera_perspective(&app->camera, 90.0f, (float)width / (float)height);
scene_update_size(app->active_scene, width, height);
}
static void destroy_application(Application* app)
{
assert(app);
destroy_vao(app->object);
destroy_window(app->window);
destroy_scene(*app->scenes);
}
int init_application(Application* app, const char* name)
@ -35,91 +32,14 @@ int init_application(Application* app, const char* name)
app->window.user_data = app;
app->window.on_size_change = on_window_size_change;
// Create quad for testing
create_vao(&app->object);
app->scenes = (Scene*)malloc(1 * sizeof(Scene));
app->active_scene = app->scenes; // First scene is active scene
float vertices[] = {
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // front bottom left
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // front top left
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // front top right
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, // front bottom right
create_scene(app->scenes);
Cube* obj = (Cube*)malloc(sizeof(Cube));
create_cube(obj);
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, // back bottom left
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // back top left
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // back top right
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // back bottom right
};
attach_vertex_buffer(&app->object, vertices, sizeof(vertices));
unsigned indices[] = {
0, 1, 2, // front
0, 2, 3,
3, 2, 6, // right
3, 6, 7,
4, 5, 1, // left
4, 1, 0,
7, 6, 5, // back
7, 5, 4,
1, 5, 6, // top
1, 6, 2,
4, 0, 3, // bottom
4, 3, 7
};
attach_element_buffer(&app->object, indices, sizeof(indices));
VertexAttribute layout[] = {
{ GL_FLOAT, 3, 3 * sizeof(float) },
{ GL_FLOAT, 3, 3 * sizeof(float) }
};
set_vertex_layout(&app->object, layout, sizeof(layout) / sizeof(VertexAttribute));
app->shader = create_shader(
"#version 460 core\n"
""
"layout (location = 0) in vec3 pos;"
"layout (location = 1) in vec3 col;"
""
"out vec3 i_col;"
""
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
""
"void main() {"
" i_col = col;"
" gl_Position = projection * view * model * vec4(pos, 1.0);"
"}",
"#version 460 core\n"
""
"in vec3 i_col;"
"out vec4 FragColor;"
""
"void main() {"
" FragColor = vec4(i_col, 1.0);"
"}"
);
if(app->shader == 0)
{
destroy_application(app);
return 1;
}
if (create_camera(&app->camera) != 0)
{
destroy_application(app);
return 1;
}
glm_mat4_identity(app->model);
ctx_enable(GL_DEPTH_TEST);
ctx_front_face(GL_CW);
scene_add_object(app->active_scene, &obj->object);
return 0;
}
@ -130,17 +50,7 @@ int launch_application(Application* app)
{
glfwPollEvents();
// rotate cube
glm_rotate(app->model, 0.03f, (vec3) { 0.0f, 1.0f, 0.0f });
ctx_clear_screen(0.3f, 0.1f, 0.8f, 1.0f);
bind_shader(app->shader);
set_uniform_mat4(app->shader, "model", app->model);
set_uniform_mat4(app->shader, "view", app->camera.view);
set_uniform_mat4(app->shader, "projection", app->camera.projection);
ctx_draw_elements(&app->object);
render_scene(app->active_scene);
glfwSwapBuffers(app->window.window);
}

View file

@ -2,18 +2,14 @@
#define APPLICATION_H
#include "renderer/window.h"
#include "renderer/buffer.h"
#include "renderer/shader.h"
#include "renderer/camera.h"
#include "scene.h"
typedef struct Application
{
Window window;
VertexArrayObject object;
int shader;
Camera camera;
mat4 model;
Scene* scenes;
Scene* active_scene;
} Application;
int init_application(Application* app, const char* name);

149
src/objects/cube.c Normal file
View file

@ -0,0 +1,149 @@
#include "cube.h"
#include <stdio.h>
#include <glad/glad.h>
static VertexArrayObject* vao = NULL;
static Shader shader = 0;
static size_t num_cubes = 0;
static int init_cube_object(void)
{
vao = (VertexArrayObject*) malloc(sizeof(VertexArrayObject));
if (vao == NULL)
{
fprintf(stderr, "Failed to allocate memory for cube vao\n");
return 1;
}
create_vao(vao);
float cube_vertices[] = {
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
};
attach_vertex_buffer(vao, cube_vertices, sizeof(cube_vertices));
unsigned cube_indices[] = {
0, 1, 2, 2, 1, 3,
1, 5, 6, 1, 6, 2,
3, 2, 6, 3, 6, 7,
4, 5, 1, 4, 1, 0,
4, 0, 3, 4, 3, 7,
7, 6, 5, 7, 5, 4
};
attach_element_buffer(vao, cube_indices, sizeof(cube_indices));
VertexAttribute attributes[] = {
{ GL_FLOAT, 3, sizeof(float) }
};
set_vertex_layout(vao, attributes, sizeof(attributes) / sizeof(VertexAttribute));
shader = create_shader(
"#version 460 core\n"
""
"layout (location = 0) in vec3 pos;"
""
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
""
"void main() {"
" gl_Position = projection * view * model * vec4(pos, 1.0);"
"}",
"#version 460 core\n"
""
"uniform vec3 cube_color;"
"out vec4 FragColor;"
""
"void main() {"
" FragColor = vec4(cube_color, 1.0);"
"}"
);
if (shader == 0)
{
fprintf(stderr, "failed to create shader for cube\n");
return 1;
}
return 0;
}
static void on_shader_bind(Cube* cube)
{
set_uniform_vec3(shader, "cube_color", cube->color);
}
static void on_update(Cube* cube)
{
cube->object.rotation[1] += 0.05f;
for (int i = 0; i < 3; i++)
{
cube->color[i] += cube->color_mod[i];
if (cube->color[i] > 1.0f)
{
cube->color_mod[i] *= -1.0f;
cube->color[i] = 1.0f;
}
else if (cube->color[i] < 0.0f)
{
cube->color_mod[i] *= -1.0f;
cube->color[i] = 0.0f;
}
}
}
int create_cube(Cube* cube)
{
if (vao == NULL || shader == 0)
{
if (init_cube_object() != 0)
{
return 1;
}
}
init_object(&cube->object);
glm_vec3_one(cube->color);
cube->color_mod[0] = 0.01f;
cube->color_mod[1] = 0.006f;
cube->color_mod[2] = 0.005f;
cube->object.vao = vao;
cube->object.shader = shader;
cube->object.child = cube;
cube->object.on_shader_use = on_shader_bind;
cube->object.on_update = on_update;
cube->object.on_destroy = destroy_cube;
num_cubes++;
}
void destroy_cube(Cube* cube)
{
num_cubes--;
if (num_cubes == 0)
{
destroy_shader(shader);
shader = 0;
destroy_vao(*vao);
vao = NULL;
}
}

15
src/objects/cube.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef OBJ_CUBE_H
#define OBJ_CUBE_H
#include "renderer/object.h"
typedef struct Cube {
Object object;
vec3 color;
vec3 color_mod;
} Cube;
int create_cube(Cube* cube);
void destroy_cube(Cube* cube);
#endif // OBJ_CUBE_H

View file

@ -50,7 +50,7 @@ void set_vertex_layout(VertexArrayObject* vao, VertexAttribute* attributes, size
size_t stride = 0;
for (size_t i = 0; i < count; i++) {
stride += attributes[i].size;
stride += attributes[i].size * attributes[i].count;
}
size_t offset = 0;
@ -58,11 +58,16 @@ void set_vertex_layout(VertexArrayObject* vao, VertexAttribute* attributes, size
glVertexAttribPointer(i, attributes[i].count, attributes[i].type, GL_FALSE, stride, (const void*)(offset));
glEnableVertexAttribArray(i);
offset += attributes[i].size;
offset += attributes[i].size * attributes[i].count;
}
}
void bind_vao(VertexArrayObject vao)
void bind_vao(VertexArrayObject* vao)
{
glBindVertexArray(vao.vao);
glBindVertexArray(vao->vao);
}
void render_vao(VertexArrayObject* vao)
{
glDrawArrays(GL_TRIANGLES, 0, vao->elements);
}

View file

@ -28,6 +28,7 @@ void attach_element_buffer(VertexArrayObject* vao, const unsigned* data, size_t
void set_vertex_layout(VertexArrayObject* vao, VertexAttribute* attributes, size_t count);
void bind_vao(VertexArrayObject vao);
void bind_vao(VertexArrayObject* vao);
void render_vao(VertexArrayObject* vao);
#endif // BUFFER_H

View file

@ -10,7 +10,7 @@ int create_camera(Camera* camera)
glm_mat4_identity(camera->view);
glm_rotate(camera->view, glm_rad(35.0f), (vec3) { 1.0f, 0.0f, 0.0f });
glm_translate(camera->view, (vec3) { 0.0f, -1.0f, -2.0f });
glm_translate(camera->view, (vec3) { 0.0f, -1.5f, -3.0f });
glm_perspective(glm_rad(90.0f), 1.0f, 0.001f, 100.0f, camera->projection);

View file

@ -23,7 +23,7 @@ void ctx_clear_screen(float r, float g, float b, float a)
void ctx_draw_elements(VertexArrayObject* vao)
{
bind_vao(*vao);
bind_vao(vao);
glDrawElements(GL_TRIANGLES, vao->elements, GL_UNSIGNED_INT, (void*)0);
}

44
src/renderer/object.c Normal file
View file

@ -0,0 +1,44 @@
#include "object.h"
#include <cglm/affine.h>
#include "context.h"
void init_object(Object* obj)
{
glm_mat4_identity(obj->transform);
glm_vec3_zero(obj->position);
glm_vec3_zero(obj->rotation);
glm_vec3_one(obj->scale);
}
void update_object(Object* obj)
{
obj->on_update(obj->child);
}
void render_object(Object* obj, Camera* camera)
{
bind_shader(obj->shader);
glm_mat4_identity(obj->transform);
float angle = glm_vec3_norm(obj->rotation);
vec3 normalized_rot;
glm_vec3_normalize_to(obj->rotation, normalized_rot);
glm_scale(obj->transform, obj->scale);
glm_rotate(obj->transform, angle, normalized_rot);
glm_scale(obj->transform, obj->scale);
set_uniform_mat4(obj->shader, "model", obj->transform);
set_uniform_mat4(obj->shader, "view", camera->view);
set_uniform_mat4(obj->shader, "projection", camera->projection);
obj->on_shader_use(obj->child);
ctx_draw_elements(obj->vao);
}
void destroy_object(Object obj)
{
obj.on_destroy(obj.child);
}

32
src/renderer/object.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <cglm/mat4.h>
#include "shader.h"
#include "buffer.h"
#include "camera.h"
typedef struct Object
{
VertexArrayObject* vao;
Shader shader;
mat4 transform;
vec3 position;
vec3 rotation;
vec3 scale;
void* child;
void(*on_shader_use)(void*);
void(*on_update)(void*);
void(*on_destroy)(void*);
} Object;
void init_object(Object* obj);
void destroy_object(Object obj);
void update_object(Object* obj);
void render_object(Object* obj, Camera* camera);
#endif // OBJECT_H

View file

@ -32,7 +32,7 @@ static int set_and_compile_shader(GLuint program, GLuint shader, const char* cod
return 0;
}
int create_shader(const char* vertex_shader_code, const char* fragment_shader_code)
Shader create_shader(const char* vertex_shader_code, const char* fragment_shader_code)
{
assert(vertex_shader_code && fragment_shader_code);
@ -83,18 +83,24 @@ vertex_failed:
return shader;
}
void destroy_shader(int shader)
void destroy_shader(Shader shader)
{
glDeleteProgram(shader);
}
void bind_shader(int shader)
void bind_shader(Shader shader)
{
glUseProgram(shader);
}
void set_uniform_mat4(int shader, const char* name, mat4 mat)
void set_uniform_mat4(Shader shader, const char* name, mat4 mat)
{
int location = glGetUniformLocation(shader, name);
glUniformMatrix4fv(location, 1, GL_FALSE, (float*)mat);
}
}
void set_uniform_vec3(Shader shader, const char* name, vec3 vec)
{
int location = glGetUniformLocation(shader, name);
glUniform3fv(location, 1, vec);
}

View file

@ -3,10 +3,14 @@
#include <cglm/mat4.h>
int create_shader(const char* vertex_shader_code, const char* fragment_shader_code);
void destroy_shader(int shader);
typedef int Shader;
void bind_shader(int shader);
void set_uniform_mat4(int shader, const char* name, mat4 mat);
Shader create_shader(const char* vertex_shader_code, const char* fragment_shader_code);
void destroy_shader(Shader shader);
void bind_shader(Shader shader);
void set_uniform_mat4(Shader shader, const char* name, mat4 mat);
void set_uniform_vec3(Shader shader, const char* name, vec3 vec);
#endif // SHADER_H

View file

@ -33,6 +33,8 @@ int create_managed_window(Window* window, const char* title, int width, int heig
glfwMakeContextCurrent(window->window);
ctx_init();
ctx_enable(GL_DEPTH_TEST);
ctx_front_face(GL_CW);
glfwSetFramebufferSizeCallback(window->window, default_framebuffer_size_callback);

48
src/scene.c Normal file
View file

@ -0,0 +1,48 @@
#include "scene.h"
#include <assert.h>
#include <stdio.h>
#include <glad/glad.h>
#include "objects/cube.h"
int create_scene(Scene* scene)
{
assert(scene);
if (create_camera(&scene->camera) != 0)
{
fprintf(stderr, "Failed to set up camera for scene\n");
return 1;
}
scene->objects = (Object*)malloc(sizeof(Object));
}
void destroy_scene(Scene scene)
{
destroy_object(*(scene.objects));
}
void scene_add_object(Scene* scene, Object* object)
{
assert(scene);
scene->objects = object;
}
void scene_update_size(Scene* scene, int width, int height)
{
assert(scene);
set_camera_perspective(&scene->camera, 90.0f, (float)width / (float)height);
}
void render_scene(Scene* scene)
{
assert(scene);
ctx_clear_screen(0.0f, 0.0f, 0.0f, 1.0f);
update_object(scene->objects);
render_object(scene->objects, &scene->camera);
}

21
src/scene.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef SCENE_H
#define SCENE_H
#include "renderer/camera.h"
#include "renderer/object.h"
typedef struct Scene
{
Camera camera;
Object* objects;
} Scene;
int create_scene(Scene* scene);
void destroy_scene(Scene scene);
void scene_add_object(Scene* scene, Object* object);
void scene_update_size(Scene* scene, int width, int height);
void render_scene(Scene* scene);
#endif