Compare commits

..

No commits in common. "891a97739f63872d66a0678ac43d72bfa80bad22" and "6d6d4781ff9d9049c346319bcb22fac9475c3a40" have entirely different histories.

5 changed files with 58 additions and 145 deletions

View File

@ -7,7 +7,7 @@
#include <stddef.h>
#include <string.h>
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
internal u64 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,20 +21,12 @@ bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
}
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
if (idx == -1) {
idx = 0;
}
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
return ((u8 *)(buffer->buf)) + idx;
}
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
if (idx == -1) {
return;
}
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
return;
}
@ -83,11 +75,7 @@ void save_image(const Image *img, const char *filename) {
write_p7_image(img->width, img->height, (u8 *)(img->buf), filename);
}
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
internal u64 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;
}

View File

@ -3,7 +3,6 @@
#include "img.h"
#include "mem_arena.h"
#include "pam.h"
#include "shader.h"
#include "typed_list.h"
#include "utils.h"
#include "vec.h"
@ -24,10 +23,9 @@ struct triangle_bbox {
};
internal void render_triangle(const Triangle *triangle, const Model *model,
ShaderID shader, Render *render,
const Shader *shader, Render *render,
RenderType render_type, Colour colour);
internal void fill_triangle(Render *render, ShaderID shader,
V3f vertices[TRIANGLE_VERTICES],
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
V3f normals[TRIANGLE_VERTICES],
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
Image *texture, RenderType type);
@ -38,6 +36,8 @@ 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, ShaderID shader,
void render_model(const Model *model, Render *render, const Shader *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, ShaderID shader,
}
internal void render_triangle(const Triangle *triangle, const Model *model,
ShaderID shader, Render *render,
const Shader *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] =
run_vertex_shader(shader, &vertices[i], (Buffer *)&render->img);
vertices[i] = shader->vertex(&vertices[i], shader->model_view,
shader->projection, &render->img);
}
if (render_type == RENDER_TYPE_WIREFRAME) {
@ -176,13 +176,12 @@ 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, shader, vertices, normals, coordinates, colour,
fill_triangle(render, vertices, normals, coordinates, colour,
model->texture, render_type);
}
}
internal void fill_triangle(Render *render, ShaderID shader,
V3f vertices[TRIANGLE_VERTICES],
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
V3f normals[TRIANGLE_VERTICES],
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
Image *texture, RenderType type) {
@ -208,8 +207,6 @@ internal void fill_triangle(Render *render, ShaderID shader,
V3f normal;
f32 tx_u, tx_v;
u64 tx_x, tx_y;
V2f tex_coords;
FragmentResult result;
f32 intensity = 1.0f;
@ -225,32 +222,40 @@ internal void fill_triangle(Render *render, ShaderID shader,
z += v0.z * coords.x + v1.z * coords.y + v2.z * coords.z;
zbuf = get_pixel(f32, &(render->depth), x, y);
if (z <= zbuf) {
continue;
if (z > zbuf) {
if (type == RENDER_TYPE_SHADED) {
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 +
normals[2].y * coords.z;
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;
colour = get_pixel(Colour, texture, tx_x, tx_y);
}
colour.r *= intensity;
colour.g *= intensity;
colour.b *= intensity;
set_pixel(depth, x, y, &z);
set_pixel(img, x, y, &colour);
}
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 +
normals[2].y * coords.z;
nz = normals[0].z * coords.x + normals[1].z * coords.y +
normals[2].z * coords.z;
normal = (V3f){nx, ny, nz};
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};
result =
run_fragment_shader(shader, normal, tex_coords, &colour, texture);
if (DISCARD_FRAGMENT(result)) {
continue;
}
set_pixel(depth, x, y, &z);
set_pixel(img, x, y, &result.colour);
}
}
}

View File

@ -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, ShaderID shader,
void render_model(const Model *model, Render *render, const Shader *shader,
RenderType render_type, Colour colour);
#endif // OBJ_H

View File

@ -1,62 +0,0 @@
#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);
}

View File

@ -1,37 +1,19 @@
#ifndef SHADER_H
#define SHADER_H
#include "aliases.h"
#include "img.h"
#include "vec.h"
typedef struct shader_id ShaderID;
struct shader_id {
u64 id;
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 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