diff --git a/src/model/render.c b/src/model/render.c index e14b5f1..5171f90 100644 --- a/src/model/render.c +++ b/src/model/render.c @@ -1,5 +1,7 @@ #include "render.h" +#include "shader.h" #include "utils.h" +#include "vec.h" #include #define TRIANGLE_VERTICES 3 @@ -117,11 +119,14 @@ internal void fill_triangle(Render *render, ShaderID shader, V3f coords; f32 z; f32 zbuf; + f32 px, py, pz; + V3f position; f32 nx, ny, nz; V3f normal; f32 tx_u, tx_v; u64 tx_x, tx_y; V2f tex_coords; + FragmentData data = {0}; FragmentResult result; f32 intensity = 1.0f; @@ -142,6 +147,16 @@ internal void fill_triangle(Render *render, ShaderID shader, continue; } + px = vertices[0].x * coords.x + vertices[1].x * coords.y + + vertices[2].x * coords.z; + py = vertices[0].y * coords.x + vertices[1].y * coords.y + + vertices[2].y * coords.z; + pz = vertices[0].z * coords.x + vertices[1].z * coords.y + + vertices[2].z * coords.z; + position = (V3f){px, py, pz}; + normalise_v3(position); + data.position = position; + nx = normals[0].x * coords.x + normals[1].x * coords.y + normals[2].x * coords.z; ny = normals[0].y * coords.x + normals[1].y * coords.y + @@ -149,14 +164,16 @@ internal void fill_triangle(Render *render, ShaderID shader, nz = normals[0].z * coords.x + normals[1].z * coords.y + normals[2].z * coords.z; normal = (V3f){nx, ny, nz}; + data.normal = normal; tx_u = coordinates[0].u * coords.x + coordinates[1].u * coords.y + coordinates[2].u * coords.z; tx_v = coordinates[0].v * coords.x + coordinates[1].v * coords.y + coordinates[2].v * coords.z; tex_coords = (V2f){tx_u, tx_v}; + data.tex_coords = tex_coords; - result = run_fragment_shader(shader, normal, tex_coords, &colour, model); + result = run_fragment_shader(shader, &data, &colour, model); if (DISCARD_FRAGMENT(result)) { continue; } diff --git a/src/shader/shader.c b/src/shader/shader.c index c6b162e..ace6d61 100644 --- a/src/shader/shader.c +++ b/src/shader/shader.c @@ -45,7 +45,7 @@ V3f run_vertex_shader(ShaderID shader, const V3f *vertex, return vertex_func(shader_obj, vertex, out_buf); } -FragmentResult run_fragment_shader(ShaderID shader, V3f normal, V2f tex_coords, +FragmentResult run_fragment_shader(ShaderID shader, const FragmentData *data, const Colour *colour, const Model *model) { if (IS_INVALID_SHADER(shader) || shader.id > g_repository.count || !colour) { return DISCARDED_FRAGMENT; @@ -58,5 +58,5 @@ FragmentResult run_fragment_shader(ShaderID shader, V3f normal, V2f tex_coords, return DISCARDED_FRAGMENT; } - return fragment_func(shader_obj, normal, tex_coords, colour, model); + return fragment_func(shader_obj, data, colour, model); } diff --git a/src/shader/shader.h b/src/shader/shader.h index afea063..314a6bd 100644 --- a/src/shader/shader.h +++ b/src/shader/shader.h @@ -17,6 +17,13 @@ struct fragment_result { bool discard; }; +typedef struct fragment_data FragmentData; +struct fragment_data { + V3f position; + V3f normal; + V2f tex_coords; +}; + #define INVALID_SHADER ((ShaderID){0}) #define IS_INVALID_SHADER(ID) (ID.id == 0) #define DISCARDED_FRAGMENT ((FragmentResult){.discard = true}) @@ -24,7 +31,7 @@ struct fragment_result { typedef V3f(VertexShader)(void *shader, const V3f *vertex, const Buffer *out_buf); -typedef FragmentResult(FragmentShader)(void *shader, V3f normal, V2f tex_coords, +typedef FragmentResult(FragmentShader)(void *shader, const FragmentData *data, const Colour *colour, const Model *model); @@ -32,7 +39,7 @@ ShaderID create_shader(void *shader, VertexShader *vertex, FragmentShader *fragment); V3f run_vertex_shader(ShaderID shader, const V3f *vertex, const Buffer *out_buf); -FragmentResult run_fragment_shader(ShaderID shader, V3f normal, V2f tex_coords, +FragmentResult run_fragment_shader(ShaderID shader, const FragmentData *data, const Colour *colour, const Model *model); #endif // SHADER_H diff --git a/src/shader/shaders.c b/src/shader/shaders.c index a867c49..84ee0ea 100644 --- a/src/shader/shaders.c +++ b/src/shader/shaders.c @@ -10,15 +10,15 @@ struct shader { M4x4f projection; }; -internal Shader perspective = {0}; -internal Shader orthographic = {0}; - ShaderID perspective_phong = {0}; ShaderID perspective_albedo = {0}; ShaderID orthographic_phong = {0}; ShaderID orthographic_albedo = {0}; -internal V3f g_light_dir = {0.0f, 0.0f, 1.0f}; +internal Shader perspective = {0}; +internal Shader orthographic = {0}; + +internal V3f g_directional_light = {0.0f, 0.0f, 1.0f}; internal V3f g_eye = {0.2f, 0.1f, 0.75f}; internal V3f g_target = {0}; internal V3f g_up = {0.0f, 1.0f, 0.0f}; @@ -26,12 +26,12 @@ internal M4x4f g_cam_matrix = mat4x4_identity; internal V3f general_shader_vertex(void *shader, const V3f *vertex, const Buffer *out_buf); -internal FragmentResult phong_shader_fragment(void *shader, V3f normal, - V2f tex_coords, +internal FragmentResult phong_shader_fragment(void *shader, + const FragmentData *data, const Colour *colour, const Model *model); -internal FragmentResult albedo_shader_fragment(void *shader, V3f normal, - V2f tex_coords, +internal FragmentResult albedo_shader_fragment(void *shader, + const FragmentData *data, const Colour *colour, const Model *model); internal M4x4f get_projection_matrix(ProjectionType projection_type); @@ -76,14 +76,14 @@ internal V3f general_shader_vertex(void *shader, const V3f *vertex, return output; } -internal FragmentResult phong_shader_fragment(void *shader, V3f normal, - V2f tex_coords, +internal FragmentResult phong_shader_fragment(void *shader, + const FragmentData *data, const Colour *colour, const Model *model) { f32 intensity; if (model->normal) { - u64 nm_x = tex_coords.u * model->normal->width; - u64 nm_y = (1.0f - tex_coords.v) * model->normal->height; + u64 nm_x = data->tex_coords.u * model->normal->width; + u64 nm_y = (1.0f - data->tex_coords.v) * model->normal->height; Colour pixel = get_pixel(Colour, model->normal, nm_x, nm_y); V3f norm = {.x = pixel.r, .y = pixel.g, .z = pixel.b}; @@ -91,27 +91,27 @@ internal FragmentResult phong_shader_fragment(void *shader, V3f normal, intensity = get_intensity(&norm); } else { - intensity = get_intensity(&normal); + intensity = get_intensity(&data->normal); } Colour output; if (model->texture) { - u64 tx_x = tex_coords.u * model->texture->width; - u64 tx_y = (1.0f - tex_coords.v) * model->texture->height; + u64 tx_x = data->tex_coords.u * model->texture->width; + u64 tx_y = (1.0f - data->tex_coords.v) * model->texture->height; output = get_pixel(Colour, model->texture, tx_x, tx_y); } else { output = *colour; } - output.r *= intensity; - output.g *= intensity; - output.b *= intensity; + output.r = clamp(intensity * output.r, 0.0f, 255.0f); + output.g = clamp(intensity * output.g, 0.0f, 255.0f); + output.b = clamp(intensity * output.b, 0.0f, 255.0f); return (FragmentResult){.colour = output}; } -internal FragmentResult albedo_shader_fragment(void *shader, V3f normal, - V2f tex_coords, +internal FragmentResult albedo_shader_fragment(void *shader, + const FragmentData *data, const Colour *colour, const Model *model) { return (FragmentResult){.colour = *colour}; @@ -131,7 +131,7 @@ internal M4x4f get_projection_matrix(ProjectionType projection_type) { } internal f32 get_intensity(const V3f *normal) { - V3f light = g_light_dir; + V3f light = g_directional_light; normalise_v3(light); f32 intensity = dot_v3((*normal), light);