modularized shaders
This commit is contained in:
parent
18d817e6bf
commit
5e61cd8c50
|
@ -36,7 +36,10 @@ int init_application(Application* app, const char* name)
|
||||||
app->scenes = (Scene*)malloc(1 * sizeof(Scene));
|
app->scenes = (Scene*)malloc(1 * sizeof(Scene));
|
||||||
app->active_scene = app->scenes; // First scene is active scene
|
app->active_scene = app->scenes; // First scene is active scene
|
||||||
|
|
||||||
create_spinning_cubes_scene(&app->window, app->scenes);
|
if (create_spinning_cubes_scene(&app->window, app->scenes) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
static VertexArrayObject* vao = NULL;
|
static VertexArrayObject* vao = NULL;
|
||||||
static Shader shader = 0;
|
|
||||||
static size_t num_cubes = 0;
|
static size_t num_cubes = 0;
|
||||||
|
|
||||||
static int init_cube_object(void)
|
static int init_cube_object(void)
|
||||||
|
@ -78,72 +77,10 @@ static int init_cube_object(void)
|
||||||
};
|
};
|
||||||
set_vertex_layout(vao, attributes, sizeof(attributes) / sizeof(VertexAttribute));
|
set_vertex_layout(vao, attributes, sizeof(attributes) / sizeof(VertexAttribute));
|
||||||
|
|
||||||
shader = create_shader(
|
|
||||||
"#version 460 core\n"
|
|
||||||
""
|
|
||||||
"layout (location = 0) in vec3 pos;"
|
|
||||||
"layout (location = 1) in vec3 normal;"
|
|
||||||
""
|
|
||||||
"out vec3 frag_normal;"
|
|
||||||
"out vec3 frag_pos;"
|
|
||||||
""
|
|
||||||
"uniform mat4 model;"
|
|
||||||
"uniform mat4 view;"
|
|
||||||
"uniform mat4 projection;"
|
|
||||||
""
|
|
||||||
"void main() {"
|
|
||||||
" frag_normal = mat3(transpose(inverse(model))) * normal;"
|
|
||||||
" frag_pos = vec3(model * vec4(pos, 1.0));"
|
|
||||||
" gl_Position = projection * view * model * vec4(pos, 1.0);"
|
|
||||||
"}",
|
|
||||||
|
|
||||||
"#version 460 core\n"
|
|
||||||
""
|
|
||||||
"in vec3 frag_pos;"
|
|
||||||
"in vec3 frag_normal;"
|
|
||||||
""
|
|
||||||
"uniform vec3 ambient_color = vec3(1.0, 1.0, 1.0);"
|
|
||||||
"uniform float ambient_intens = 1.0f;"
|
|
||||||
""
|
|
||||||
"uniform vec3 point_pos = vec3(0.0, 0.0, 0.0);"
|
|
||||||
"uniform vec3 point_col = vec3(1.0, 1.0, 1.0);"
|
|
||||||
"uniform float point_intens = 1.0f;"
|
|
||||||
""
|
|
||||||
"uniform vec3 cam_pos = vec3(0.0, 0.0, 0.0);"
|
|
||||||
"float specular_strength = 0.5f;"
|
|
||||||
""
|
|
||||||
"uniform vec3 cube_color;"
|
|
||||||
""
|
|
||||||
"out vec4 FragColor;"
|
|
||||||
""
|
|
||||||
"void main() {"
|
|
||||||
" vec3 ambient = ambient_intens * ambient_color;"
|
|
||||||
""
|
|
||||||
" vec3 norm = normalize(frag_normal);"
|
|
||||||
" vec3 light_dir = normalize(point_pos - frag_pos);"
|
|
||||||
" float diff = max(dot(norm, light_dir), 0.0);"
|
|
||||||
" vec3 diffuse = diff * point_col;"
|
|
||||||
""
|
|
||||||
" vec3 view_dir = normalize(cam_pos - frag_pos);"
|
|
||||||
" vec3 reflect_dir = reflect(-light_dir, norm);"
|
|
||||||
""
|
|
||||||
" float spec = pow(max(dot(view_dir, reflect_dir), 0.0), 32);"
|
|
||||||
" vec3 specular = specular_strength * spec * point_col; "
|
|
||||||
""
|
|
||||||
" vec3 result = (ambient + diffuse + specular) * cube_color;"
|
|
||||||
" FragColor = vec4(result, 1.0);"
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
if (shader == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "failed to create shader for cube\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_shader_bind(Cube* cube)
|
static void on_shader_bind(Cube* cube, Shader* shader)
|
||||||
{
|
{
|
||||||
set_uniform_vec3(shader, "cube_color", cube->color);
|
set_uniform_vec3(shader, "cube_color", cube->color);
|
||||||
}
|
}
|
||||||
|
@ -171,7 +108,7 @@ static void on_update(Cube* cube)
|
||||||
|
|
||||||
int create_cube(Cube* cube)
|
int create_cube(Cube* cube)
|
||||||
{
|
{
|
||||||
if (vao == NULL || shader == 0)
|
if (vao == NULL)
|
||||||
{
|
{
|
||||||
if (init_cube_object() != 0)
|
if (init_cube_object() != 0)
|
||||||
{
|
{
|
||||||
|
@ -187,7 +124,6 @@ int create_cube(Cube* cube)
|
||||||
cube->color_mod[2] = 0.005f;
|
cube->color_mod[2] = 0.005f;
|
||||||
|
|
||||||
cube->object.vao = vao;
|
cube->object.vao = vao;
|
||||||
cube->object.shader = shader;
|
|
||||||
|
|
||||||
cube->object.child = cube;
|
cube->object.child = cube;
|
||||||
cube->object.on_shader_use_obj = on_shader_bind;
|
cube->object.on_shader_use_obj = on_shader_bind;
|
||||||
|
@ -203,9 +139,6 @@ void destroy_cube(Cube* cube)
|
||||||
|
|
||||||
if (num_cubes == 0)
|
if (num_cubes == 0)
|
||||||
{
|
{
|
||||||
destroy_shader(shader);
|
|
||||||
shader = 0;
|
|
||||||
|
|
||||||
destroy_vao(*vao);
|
destroy_vao(*vao);
|
||||||
vao = NULL;
|
vao = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,8 @@ void update_object(Object* obj)
|
||||||
obj->on_update(obj->child);
|
obj->on_update(obj->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_object(Object* obj, Camera* camera)
|
void render_object(Object* obj, Shader* shader)
|
||||||
{
|
{
|
||||||
bind_shader(obj->shader);
|
|
||||||
|
|
||||||
glm_mat4_identity(obj->transform);
|
glm_mat4_identity(obj->transform);
|
||||||
float angle = glm_vec3_norm(obj->rotation);
|
float angle = glm_vec3_norm(obj->rotation);
|
||||||
vec3 normalized_rot;
|
vec3 normalized_rot;
|
||||||
|
@ -30,12 +28,9 @@ void render_object(Object* obj, Camera* camera)
|
||||||
glm_rotate(obj->transform, angle, normalized_rot);
|
glm_rotate(obj->transform, angle, normalized_rot);
|
||||||
glm_scale(obj->transform, obj->scale);
|
glm_scale(obj->transform, obj->scale);
|
||||||
|
|
||||||
set_uniform_mat4(obj->shader, "model", obj->transform);
|
set_uniform_mat4(shader, "model", obj->transform);
|
||||||
set_uniform_mat4(obj->shader, "view", get_camera_view(camera));
|
|
||||||
set_uniform_mat4(obj->shader, "projection", camera->projection);
|
|
||||||
|
|
||||||
obj->on_shader_use_obj(obj->child);
|
obj->on_shader_use_obj(obj->child, shader);
|
||||||
obj->on_shader_use_scene(obj, obj->scene);
|
|
||||||
|
|
||||||
ctx_draw_elements(obj->vao);
|
ctx_draw_elements(obj->vao);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ typedef struct Camera Camera;
|
||||||
typedef struct Object
|
typedef struct Object
|
||||||
{
|
{
|
||||||
VertexArrayObject* vao;
|
VertexArrayObject* vao;
|
||||||
Shader shader;
|
|
||||||
|
|
||||||
mat4 transform;
|
mat4 transform;
|
||||||
vec3 position;
|
vec3 position;
|
||||||
|
@ -20,8 +19,7 @@ typedef struct Object
|
||||||
|
|
||||||
void* child;
|
void* child;
|
||||||
void* scene;
|
void* scene;
|
||||||
void(*on_shader_use_obj)(void*);
|
void(*on_shader_use_obj)(void*, void*);
|
||||||
void(*on_shader_use_scene)(void*, void*);
|
|
||||||
void(*on_update)(void*);
|
void(*on_update)(void*);
|
||||||
void(*on_destroy)(void*);
|
void(*on_destroy)(void*);
|
||||||
} Object;
|
} Object;
|
||||||
|
@ -33,6 +31,6 @@ void object_set_position(Object* obj, vec3 position);
|
||||||
void object_move(Object* obj, vec3 direction);
|
void object_move(Object* obj, vec3 direction);
|
||||||
|
|
||||||
void update_object(Object* obj);
|
void update_object(Object* obj);
|
||||||
void render_object(Object* obj, Camera* camera);
|
void render_object(Object* obj, Shader* shader);
|
||||||
|
|
||||||
#endif // OBJECT_H
|
#endif // OBJECT_H
|
|
@ -4,8 +4,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include "object.h"
|
||||||
|
|
||||||
static int set_and_compile_shader(GLuint program, GLuint shader, const char* code, char** error)
|
static int set_and_compile_shader(GLuint program, GLuint shader, const char* code, char** error)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -32,47 +35,54 @@ static int set_and_compile_shader(GLuint program, GLuint shader, const char* cod
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader create_shader(const char* vertex_shader_code, const char* fragment_shader_code)
|
int create_shader(Shader* shader, const char* vertex_shader_code, const char* fragment_shader_code)
|
||||||
{
|
{
|
||||||
|
assert(shader);
|
||||||
assert(vertex_shader_code && fragment_shader_code);
|
assert(vertex_shader_code && fragment_shader_code);
|
||||||
|
|
||||||
int shader = glCreateProgram();
|
int return_val = 0;
|
||||||
|
|
||||||
|
shader->objects = create_dynamic_array(Object*);
|
||||||
|
shader->id = glCreateProgram();
|
||||||
|
|
||||||
char* error;
|
char* error;
|
||||||
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
if (set_and_compile_shader(shader, vertex_shader, vertex_shader_code, &error) != 0)
|
if (set_and_compile_shader(shader->id, vertex_shader, vertex_shader_code, &error) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "vertex shader compilation failed: %s\n", error);
|
fprintf(stderr, "vertex shader compilation failed: %s\n", error);
|
||||||
free(error);
|
free(error);
|
||||||
glDeleteProgram(shader);
|
glDeleteProgram(shader->id);
|
||||||
shader = 0;
|
shader->id = 0;
|
||||||
|
return_val = 1;
|
||||||
|
|
||||||
goto vertex_failed;
|
goto vertex_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
if (set_and_compile_shader(shader, fragment_shader, fragment_shader_code, &error) != 0)
|
if (set_and_compile_shader(shader->id, fragment_shader, fragment_shader_code, &error) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "fragment shader compilation failed: %s\n", error);
|
fprintf(stderr, "fragment shader compilation failed: %s\n", error);
|
||||||
free(error);
|
free(error);
|
||||||
glDeleteProgram(shader);
|
glDeleteProgram(shader->id);
|
||||||
shader = 0;
|
shader->id = 0;
|
||||||
|
return_val = 1;
|
||||||
|
|
||||||
goto fragment_failed;
|
goto fragment_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
glLinkProgram(shader);
|
glLinkProgram(shader->id);
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
glGetProgramiv(shader, GL_LINK_STATUS, &result);
|
glGetProgramiv(shader, GL_LINK_STATUS, &result);
|
||||||
if (result == GL_FALSE)
|
if (result == GL_FALSE)
|
||||||
{
|
{
|
||||||
char error[512];
|
char error[512];
|
||||||
glGetProgramInfoLog(shader, 512, NULL, error);
|
glGetProgramInfoLog(shader->id, 512, NULL, error);
|
||||||
|
|
||||||
fprintf(stderr, "shader linking failed: %s\n", error);
|
fprintf(stderr, "shader linking failed: %s\n", error);
|
||||||
glDeleteProgram(shader);
|
glDeleteProgram(shader);
|
||||||
shader = 0;
|
shader->id = 0;
|
||||||
|
return_val = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment_failed:
|
fragment_failed:
|
||||||
|
@ -80,33 +90,49 @@ fragment_failed:
|
||||||
vertex_failed:
|
vertex_failed:
|
||||||
glDeleteShader(vertex_shader);
|
glDeleteShader(vertex_shader);
|
||||||
|
|
||||||
return shader;
|
return return_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_shader(Shader shader)
|
void destroy_shader(Shader shader)
|
||||||
{
|
{
|
||||||
glDeleteProgram(shader);
|
destroy_dynamic_array(shader.objects);
|
||||||
|
glDeleteProgram(shader.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind_shader(Shader shader)
|
void bind_shader(Shader* shader)
|
||||||
{
|
{
|
||||||
glUseProgram(shader);
|
dynamic_array_clear(&shader->objects);
|
||||||
|
glUseProgram(shader->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_uniform_mat4(Shader shader, const char* name, mat4 mat)
|
void shader_add_object(Shader* shader, Object* object)
|
||||||
{
|
{
|
||||||
int location = glGetUniformLocation(shader, name);
|
dynamic_array_push(&shader->objects, (void*)&object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader_render(Shader* shader)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < shader->objects.size; i++)
|
||||||
|
{
|
||||||
|
Object* obj = *(Object**)dynamic_array_get(&shader->objects, i);
|
||||||
|
render_object(obj, shader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_uniform_mat4(Shader* shader, const char* name, mat4 mat)
|
||||||
|
{
|
||||||
|
int location = glGetUniformLocation(shader->id, name);
|
||||||
glUniformMatrix4fv(location, 1, GL_FALSE, (float*)mat);
|
glUniformMatrix4fv(location, 1, GL_FALSE, (float*)mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_uniform_float(Shader shader, const char* name, float val)
|
void set_uniform_float(Shader* shader, const char* name, float val)
|
||||||
{
|
{
|
||||||
int location = glGetUniformLocation(shader, name);
|
int location = glGetUniformLocation(shader->id, name);
|
||||||
glUniform1f(location, val);
|
glUniform1f(location, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_uniform_vec3(Shader shader, const char* name, vec3 vec)
|
void set_uniform_vec3(Shader* shader, const char* name, vec3 vec)
|
||||||
{
|
{
|
||||||
int location = glGetUniformLocation(shader, name);
|
int location = glGetUniformLocation(shader->id, name);
|
||||||
glUniform3fv(location, 1, vec);
|
glUniform3fv(location, 1, vec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,25 @@
|
||||||
#define SHADER_H
|
#define SHADER_H
|
||||||
|
|
||||||
#include <cglm/mat4.h>
|
#include <cglm/mat4.h>
|
||||||
|
#include "util/dynarray.h"
|
||||||
|
|
||||||
typedef int Shader;
|
typedef struct Object Object;
|
||||||
|
|
||||||
Shader create_shader(const char* vertex_shader_code, const char* fragment_shader_code);
|
typedef struct Shader
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
DynamicArray objects;
|
||||||
|
} Shader;
|
||||||
|
|
||||||
|
int create_shader(Shader* shader, const char* vertex_shader_code, const char* fragment_shader_code);
|
||||||
void destroy_shader(Shader shader);
|
void destroy_shader(Shader shader);
|
||||||
|
|
||||||
void bind_shader(Shader shader);
|
void bind_shader(Shader* shader);
|
||||||
|
void shader_add_object(Shader* shader, Object* object);
|
||||||
|
void shader_render(Shader* shader);
|
||||||
|
|
||||||
void set_uniform_mat4(Shader shader, const char* name, mat4 mat);
|
void set_uniform_mat4(Shader* shader, const char* name, mat4 mat);
|
||||||
void set_uniform_float(Shader shader, const char* name, float val);
|
void set_uniform_float(Shader* shader, const char* name, float val);
|
||||||
void set_uniform_vec3(Shader shader, const char* name, vec3 vec);
|
void set_uniform_vec3(Shader* shader, const char* name, vec3 vec);
|
||||||
|
|
||||||
#endif // SHADER_H
|
#endif // SHADER_H
|
45
src/scene.c
45
src/scene.c
|
@ -8,20 +8,6 @@
|
||||||
|
|
||||||
#include "objects/cube.h"
|
#include "objects/cube.h"
|
||||||
|
|
||||||
static void set_lighting_uniforms(Object* obj, Scene* scene)
|
|
||||||
{
|
|
||||||
Shader shader = obj->shader;
|
|
||||||
|
|
||||||
set_uniform_vec3(shader, "ambient_color", scene->ambient_light.color);
|
|
||||||
set_uniform_float(shader, "ambient_intens", scene->ambient_light.intensity);
|
|
||||||
|
|
||||||
set_uniform_vec3(shader, "point_pos", scene->point_light.position);
|
|
||||||
set_uniform_vec3(shader, "point_col", scene->point_light.color);
|
|
||||||
set_uniform_float(shader, "point_intens", scene->point_light.intensity);
|
|
||||||
|
|
||||||
set_uniform_vec3(shader, "cam_pos", scene->camera.object.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
int create_scene(Scene* scene)
|
int create_scene(Scene* scene)
|
||||||
{
|
{
|
||||||
assert(scene);
|
assert(scene);
|
||||||
|
@ -32,29 +18,13 @@ int create_scene(Scene* scene)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene->objects = create_dynamic_array(Object*);
|
|
||||||
scene->on_update = NULL;
|
scene->on_update = NULL;
|
||||||
scene->last_frame_start = glfwGetTime();
|
scene->last_frame_start = glfwGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_scene(Scene scene)
|
void destroy_scene(Scene scene)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < scene.objects.size; i++)
|
|
||||||
{
|
|
||||||
Object* obj = *(Object**)dynamic_array_get(&scene.objects, i);
|
|
||||||
destroy_object(*obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy_dynamic_array(scene.objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scene_add_object(Scene* scene, Object* object)
|
|
||||||
{
|
|
||||||
assert(scene);
|
|
||||||
|
|
||||||
object->scene = scene;
|
|
||||||
object->on_shader_use_scene = set_lighting_uniforms;
|
|
||||||
dynamic_array_push(&scene->objects, (void*)&object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void scene_update_size(Scene* scene, int width, int height)
|
void scene_update_size(Scene* scene, int width, int height)
|
||||||
|
@ -63,6 +33,12 @@ void scene_update_size(Scene* scene, int width, int height)
|
||||||
set_camera_perspective(&scene->camera, 90.0f, (float)width / (float)height);
|
set_camera_perspective(&scene->camera, 90.0f, (float)width / (float)height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scene_set_camera_uniforms(Scene* scene, Shader* shader)
|
||||||
|
{
|
||||||
|
set_uniform_mat4(shader, "view", get_camera_view(&scene->camera));
|
||||||
|
set_uniform_mat4(shader, "projection", scene->camera.projection);
|
||||||
|
}
|
||||||
|
|
||||||
void update_scene(Scene* scene)
|
void update_scene(Scene* scene)
|
||||||
{
|
{
|
||||||
double frametime = glfwGetTime() - scene->last_frame_start;
|
double frametime = glfwGetTime() - scene->last_frame_start;
|
||||||
|
@ -76,10 +52,5 @@ void render_scene(Scene* scene)
|
||||||
assert(scene);
|
assert(scene);
|
||||||
ctx_clear_screen(0.0f, 0.0f, 0.0f, 1.0f);
|
ctx_clear_screen(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
for (size_t i = 0; i < scene->objects.size; i++)
|
scene->on_render(scene);
|
||||||
{
|
|
||||||
Object* obj = *(Object**)dynamic_array_get(&scene->objects, i);
|
|
||||||
update_object(obj);
|
|
||||||
render_object(obj, &scene->camera);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,21 +11,18 @@
|
||||||
typedef struct Scene
|
typedef struct Scene
|
||||||
{
|
{
|
||||||
Camera camera;
|
Camera camera;
|
||||||
DynamicArray objects;
|
|
||||||
|
|
||||||
AmbientLight ambient_light;
|
|
||||||
PointLight point_light;
|
|
||||||
|
|
||||||
void* child;
|
void* child;
|
||||||
void(*on_update)(void*, double);
|
void(*on_update)(void*, double);
|
||||||
|
void(*on_render)(void*);
|
||||||
double last_frame_start;
|
double last_frame_start;
|
||||||
} Scene;
|
} Scene;
|
||||||
|
|
||||||
int create_scene(Scene* scene);
|
int create_scene(Scene* scene);
|
||||||
void destroy_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 scene_update_size(Scene* scene, int width, int height);
|
||||||
|
void scene_set_camera_uniforms(Scene* scene, Shader* shader);
|
||||||
|
|
||||||
void update_scene(Scene* scene);
|
void update_scene(Scene* scene);
|
||||||
void render_scene(Scene* scene);
|
void render_scene(Scene* scene);
|
||||||
|
|
|
@ -9,9 +9,73 @@
|
||||||
|
|
||||||
#include "objects/cube.h"
|
#include "objects/cube.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
|
#include "renderer/object.h"
|
||||||
|
|
||||||
|
static const char* vertex_shader =
|
||||||
|
"#version 460 core\n"
|
||||||
|
""
|
||||||
|
"layout (location = 0) in vec3 pos;"
|
||||||
|
"layout (location = 1) in vec3 normal;"
|
||||||
|
""
|
||||||
|
"out vec3 frag_normal;"
|
||||||
|
"out vec3 frag_pos;"
|
||||||
|
""
|
||||||
|
"uniform mat4 model;"
|
||||||
|
"uniform mat4 view;"
|
||||||
|
"uniform mat4 projection;"
|
||||||
|
""
|
||||||
|
"void main() {"
|
||||||
|
" frag_normal = mat3(transpose(inverse(model))) * normal;"
|
||||||
|
" frag_pos = vec3(model * vec4(pos, 1.0));"
|
||||||
|
" gl_Position = projection * view * model * vec4(pos, 1.0);"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
static const char* fragment_shader =
|
||||||
|
"#version 460 core\n"
|
||||||
|
""
|
||||||
|
"in vec3 frag_pos;"
|
||||||
|
"in vec3 frag_normal;"
|
||||||
|
""
|
||||||
|
"uniform vec3 ambient_color = vec3(1.0, 1.0, 1.0);"
|
||||||
|
"uniform float ambient_intens = 1.0f;"
|
||||||
|
""
|
||||||
|
"uniform vec3 point_pos = vec3(0.0, 0.0, 0.0);"
|
||||||
|
"uniform vec3 point_col = vec3(1.0, 1.0, 1.0);"
|
||||||
|
"uniform float point_intens = 1.0f;"
|
||||||
|
""
|
||||||
|
"uniform vec3 cam_pos = vec3(0.0, 0.0, 0.0);"
|
||||||
|
"float specular_strength = 0.5f;"
|
||||||
|
""
|
||||||
|
"uniform vec3 cube_color;"
|
||||||
|
""
|
||||||
|
"out vec4 FragColor;"
|
||||||
|
""
|
||||||
|
"void main() {"
|
||||||
|
" vec3 ambient = ambient_intens * ambient_color;"
|
||||||
|
""
|
||||||
|
" vec3 norm = normalize(frag_normal);"
|
||||||
|
" vec3 light_dir = normalize(point_pos - frag_pos);"
|
||||||
|
" float diff = max(dot(norm, light_dir), 0.0);"
|
||||||
|
" vec3 diffuse = diff * point_col;"
|
||||||
|
""
|
||||||
|
" vec3 view_dir = normalize(cam_pos - frag_pos);"
|
||||||
|
" vec3 reflect_dir = reflect(-light_dir, norm);"
|
||||||
|
""
|
||||||
|
" float spec = pow(max(dot(view_dir, reflect_dir), 0.0), 32);"
|
||||||
|
" vec3 specular = specular_strength * spec * point_col; "
|
||||||
|
""
|
||||||
|
" vec3 result = (ambient + diffuse + specular) * cube_color;"
|
||||||
|
" FragColor = vec4(result, 1.0);"
|
||||||
|
"}";
|
||||||
|
|
||||||
typedef struct SpinningCubes
|
typedef struct SpinningCubes
|
||||||
{
|
{
|
||||||
|
Shader cube_shader;
|
||||||
|
DynamicArray objects;
|
||||||
|
|
||||||
|
AmbientLight ambient_light;
|
||||||
|
PointLight point_light;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
double x, y;
|
double x, y;
|
||||||
} last_cursor_pos;
|
} last_cursor_pos;
|
||||||
|
@ -23,6 +87,20 @@ typedef struct SpinningCubes
|
||||||
double time;
|
double time;
|
||||||
} SpinningCubes;
|
} SpinningCubes;
|
||||||
|
|
||||||
|
static void set_lighting_uniforms(Shader* shader, Scene* scene)
|
||||||
|
{
|
||||||
|
SpinningCubes* data = scene->child;
|
||||||
|
|
||||||
|
set_uniform_vec3(shader, "ambient_color", data->ambient_light.color);
|
||||||
|
set_uniform_float(shader, "ambient_intens", data->ambient_light.intensity);
|
||||||
|
|
||||||
|
set_uniform_vec3(shader, "point_pos", data->point_light.position);
|
||||||
|
set_uniform_vec3(shader, "point_col", data->point_light.color);
|
||||||
|
set_uniform_float(shader, "point_intens", data->point_light.intensity);
|
||||||
|
|
||||||
|
set_uniform_vec3(shader, "cam_pos", scene->camera.object.position);
|
||||||
|
}
|
||||||
|
|
||||||
static void init_spinning_cubes_data(SpinningCubes* scene)
|
static void init_spinning_cubes_data(SpinningCubes* scene)
|
||||||
{
|
{
|
||||||
assert(scene);
|
assert(scene);
|
||||||
|
@ -31,6 +109,8 @@ static void init_spinning_cubes_data(SpinningCubes* scene)
|
||||||
scene->dragging = false;
|
scene->dragging = false;
|
||||||
scene->drag_speed = 0.01f;
|
scene->drag_speed = 0.01f;
|
||||||
scene->time = 0.0f;
|
scene->time = 0.0f;
|
||||||
|
|
||||||
|
scene->objects = create_dynamic_array(Object*);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_arcball_vector(vec3 dest, double width, double height, double x, double y)
|
static void get_arcball_vector(vec3 dest, double width, double height, double x, double y)
|
||||||
|
@ -113,23 +193,48 @@ static void mouse_moved_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
static void on_update(Scene* scene, double frametime)
|
static void on_update(Scene* scene, double frametime)
|
||||||
{
|
{
|
||||||
SpinningCubes* data = scene->child;
|
SpinningCubes* data = scene->child;
|
||||||
|
|
||||||
|
for (int i = 0; i < data->objects.size; i++)
|
||||||
|
{
|
||||||
|
Object* obj = *(Object**)dynamic_array_get(&data->objects, i);
|
||||||
|
update_object(obj);
|
||||||
|
}
|
||||||
|
|
||||||
vec3 cam_pos = { 6.0f * sin(2.0f * data->time), 3.5f * cos(data->time), 6.0f * cos(2.0f * data->time)};
|
vec3 cam_pos = { 6.0f * sin(2.0f * data->time), 3.5f * cos(data->time), 6.0f * cos(2.0f * data->time)};
|
||||||
|
|
||||||
object_set_position(&scene->camera.object, cam_pos);
|
object_set_position(&scene->camera.object, cam_pos);
|
||||||
data->time += frametime;
|
data->time += frametime;
|
||||||
|
|
||||||
glm_vec3_copy(scene->camera.object.position, scene->point_light.position);
|
glm_vec3_copy(scene->camera.object.position, data->point_light.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_spinning_cubes_scene(Window* window, Scene* scene)
|
static void on_render(Scene* scene)
|
||||||
|
{
|
||||||
|
SpinningCubes* data = scene->child;
|
||||||
|
|
||||||
|
bind_shader(&data->cube_shader);
|
||||||
|
set_lighting_uniforms(&data->cube_shader, scene);
|
||||||
|
scene_set_camera_uniforms(scene, &data->cube_shader);
|
||||||
|
|
||||||
|
for (int i = 0; i < data->objects.size; i++)
|
||||||
|
{
|
||||||
|
shader_add_object(&data->cube_shader, *(Object**)dynamic_array_get(&data->objects, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
shader_render(&data->cube_shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_spinning_cubes_scene(Window* window, Scene* scene)
|
||||||
{
|
{
|
||||||
assert(scene);
|
assert(scene);
|
||||||
|
|
||||||
create_scene(scene);
|
create_scene(scene);
|
||||||
scene->on_update = on_update;
|
scene->on_update = on_update;
|
||||||
|
scene->on_render = on_render;
|
||||||
scene->child = malloc(sizeof(SpinningCubes));
|
scene->child = malloc(sizeof(SpinningCubes));
|
||||||
init_spinning_cubes_data(scene->child);
|
init_spinning_cubes_data(scene->child);
|
||||||
|
|
||||||
|
SpinningCubes* data = scene->child;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
Cube* obj = (Cube*)malloc(sizeof(Cube));
|
Cube* obj = (Cube*)malloc(sizeof(Cube));
|
||||||
|
@ -140,22 +245,31 @@ void create_spinning_cubes_scene(Window* window, Scene* scene)
|
||||||
0.0f,
|
0.0f,
|
||||||
((i < 2) ? -1 : 1) * 1.5
|
((i < 2) ? -1 : 1) * 1.5
|
||||||
};
|
};
|
||||||
|
|
||||||
object_set_position(&obj->object, position);
|
object_set_position(&obj->object, position);
|
||||||
|
|
||||||
scene_add_object(scene, &obj->object);
|
Object* raw_obj = &obj->object;
|
||||||
|
dynamic_array_push(&data->objects, (void*)&raw_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(create_shader(&data->cube_shader, vertex_shader, fragment_shader) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "failed to create shader for cube\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 cam_pos = { 0.0f, 3.5f, 3.0 };
|
vec3 cam_pos = { 0.0f, 3.5f, 3.0 };
|
||||||
object_set_position(&scene->camera.object, cam_pos);
|
object_set_position(&scene->camera.object, cam_pos);
|
||||||
glm_vec3_zero(&scene->camera.look_at);
|
glm_vec3_zero(&scene->camera.look_at);
|
||||||
|
|
||||||
|
glm_vec3_one(data->ambient_light.color);
|
||||||
|
data->ambient_light.intensity = 0.1f;
|
||||||
|
|
||||||
glm_vec3_one(scene->ambient_light.color);
|
glm_vec3_one(data->point_light.color);
|
||||||
scene->ambient_light.intensity = 0.1f;
|
data->point_light.intensity = 1.0f;
|
||||||
|
|
||||||
glm_vec3_one(scene->point_light.color);
|
|
||||||
scene->point_light.intensity = 1.0f;
|
|
||||||
|
|
||||||
glfwSetMouseButtonCallback(window->window, mouse_button_callback);
|
glfwSetMouseButtonCallback(window->window, mouse_button_callback);
|
||||||
glfwSetCursorPosCallback(window->window, mouse_moved_callback);
|
glfwSetCursorPosCallback(window->window, mouse_moved_callback);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "renderer/window.h"
|
#include "renderer/window.h"
|
||||||
|
|
||||||
void create_spinning_cubes_scene(Window* window, Scene* scene);
|
int create_spinning_cubes_scene(Window* window, Scene* scene);
|
||||||
|
|
||||||
#endif // SCENE_SPINNING_CUBES_H
|
#endif // SCENE_SPINNING_CUBES_H
|
|
@ -36,6 +36,14 @@ void* dynamic_array_get(DynamicArray* array, size_t i)
|
||||||
return (void*)((char*)array->data + (i * array->element_size));
|
return (void*)((char*)array->data + (i * array->element_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dynamic_array_clear(DynamicArray* array)
|
||||||
|
{
|
||||||
|
array->capacity = 5;
|
||||||
|
array->size = 0;
|
||||||
|
|
||||||
|
array->data = realloc(array->data, array->element_size * array->capacity);
|
||||||
|
}
|
||||||
|
|
||||||
void dynamic_array_push(DynamicArray* array, void* element)
|
void dynamic_array_push(DynamicArray* array, void* element)
|
||||||
{
|
{
|
||||||
assert(array->capacity > 0);
|
assert(array->capacity > 0);
|
||||||
|
|
|
@ -18,6 +18,7 @@ DynamicArray create_dynamic_array_from_size(size_t type_size);
|
||||||
void destroy_dynamic_array(DynamicArray array);
|
void destroy_dynamic_array(DynamicArray array);
|
||||||
|
|
||||||
void* dynamic_array_get(DynamicArray* array, size_t i);
|
void* dynamic_array_get(DynamicArray* array, size_t i);
|
||||||
|
void dynamic_array_clear(DynamicArray* array);
|
||||||
|
|
||||||
void dynamic_array_push(DynamicArray* array, void* element);
|
void dynamic_array_push(DynamicArray* array, void* element);
|
||||||
void dynamic_array_pop(DynamicArray* array);
|
void dynamic_array_pop(DynamicArray* array);
|
||||||
|
|
Loading…
Reference in a new issue