Compare commits
2 Commits
6d6d4781ff
...
891a97739f
Author | SHA1 | Date | |
---|---|---|---|
891a97739f | |||
6c275baa20 |
20
src/img.c
20
src/img.c
@ -7,7 +7,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
|
||||
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
|
||||
|
||||
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
|
||||
if (!arena || !buffer || buffer->width == 0 || buffer->height == 0) {
|
||||
@ -21,12 +21,20 @@ bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
|
||||
}
|
||||
|
||||
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
|
||||
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||
if (idx == -1) {
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
return ((u8 *)(buffer->buf)) + idx;
|
||||
}
|
||||
|
||||
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
|
||||
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
|
||||
return;
|
||||
}
|
||||
@ -75,7 +83,11 @@ void save_image(const Image *img, const char *filename) {
|
||||
write_p7_image(img->width, img->height, (u8 *)(img->buf), filename);
|
||||
}
|
||||
|
||||
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
|
||||
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
|
||||
u64 base_size) {
|
||||
if (x < 0 || y < 0 || x >= buffer->width || y >= buffer->height) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (y * buffer->width + x) * base_size;
|
||||
}
|
||||
|
51
src/obj.c
51
src/obj.c
@ -3,6 +3,7 @@
|
||||
#include "img.h"
|
||||
#include "mem_arena.h"
|
||||
#include "pam.h"
|
||||
#include "shader.h"
|
||||
#include "typed_list.h"
|
||||
#include "utils.h"
|
||||
#include "vec.h"
|
||||
@ -23,9 +24,10 @@ struct triangle_bbox {
|
||||
};
|
||||
|
||||
internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||
const Shader *shader, Render *render,
|
||||
ShaderID shader, Render *render,
|
||||
RenderType render_type, Colour colour);
|
||||
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||
internal void fill_triangle(Render *render, ShaderID shader,
|
||||
V3f vertices[TRIANGLE_VERTICES],
|
||||
V3f normals[TRIANGLE_VERTICES],
|
||||
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
||||
Image *texture, RenderType type);
|
||||
@ -36,8 +38,6 @@ internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
||||
const V2i *ap);
|
||||
internal V3f get_viewport_vertex(const V3f *vertex, const Image *img);
|
||||
|
||||
V3f g_light_dir = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
Model load_obj_file(Arena *arena, const char *filename, const char *texture) {
|
||||
if (!arena) {
|
||||
return INVALID_MODEL;
|
||||
@ -131,7 +131,7 @@ bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void render_model(const Model *model, Render *render, const Shader *shader,
|
||||
void render_model(const Model *model, Render *render, ShaderID shader,
|
||||
RenderType render_type, Colour colour) {
|
||||
Triangle triangle;
|
||||
for (u64 i = 0; i < model->triangles->count; ++i) {
|
||||
@ -141,7 +141,7 @@ void render_model(const Model *model, Render *render, const Shader *shader,
|
||||
}
|
||||
|
||||
internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||
const Shader *shader, Render *render,
|
||||
ShaderID shader, Render *render,
|
||||
RenderType render_type, Colour colour) {
|
||||
Image *img = &(render->img);
|
||||
V3f vertices[TRIANGLE_VERTICES] = {
|
||||
@ -161,8 +161,8 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||
};
|
||||
|
||||
for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
|
||||
vertices[i] = shader->vertex(&vertices[i], shader->model_view,
|
||||
shader->projection, &render->img);
|
||||
vertices[i] =
|
||||
run_vertex_shader(shader, &vertices[i], (Buffer *)&render->img);
|
||||
}
|
||||
|
||||
if (render_type == RENDER_TYPE_WIREFRAME) {
|
||||
@ -176,12 +176,13 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||
}
|
||||
} else if (render_type == RENDER_TYPE_FILLED ||
|
||||
render_type == RENDER_TYPE_SHADED) {
|
||||
fill_triangle(render, vertices, normals, coordinates, colour,
|
||||
fill_triangle(render, shader, vertices, normals, coordinates, colour,
|
||||
model->texture, render_type);
|
||||
}
|
||||
}
|
||||
|
||||
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||
internal void fill_triangle(Render *render, ShaderID shader,
|
||||
V3f vertices[TRIANGLE_VERTICES],
|
||||
V3f normals[TRIANGLE_VERTICES],
|
||||
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
||||
Image *texture, RenderType type) {
|
||||
@ -207,6 +208,8 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||
V3f normal;
|
||||
f32 tx_u, tx_v;
|
||||
u64 tx_x, tx_y;
|
||||
V2f tex_coords;
|
||||
FragmentResult result;
|
||||
|
||||
f32 intensity = 1.0f;
|
||||
|
||||
@ -222,8 +225,10 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||
z += v0.z * coords.x + v1.z * coords.y + v2.z * coords.z;
|
||||
zbuf = get_pixel(f32, &(render->depth), x, y);
|
||||
|
||||
if (z > zbuf) {
|
||||
if (type == RENDER_TYPE_SHADED) {
|
||||
if (z <= zbuf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 +
|
||||
@ -231,31 +236,21 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||
nz = normals[0].z * coords.x + normals[1].z * coords.y +
|
||||
normals[2].z * coords.z;
|
||||
normal = (V3f){nx, ny, nz};
|
||||
intensity = dot_v3(normal, g_light_dir);
|
||||
}
|
||||
|
||||
if (intensity < 0.0f) {
|
||||
intensity = 0.01f;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
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;
|
||||
tx_x = tx_u * texture->width;
|
||||
tx_y = (1.0f - tx_v) * texture->height;
|
||||
tex_coords = (V2f){tx_u, tx_v};
|
||||
|
||||
colour = get_pixel(Colour, texture, tx_x, tx_y);
|
||||
result =
|
||||
run_fragment_shader(shader, normal, tex_coords, &colour, texture);
|
||||
if (DISCARD_FRAGMENT(result)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
colour.r *= intensity;
|
||||
colour.g *= intensity;
|
||||
colour.b *= intensity;
|
||||
|
||||
set_pixel(depth, x, y, &z);
|
||||
set_pixel(img, x, y, &colour);
|
||||
}
|
||||
set_pixel(img, x, y, &result.colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ struct render {
|
||||
|
||||
Model load_obj_file(Arena *arena, const char *filename, const char *texture);
|
||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height);
|
||||
void render_model(const Model *model, Render *render, const Shader *shader,
|
||||
void render_model(const Model *model, Render *render, ShaderID shader,
|
||||
RenderType render_type, Colour colour);
|
||||
|
||||
#endif // OBJ_H
|
||||
|
62
src/shader.c
Normal file
62
src/shader.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "shader.h"
|
||||
#include "aliases.h"
|
||||
#include "vec.h"
|
||||
|
||||
#define MAX_SHADER_COUNT 2048
|
||||
|
||||
typedef struct shader_repo ShaderRepo;
|
||||
struct shader_repo {
|
||||
void *shaders[MAX_SHADER_COUNT];
|
||||
VertexShader *vertex_funcs[MAX_SHADER_COUNT];
|
||||
FragmentShader *fragment_funcs[MAX_SHADER_COUNT];
|
||||
u64 count;
|
||||
};
|
||||
|
||||
internal ShaderRepo g_repository = {0};
|
||||
|
||||
ShaderID create_shader(void *shader, VertexShader *vertex,
|
||||
FragmentShader *fragment) {
|
||||
if (g_repository.count + 1 >= MAX_SHADER_COUNT) {
|
||||
return INVALID_SHADER;
|
||||
}
|
||||
|
||||
++(g_repository.count);
|
||||
g_repository.shaders[g_repository.count] = shader;
|
||||
g_repository.vertex_funcs[g_repository.count] = vertex;
|
||||
g_repository.fragment_funcs[g_repository.count] = fragment;
|
||||
|
||||
return (ShaderID){g_repository.count};
|
||||
}
|
||||
|
||||
V3f run_vertex_shader(ShaderID shader, const V3f *vertex,
|
||||
const Buffer *out_buf) {
|
||||
if (IS_INVALID_SHADER(shader) || shader.id > g_repository.count || !vertex ||
|
||||
!out_buf) {
|
||||
return (V3f){0};
|
||||
}
|
||||
|
||||
void *shader_obj = g_repository.shaders[shader.id];
|
||||
VertexShader *vertex_func = g_repository.vertex_funcs[shader.id];
|
||||
|
||||
if (!shader_obj || !vertex_func) {
|
||||
return (V3f){0};
|
||||
}
|
||||
|
||||
return vertex_func(shader_obj, vertex, out_buf);
|
||||
}
|
||||
|
||||
FragmentResult run_fragment_shader(ShaderID shader, V3f normal, V2f tex_coords,
|
||||
const Colour *colour, const Image *texture) {
|
||||
if (IS_INVALID_SHADER(shader) || shader.id > g_repository.count || !colour) {
|
||||
return DISCARDED_FRAGMENT;
|
||||
}
|
||||
|
||||
void *shader_obj = g_repository.shaders[shader.id];
|
||||
FragmentShader *fragment_func = g_repository.fragment_funcs[shader.id];
|
||||
|
||||
if (!shader_obj || !fragment_func) {
|
||||
return DISCARDED_FRAGMENT;
|
||||
}
|
||||
|
||||
return fragment_func(shader_obj, normal, tex_coords, colour, texture);
|
||||
}
|
38
src/shader.h
38
src/shader.h
@ -1,19 +1,37 @@
|
||||
#ifndef SHADER_H
|
||||
#define SHADER_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "img.h"
|
||||
#include "vec.h"
|
||||
|
||||
typedef V3f(VertexShader)(const V3f *vertex, M4x4f *model_view,
|
||||
M4x4f *projection, const Image *img);
|
||||
typedef bool(FragmentShader)(Colour colour);
|
||||
|
||||
typedef struct shader Shader;
|
||||
struct shader {
|
||||
VertexShader *vertex;
|
||||
FragmentShader *fragment;
|
||||
M4x4f *model_view;
|
||||
M4x4f *projection;
|
||||
typedef struct shader_id ShaderID;
|
||||
struct shader_id {
|
||||
u64 id;
|
||||
};
|
||||
|
||||
typedef struct fragment_result FragmentResult;
|
||||
struct fragment_result {
|
||||
Colour colour;
|
||||
bool discard;
|
||||
};
|
||||
|
||||
#define INVALID_SHADER ((ShaderID){0})
|
||||
#define IS_INVALID_SHADER(ID) (ID.id == 0)
|
||||
#define DISCARDED_FRAGMENT ((FragmentResult){.discard = true})
|
||||
#define DISCARD_FRAGMENT(RESULT) (RESULT.discard)
|
||||
|
||||
typedef V3f(VertexShader)(void *shader, const V3f *vertex,
|
||||
const Buffer *out_buf);
|
||||
typedef FragmentResult(FragmentShader)(void *shader, V3f normal, V2f tex_coords,
|
||||
const Colour *colour,
|
||||
const Image *texture);
|
||||
|
||||
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,
|
||||
const Colour *colour, const Image *texture);
|
||||
|
||||
#endif // SHADER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user