Compare commits
6 Commits
9fa4d4b4ec
...
e6a3b73f99
Author | SHA1 | Date | |
---|---|---|---|
e6a3b73f99 | |||
c836f3758f | |||
df5557d1fc | |||
dd290f4094 | |||
d8a44f57ed | |||
edf3851f20 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
|
.cache
|
||||||
|
build_dir
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[submodule "include/c_cpp_aliases"]
|
||||||
|
path = include/c_cpp_aliases
|
||||||
|
url = https://git.thewizardapprentice.com/abdelrahman/c-cpp-aliases.git
|
||||||
|
branch = main
|
16
compile
Normal file
16
compile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CC=clang
|
||||||
|
CFLAGS="-g -Wall -Werror -pedantic -Iinclude $(pkg-config --cflags sdl2)"
|
||||||
|
LIBS="$(pkg-config --libs sdl2)"
|
||||||
|
|
||||||
|
RAYTRACER_SRC="src/window/*.c \
|
||||||
|
src/raytracer/*.c \
|
||||||
|
"
|
||||||
|
|
||||||
|
BUILD=build_dir
|
||||||
|
RAYTRACER_OUT="$BUILD/raytracer"
|
||||||
|
|
||||||
|
mkdir -p $BUILD
|
||||||
|
|
||||||
|
(set -x ; $CC $CFLAGS $LIBS $RAYTRACER_SRC -o $RAYTRACER_OUT)
|
1
include/c_cpp_aliases
Submodule
1
include/c_cpp_aliases
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f95f3aa499910286876c1f2cdceea8146ebcf7b1
|
31
include/window/window.h
Normal file
31
include/window/window.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef WINDOW_H
|
||||||
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include "c_cpp_aliases/aliases.h"
|
||||||
|
#include <SDL2/SDL_video.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 r;
|
||||||
|
u8 g;
|
||||||
|
u8 b;
|
||||||
|
u8 a;
|
||||||
|
} colour_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 width;
|
||||||
|
u64 height;
|
||||||
|
const char *title;
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Surface *front_buffer;
|
||||||
|
SDL_Surface *back_buffer;
|
||||||
|
} window_t;
|
||||||
|
|
||||||
|
bool init_window(window_t *wnd, u64 width, u64 height, const char *title);
|
||||||
|
void close_window(window_t *wnd);
|
||||||
|
|
||||||
|
void clear_window(window_t *wnd, colour_t colour);
|
||||||
|
void set_pixel(window_t *wnd, f32 x, f32 y, colour_t colour);
|
||||||
|
void swap_buffers(window_t *wnd);
|
||||||
|
|
||||||
|
#endif // !WINDOW_H
|
23
run
Normal file
23
run
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
USAGE="Usage: run (raytracer | rasteriser)"
|
||||||
|
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
echo $USAGE
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
raytracer)
|
||||||
|
RENDERER="raytracer"
|
||||||
|
shift # past argument
|
||||||
|
;;
|
||||||
|
-*|--*|*)
|
||||||
|
echo $USAGE
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
./build_dir/$RENDERER
|
37
src/raytracer/main.c
Normal file
37
src/raytracer/main.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "SDL_events.h"
|
||||||
|
#include "c_cpp_aliases/aliases.h"
|
||||||
|
#include "window/window.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
colour_t bg = (colour_t){.r = 128, .g = 128, .b = 128, .a = 255};
|
||||||
|
|
||||||
|
window_t window = {0};
|
||||||
|
|
||||||
|
if (!init_window(&window, 1000, 800, "CG From Scratch")) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool running = true;
|
||||||
|
SDL_Event event = {0};
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_window(&window, bg);
|
||||||
|
|
||||||
|
swap_buffers(&window);
|
||||||
|
}
|
||||||
|
|
||||||
|
close_window(&window);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
144
src/window/window.c
Normal file
144
src/window/window.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "window/window.h"
|
||||||
|
#include "c_cpp_aliases/aliases.h"
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_error.h>
|
||||||
|
#include <SDL2/SDL_pixels.h>
|
||||||
|
#include <SDL2/SDL_surface.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define NORMALISED_MIN -1.0f
|
||||||
|
#define NORMALISED_MAX 1.0f
|
||||||
|
|
||||||
|
u32 colour_to_u32(colour_t colour);
|
||||||
|
u32 index_from_coordinates(window_t *wnd, u32 x, u32 y);
|
||||||
|
i32 denormalise(f32 value, u32 max);
|
||||||
|
void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour);
|
||||||
|
|
||||||
|
bool init_window(window_t *wnd, u64 width, u64 height, const char *title) {
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||||
|
printf("Failed to initialise SDL: %s\n", SDL_GetError());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wnd->window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED, width, height, 0);
|
||||||
|
if (!(wnd->window)) {
|
||||||
|
printf("Failed to create window: %s\n", SDL_GetError());
|
||||||
|
|
||||||
|
close_window(wnd);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wnd->front_buffer = SDL_GetWindowSurface(wnd->window);
|
||||||
|
if (!(wnd->front_buffer)) {
|
||||||
|
printf("Failed to get front buffer: %s\n", SDL_GetError());
|
||||||
|
|
||||||
|
close_window(wnd);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wnd->back_buffer = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32,
|
||||||
|
SDL_PIXELFORMAT_ABGR32);
|
||||||
|
if (!(wnd->back_buffer)) {
|
||||||
|
printf("Failed to create back buffer: %s\n", SDL_GetError());
|
||||||
|
|
||||||
|
close_window(wnd);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wnd->width = width;
|
||||||
|
wnd->height = height;
|
||||||
|
wnd->title = title;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_window(window_t *wnd) {
|
||||||
|
if (wnd) {
|
||||||
|
wnd->width = 0;
|
||||||
|
wnd->height = 0;
|
||||||
|
wnd->title = "";
|
||||||
|
|
||||||
|
if (wnd->window) {
|
||||||
|
SDL_DestroyWindow(wnd->window);
|
||||||
|
|
||||||
|
wnd->window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wnd->back_buffer) {
|
||||||
|
SDL_FreeSurface(wnd->back_buffer);
|
||||||
|
|
||||||
|
wnd->back_buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_window(window_t *wnd, colour_t colour) {
|
||||||
|
SDL_LockSurface(wnd->back_buffer);
|
||||||
|
|
||||||
|
u32 c = colour_to_u32(colour);
|
||||||
|
|
||||||
|
u32 *pixels = (u32 *)(wnd->back_buffer->pixels);
|
||||||
|
u32 count = wnd->back_buffer->w * wnd->back_buffer->h;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < count; ++i) {
|
||||||
|
pixels[i] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_UnlockSurface(wnd->back_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pixel(window_t *wnd, f32 x, f32 y, colour_t colour) {
|
||||||
|
i32 screen_x = denormalise(x, wnd->width);
|
||||||
|
i32 screen_y = denormalise(-y, wnd->height);
|
||||||
|
|
||||||
|
if (screen_x < 0 || screen_y < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockSurface(wnd->back_buffer);
|
||||||
|
|
||||||
|
set_screen_pixel(wnd, screen_x, screen_y, colour);
|
||||||
|
|
||||||
|
SDL_UnlockSurface(wnd->back_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap_buffers(window_t *wnd) {
|
||||||
|
SDL_BlitSurface(wnd->back_buffer, NULL, wnd->front_buffer, NULL);
|
||||||
|
|
||||||
|
SDL_UpdateWindowSurface(wnd->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 colour_to_u32(colour_t colour) {
|
||||||
|
return ((u32)(colour.r) << 24) | ((u32)(colour.g) << 16) |
|
||||||
|
((u32)(colour.b) << 8) | (u32)(colour.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 index_from_coordinates(window_t *wnd, u32 x, u32 y) {
|
||||||
|
return y * wnd->width + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 denormalise(f32 value, u32 max) {
|
||||||
|
if (max == 0 || value < NORMALISED_MIN || value >= NORMALISED_MAX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (i32)(((value - NORMALISED_MIN) * max) /
|
||||||
|
(NORMALISED_MAX - NORMALISED_MIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour) {
|
||||||
|
u32 index = index_from_coordinates(wnd, x, y);
|
||||||
|
u32 c = colour_to_u32(colour);
|
||||||
|
|
||||||
|
u32 *pixels = (u32 *)(wnd->back_buffer->pixels);
|
||||||
|
|
||||||
|
pixels[index] = c;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user