From ff207a458eaef905170d157e5344cfcbe855549e Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 18 Aug 2024 15:15:19 +0100 Subject: [PATCH] Create shaders --- src/main.c | 55 ++++--------------- src/shaders.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/shaders.h | 6 ++ 3 files changed, 166 insertions(+), 43 deletions(-) create mode 100644 src/shaders.c create mode 100644 src/shaders.h diff --git a/src/main.c b/src/main.c index 1d2fe9d..f0895e6 100644 --- a/src/main.c +++ b/src/main.c @@ -1,9 +1,10 @@ -#include "aliases.h" #include "img.h" #include "mem_arena.h" #include "mem_utils.h" #include "obj.h" -#include "vec.h" +#include "shader.h" +#include "shaders.h" +#include #include #include #include @@ -12,10 +13,12 @@ #define SIZE 1200 #define RESOURCE(NAME) "resources/" NAME -V3f g_eye = {0.2f, 0.1f, 0.75f}; -V3f g_target = {0}; -V3f g_up = {0.0f, 1.0f, 0.0f}; -M4x4f g_cam_matrix = mat4x4_identity; +extern ShaderID perspective_lit_textured_id; +extern ShaderID perspective_lit_coloured_id; +extern ShaderID perspective_albedo_id; +extern ShaderID orthographic_lit_textured_id; +extern ShaderID orthographic_lit_coloured_id; +extern ShaderID orthographic_albedo_id; enum { TINY_EXIT_SUCCESS, @@ -24,10 +27,6 @@ enum { TINY_EXIT_MODEL_LOAD_FAILED, }; -internal M4x4f get_projection_matrix(ProjectionType projection_type); -internal V3f main_shader_vertex(const V3f *vertex, M4x4f *model_view, - M4x4f *projection, const Image *img); - int main(void) { Arena *arena = NULL; if (!wapp_mem_arena_init(&arena, 10ul * 1024ul * 1024ul * 1024ul, @@ -49,44 +48,14 @@ int main(void) { return TINY_EXIT_MODEL_LOAD_FAILED; } - M4x4f model_view = lookat(g_eye, g_target, g_up); - M4x4f perspective_projection = - get_projection_matrix(PROJECTION_TYPE_PERSPECTIVE); - - Shader main_shader = { - .vertex = main_shader_vertex, - .model_view = &model_view, - .projection = &perspective_projection, - }; + load_shaders(); clear_buffer(&(render.img), &bg); - render_model(&obj, &render, &main_shader, RENDER_TYPE_SHADED, teal); + render_model(&obj, &render, perspective_lit_textured_id, RENDER_TYPE_SHADED, + teal); save_image(&(render.img), "result.pam"); wapp_mem_arena_destroy(&arena); return TINY_EXIT_SUCCESS; } - -internal M4x4f get_projection_matrix(ProjectionType projection_type) { - if (projection_type == PROJECTION_TYPE_PERSPECTIVE) { - // Calculate projection matrix - V3f cam = V3(V3f, f32, g_target.x, g_target.y, g_target.z, g_eye.x, g_eye.y, - g_eye.z); - normalise_v3(cam); - f32 coeff = -1.0f / magnitude_v3(cam) * 0.5f; - return projection(coeff); - } - - return mat4x4_identity; -} - -internal V3f main_shader_vertex(const V3f *vertex, M4x4f *model_view, - M4x4f *projection, const Image *img) { - V4f vh = {.x = vertex->x, .y = vertex->y, .z = vertex->z, .w = 1.0f}; - vh = mat4x4_mul_vec4((*projection), mat4x4_mul_vec4((*model_view), vh)); - vh.y = 0.0 - vh.y; - vh = mat4x4_mul_vec4(viewport(vh.x, vh.y, img->width, img->height), vh); - - return project_vec4(vh); -} diff --git a/src/shaders.c b/src/shaders.c new file mode 100644 index 0000000..34b7c9c --- /dev/null +++ b/src/shaders.c @@ -0,0 +1,148 @@ +#include "img.h" +#include "obj.h" +#include "shader.h" +#include "utils.h" +#include "vec.h" + +typedef struct shader Shader; +struct shader { + M4x4f model_view; + M4x4f projection; +}; + +Shader perspective = {0}; +Shader orthographic = {0}; + +ShaderID perspective_lit_textured_id = {0}; +ShaderID perspective_lit_coloured_id = {0}; +ShaderID perspective_albedo_id = {0}; +ShaderID orthographic_lit_textured_id = {0}; +ShaderID orthographic_lit_coloured_id = {0}; +ShaderID orthographic_albedo_id = {0}; + +V3f g_light_dir = {0.0f, 0.0f, 1.0f}; +V3f g_eye = {0.2f, 0.1f, 0.75f}; +V3f g_target = {0}; +V3f g_up = {0.0f, 1.0f, 0.0f}; +M4x4f g_cam_matrix = mat4x4_identity; + +internal V3f general_shader_vertex(void *shader, const V3f *vertex, + const Buffer *out_buf); +internal FragmentResult lit_textured_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture); +internal FragmentResult lit_coloured_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture); +internal FragmentResult albedo_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture); +internal M4x4f get_projection_matrix(ProjectionType projection_type); +internal f32 get_intensity(const V3f *normal); + +void load_shaders(void) { + M4x4f model_view = lookat(g_eye, g_target, g_up); + M4x4f orthographic_projection = + get_projection_matrix(PROJECTION_TYPE_ORTHOGRAPHIC); + M4x4f perspective_projection = + get_projection_matrix(PROJECTION_TYPE_PERSPECTIVE); + + perspective.model_view = orthographic.model_view = model_view; + perspective.projection = perspective_projection; + orthographic.projection = orthographic_projection; + + perspective_lit_textured_id = create_shader( + &perspective, general_shader_vertex, lit_textured_shader_fragment); + perspective_lit_coloured_id = create_shader( + &perspective, general_shader_vertex, lit_coloured_shader_fragment); + perspective_albedo_id = create_shader(&perspective, general_shader_vertex, + albedo_shader_fragment); + orthographic_lit_textured_id = create_shader( + &orthographic, general_shader_vertex, lit_textured_shader_fragment); + orthographic_lit_coloured_id = create_shader( + &orthographic, general_shader_vertex, lit_coloured_shader_fragment); + orthographic_albedo_id = create_shader(&orthographic, general_shader_vertex, + albedo_shader_fragment); +} + +internal V3f general_shader_vertex(void *shader, const V3f *vertex, + const Buffer *out_buf) { + Shader *shader_ptr = (Shader *)shader; + + V4f vh = {.x = vertex->x, .y = vertex->y, .z = vertex->z, .w = 1.0f}; + vh = mat4x4_mul_vec4(shader_ptr->projection, + mat4x4_mul_vec4(shader_ptr->model_view, vh)); + vh.y = 0.0 - vh.y; + vh = mat4x4_mul_vec4(viewport(vh.x, vh.y, out_buf->width, out_buf->height), + vh); + + return project_vec4(vh); +} + +internal FragmentResult lit_textured_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture) { + if (!texture) { + return DISCARDED_FRAGMENT; + } + + f32 intensity = get_intensity(&normal); + + u64 tx_x = tex_coords.u * texture->width; + u64 tx_y = (1.0f - tex_coords.v) * texture->height; + + Colour output = get_pixel(Colour, texture, tx_x, tx_y); + + output.r *= intensity; + output.g *= intensity; + output.b *= intensity; + + return (FragmentResult){.colour = output}; +} + +internal FragmentResult lit_coloured_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture) { + f32 intensity = get_intensity(&normal); + Colour output = *colour; + + output.r *= intensity; + output.g *= intensity; + output.b *= intensity; + + return (FragmentResult){.colour = output}; +} + +internal FragmentResult albedo_shader_fragment(void *shader, V3f normal, + V2f tex_coords, + const Colour *colour, + const Image *texture) { + return (FragmentResult){.colour = *colour}; +} + +internal M4x4f get_projection_matrix(ProjectionType projection_type) { + if (projection_type == PROJECTION_TYPE_PERSPECTIVE) { + // Calculate projection matrix + V3f cam = V3(V3f, f32, g_target.x, g_target.y, g_target.z, g_eye.x, g_eye.y, + g_eye.z); + normalise_v3(cam); + f32 coeff = -1.0f / magnitude_v3(cam) * 0.5f; + return projection(coeff); + } + + return mat4x4_identity; +} + +internal f32 get_intensity(const V3f *normal) { + f32 intensity = dot_v3((*normal), g_light_dir); + if (intensity < 0.0f) { + intensity = 0.01f; + } + + return intensity; +} diff --git a/src/shaders.h b/src/shaders.h new file mode 100644 index 0000000..2022243 --- /dev/null +++ b/src/shaders.h @@ -0,0 +1,6 @@ +#ifndef SHADERS_H +#define SHADERS_H + +void load_shaders(void); + +#endif // SHADERS_H