Implement shaders (#1)

Reviewed-on: #1

	* Start implementing shaders and move vector code to dedicated files
	* Extract shader into its own header
	* Ensure pixel coordinates are within bounds
	* Refactor shader code and implement fragment shaders
	* Create shaders
	* Reorganise code
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
This commit is contained in:
2024-08-18 14:28:09 +00:00
committed by Abdelrahman Said
parent 3bbab3f624
commit 50b8c6dd0a
19 changed files with 804 additions and 567 deletions

93
src/img/img.c Normal file
View File

@@ -0,0 +1,93 @@
#include "img.h"
#include "aliases.h"
#include "mem_arena.h"
#include "pam.h"
#include "utils.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
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) {
return false;
}
u64 size = buffer->width * buffer->height * base_size;
buffer->buf = wapp_mem_arena_alloc(arena, size);
return buffer->buf != NULL;
}
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;
}
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;
}
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
return;
}
void _clear_buffer(Buffer *buffer, void *value, u64 base_size) {
for (u64 y = 0; y < buffer->height; ++y) {
for (u64 x = 0; x < buffer->width; ++x) {
_set_pixel(buffer, x, y, value, base_size);
}
}
}
void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour) {
u64 dx = absolute((i64)x1 - (i64)x0);
u64 dy = absolute((i64)y1 - (i64)y0);
f32 t = 0.0f;
i64 x = 0;
i64 y = 0;
if (dx > dy) {
if (x0 > x1) {
swap(u64, x0, x1);
swap(u64, y0, y1);
}
for (u64 x = x0; x < x1; ++x) {
t = (f32)(x - x0) / (f32)(x1 - x0);
y = (i64)y0 + ((i64)y1 - (i64)y0) * t;
set_pixel(img, x, y, &colour);
}
} else {
if (y0 > y1) {
swap(u64, x0, x1);
swap(u64, y0, y1);
}
for (u64 y = y0; y < y1; ++y) {
t = (f32)(y - y0) / (f32)(y1 - y0);
x = (i64)x0 + ((i64)x1 - (i64)x0) * t;
set_pixel(img, x, y, &colour);
}
}
}
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,
u64 base_size) {
if (x < 0 || y < 0 || x >= buffer->width || y >= buffer->height) {
return -1;
}
return (y * buffer->width + x) * base_size;
}

43
src/img/img.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef IMG_H
#define IMG_H
#include "aliases.h"
#include "mem_arena.h"
#include <stdbool.h>
#define BUF_TYPE(TYPE, NAME) \
typedef struct NAME { \
u64 width; \
u64 height; \
TYPE *buf; \
} NAME
typedef struct colour Colour;
struct colour {
u8 r;
u8 g;
u8 b;
u8 a;
};
BUF_TYPE(void, Buffer);
BUF_TYPE(Colour, Image);
BUF_TYPE(f32, Depth);
#define init_buffer(ARENA, BUF) \
_init_buffer(ARENA, (Buffer *)BUF, sizeof(*((BUF)->buf)))
#define get_pixel(TYPE, BUF, X, Y) \
(*((TYPE *)(_get_pixel((Buffer *)BUF, X, Y, sizeof(*((BUF)->buf))))))
#define set_pixel(BUF, X, Y, VAL_PTR) \
_set_pixel((Buffer *)BUF, X, Y, VAL_PTR, sizeof(*((BUF)->buf)))
#define clear_buffer(BUF, VAL_PTR) \
_clear_buffer((Buffer *)BUF, VAL_PTR, sizeof(*((BUF)->buf)))
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size);
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size);
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size);
void _clear_buffer(Buffer *buffer, void *value, u64 base_size);
void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour);
void save_image(const Image *img, const char *filename);
#endif // IMG_H