Compare commits
No commits in common. "891a97739f63872d66a0678ac43d72bfa80bad22" and "6d6d4781ff9d9049c346319bcb22fac9475c3a40" have entirely different histories.
891a97739f
...
6d6d4781ff
20
src/img.c
20
src/img.c
@ -7,7 +7,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.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) {
|
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
|
||||||
if (!arena || !buffer || buffer->width == 0 || buffer->height == 0) {
|
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) {
|
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
|
||||||
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||||
if (idx == -1) {
|
|
||||||
idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((u8 *)(buffer->buf)) + idx;
|
return ((u8 *)(buffer->buf)) + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
|
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
|
||||||
i64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
|
||||||
if (idx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
|
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
|
||||||
return;
|
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);
|
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) {
|
u64 base_size) {
|
||||||
if (x < 0 || y < 0 || x >= buffer->width || y >= buffer->height) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (y * buffer->width + x) * base_size;
|
return (y * buffer->width + x) * base_size;
|
||||||
}
|
}
|
||||||
|
81
src/obj.c
81
src/obj.c
@ -3,7 +3,6 @@
|
|||||||
#include "img.h"
|
#include "img.h"
|
||||||
#include "mem_arena.h"
|
#include "mem_arena.h"
|
||||||
#include "pam.h"
|
#include "pam.h"
|
||||||
#include "shader.h"
|
|
||||||
#include "typed_list.h"
|
#include "typed_list.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
@ -24,10 +23,9 @@ struct triangle_bbox {
|
|||||||
};
|
};
|
||||||
|
|
||||||
internal void render_triangle(const Triangle *triangle, const Model *model,
|
internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||||
ShaderID shader, Render *render,
|
const Shader *shader, Render *render,
|
||||||
RenderType render_type, Colour colour);
|
RenderType render_type, Colour colour);
|
||||||
internal void fill_triangle(Render *render, ShaderID shader,
|
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||||
V3f vertices[TRIANGLE_VERTICES],
|
|
||||||
V3f normals[TRIANGLE_VERTICES],
|
V3f normals[TRIANGLE_VERTICES],
|
||||||
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
||||||
Image *texture, RenderType type);
|
Image *texture, RenderType type);
|
||||||
@ -38,6 +36,8 @@ internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
|||||||
const V2i *ap);
|
const V2i *ap);
|
||||||
internal V3f get_viewport_vertex(const V3f *vertex, const Image *img);
|
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) {
|
Model load_obj_file(Arena *arena, const char *filename, const char *texture) {
|
||||||
if (!arena) {
|
if (!arena) {
|
||||||
return INVALID_MODEL;
|
return INVALID_MODEL;
|
||||||
@ -131,7 +131,7 @@ bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
|
|||||||
return true;
|
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) {
|
RenderType render_type, Colour colour) {
|
||||||
Triangle triangle;
|
Triangle triangle;
|
||||||
for (u64 i = 0; i < model->triangles->count; ++i) {
|
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,
|
internal void render_triangle(const Triangle *triangle, const Model *model,
|
||||||
ShaderID shader, Render *render,
|
const Shader *shader, Render *render,
|
||||||
RenderType render_type, Colour colour) {
|
RenderType render_type, Colour colour) {
|
||||||
Image *img = &(render->img);
|
Image *img = &(render->img);
|
||||||
V3f vertices[TRIANGLE_VERTICES] = {
|
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) {
|
for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
|
||||||
vertices[i] =
|
vertices[i] = shader->vertex(&vertices[i], shader->model_view,
|
||||||
run_vertex_shader(shader, &vertices[i], (Buffer *)&render->img);
|
shader->projection, &render->img);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render_type == RENDER_TYPE_WIREFRAME) {
|
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 ||
|
} else if (render_type == RENDER_TYPE_FILLED ||
|
||||||
render_type == RENDER_TYPE_SHADED) {
|
render_type == RENDER_TYPE_SHADED) {
|
||||||
fill_triangle(render, shader, vertices, normals, coordinates, colour,
|
fill_triangle(render, vertices, normals, coordinates, colour,
|
||||||
model->texture, render_type);
|
model->texture, render_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void fill_triangle(Render *render, ShaderID shader,
|
internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
||||||
V3f vertices[TRIANGLE_VERTICES],
|
|
||||||
V3f normals[TRIANGLE_VERTICES],
|
V3f normals[TRIANGLE_VERTICES],
|
||||||
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
||||||
Image *texture, RenderType type) {
|
Image *texture, RenderType type) {
|
||||||
@ -208,8 +207,6 @@ internal void fill_triangle(Render *render, ShaderID shader,
|
|||||||
V3f normal;
|
V3f normal;
|
||||||
f32 tx_u, tx_v;
|
f32 tx_u, tx_v;
|
||||||
u64 tx_x, tx_y;
|
u64 tx_x, tx_y;
|
||||||
V2f tex_coords;
|
|
||||||
FragmentResult result;
|
|
||||||
|
|
||||||
f32 intensity = 1.0f;
|
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;
|
z += v0.z * coords.x + v1.z * coords.y + v2.z * coords.z;
|
||||||
zbuf = get_pixel(f32, &(render->depth), x, y);
|
zbuf = get_pixel(f32, &(render->depth), x, y);
|
||||||
|
|
||||||
if (z <= zbuf) {
|
if (z > zbuf) {
|
||||||
continue;
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ struct render {
|
|||||||
|
|
||||||
Model load_obj_file(Arena *arena, const char *filename, const char *texture);
|
Model load_obj_file(Arena *arena, const char *filename, const char *texture);
|
||||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height);
|
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);
|
RenderType render_type, Colour colour);
|
||||||
|
|
||||||
#endif // OBJ_H
|
#endif // OBJ_H
|
||||||
|
62
src/shader.c
62
src/shader.c
@ -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);
|
|
||||||
}
|
|
38
src/shader.h
38
src/shader.h
@ -1,37 +1,19 @@
|
|||||||
#ifndef SHADER_H
|
#ifndef SHADER_H
|
||||||
#define SHADER_H
|
#define SHADER_H
|
||||||
|
|
||||||
#include "aliases.h"
|
|
||||||
#include "img.h"
|
#include "img.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
|
||||||
typedef struct shader_id ShaderID;
|
typedef V3f(VertexShader)(const V3f *vertex, M4x4f *model_view,
|
||||||
struct shader_id {
|
M4x4f *projection, const Image *img);
|
||||||
u64 id;
|
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
|
#endif // SHADER_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user