added scene abstraction
This commit is contained in:
parent
145b9f86e6
commit
67101e29f9
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
149
src/objects/cube.c
Normal 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
15
src/objects/cube.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
44
src/renderer/object.c
Normal 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
32
src/renderer/object.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
48
src/scene.c
Normal 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
21
src/scene.h
Normal 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
|
Loading…
Reference in a new issue