Create shaders

This commit is contained in:
Abdelrahman Said 2024-08-18 15:15:19 +01:00
parent 891a97739f
commit ff207a458e
3 changed files with 166 additions and 43 deletions

View File

@ -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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -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);
}

148
src/shaders.c Normal file
View File

@ -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;
}

6
src/shaders.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef SHADERS_H
#define SHADERS_H
void load_shaders(void);
#endif // SHADERS_H