Compare commits
9 Commits
a005ded219
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 44a84bbc53 | |||
| b76e73d57b | |||
| cc9f3f06db | |||
| 06d685d6a6 | |||
| 33ce544a7e | |||
| 3ab2f14235 | |||
| 61681f5e62 | |||
| 16c6048296 | |||
| 78b2b8bfd1 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
main
|
main
|
||||||
|
result.m4v
|
||||||
.cache
|
.cache
|
||||||
|
compile_commands.json
|
||||||
|
|||||||
27
aliases.h
Normal file
27
aliases.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef ALIASES_H
|
||||||
|
#define ALIASES_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define u8 uint8_t
|
||||||
|
#define u16 uint16_t
|
||||||
|
#define u32 uint32_t
|
||||||
|
#define u64 uint64_t
|
||||||
|
|
||||||
|
#define i8 int8_t
|
||||||
|
#define i16 int16_t
|
||||||
|
#define i32 int32_t
|
||||||
|
#define i64 int64_t
|
||||||
|
|
||||||
|
#define f32 float
|
||||||
|
#define f64 double
|
||||||
|
#define f128 long double
|
||||||
|
|
||||||
|
#define INTERNAL static
|
||||||
|
#define PERSISTENT static
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define CLASS_MEMBER static
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !ALIASES_H
|
||||||
4
compile
4
compile
@@ -1,8 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
CC=clang
|
CC=clang
|
||||||
CFLAGS="-g -Wall -Werror -pedantic"
|
CFLAGS="-g"
|
||||||
LIBS="-lSDL2"
|
LIBS="-lm -lSDL2"
|
||||||
SRC="main.c"
|
SRC="main.c"
|
||||||
OUT="main"
|
OUT="main"
|
||||||
|
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"arguments": [
|
|
||||||
"/usr/bin/clang",
|
|
||||||
"-c",
|
|
||||||
"-g",
|
|
||||||
"-Wall",
|
|
||||||
"-Werror",
|
|
||||||
"-pedantic",
|
|
||||||
"-o",
|
|
||||||
"main",
|
|
||||||
"main.c"
|
|
||||||
],
|
|
||||||
"directory": "/home/abdelrahman/Sources/programming/starfield",
|
|
||||||
"file": "/home/abdelrahman/Sources/programming/starfield/main.c",
|
|
||||||
"output": "/home/abdelrahman/Sources/programming/starfield/main"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"arguments": [
|
|
||||||
"/usr/bin/clang-15",
|
|
||||||
"-cc1",
|
|
||||||
"-triple",
|
|
||||||
"x86_64-pc-linux-gnu",
|
|
||||||
"-emit-obj",
|
|
||||||
"-mrelax-all",
|
|
||||||
"--mrelax-relocations",
|
|
||||||
"-disable-free",
|
|
||||||
"-clear-ast-before-backend",
|
|
||||||
"-disable-llvm-verifier",
|
|
||||||
"-discard-value-names",
|
|
||||||
"-main-file-name",
|
|
||||||
"-mrelocation-model",
|
|
||||||
"pic",
|
|
||||||
"-pic-level",
|
|
||||||
"2",
|
|
||||||
"-pic-is-pie",
|
|
||||||
"-mframe-pointer=all",
|
|
||||||
"-fmath-errno",
|
|
||||||
"-ffp-contract=on",
|
|
||||||
"-fno-rounding-math",
|
|
||||||
"-mconstructor-aliases",
|
|
||||||
"-funwind-tables=2",
|
|
||||||
"-target-cpu",
|
|
||||||
"x86-64",
|
|
||||||
"-tune-cpu",
|
|
||||||
"generic",
|
|
||||||
"-mllvm",
|
|
||||||
"-treat-scalable-fixed-error-as-warning",
|
|
||||||
"-debug-info-kind=constructor",
|
|
||||||
"-dwarf-version=5",
|
|
||||||
"-debugger-tuning=gdb",
|
|
||||||
"-fcoverage-compilation-dir=/home/abdelrahman/Sources/programming/starfield",
|
|
||||||
"-resource-dir",
|
|
||||||
"/usr/lib/clang/15.0.7",
|
|
||||||
"-internal-isystem",
|
|
||||||
"/usr/lib/clang/15.0.7/include",
|
|
||||||
"-internal-isystem",
|
|
||||||
"/usr/local/include",
|
|
||||||
"-internal-isystem",
|
|
||||||
"/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../x86_64-pc-linux-gnu/include",
|
|
||||||
"-internal-externc-isystem",
|
|
||||||
"/include",
|
|
||||||
"-internal-externc-isystem",
|
|
||||||
"/usr/include",
|
|
||||||
"-Wall",
|
|
||||||
"-Werror",
|
|
||||||
"-pedantic",
|
|
||||||
"-fdebug-compilation-dir=/home/abdelrahman/Sources/programming/starfield",
|
|
||||||
"-ferror-limit",
|
|
||||||
"19",
|
|
||||||
"-stack-protector",
|
|
||||||
"2",
|
|
||||||
"-fgnuc-version=4.2.1",
|
|
||||||
"-fcolor-diagnostics",
|
|
||||||
"-faddrsig",
|
|
||||||
"-D__GCC_HAVE_DWARF2_CFI_ASM=1",
|
|
||||||
"-x",
|
|
||||||
"c",
|
|
||||||
"-o",
|
|
||||||
"/tmp/main-7469c3.o",
|
|
||||||
"main.c"
|
|
||||||
],
|
|
||||||
"directory": "/home/abdelrahman/Sources/programming/starfield",
|
|
||||||
"file": "/home/abdelrahman/Sources/programming/starfield/main.c",
|
|
||||||
"output": "/tmp/main-7469c3.o"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
222
main.c
222
main.c
@@ -1,25 +1,77 @@
|
|||||||
|
#include "aliases.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_keycode.h>
|
||||||
#include <SDL2/SDL_pixels.h>
|
#include <SDL2/SDL_pixels.h>
|
||||||
#include <SDL2/SDL_rect.h>
|
#include <SDL2/SDL_rect.h>
|
||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
#include <SDL2/SDL_surface.h>
|
#include <SDL2/SDL_surface.h>
|
||||||
|
#include <SDL2/SDL_timer.h>
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define WINDOW_WIDTH 800
|
#define WINDOW_WIDTH 800
|
||||||
#define WINDOW_HEIGHT 600
|
#define WINDOW_HEIGHT 600
|
||||||
|
|
||||||
#define BG_COLOR 0x060616ff
|
#define NORMALISED_MIN -1
|
||||||
|
#define NORMALISED_MAX 1
|
||||||
|
|
||||||
void render_clear(SDL_Surface *surface, uint32_t color);
|
#define STAR_COUNT 2500
|
||||||
void fill_rect(SDL_Surface *surface, uint32_t x, uint32_t y, uint32_t w,
|
#define STAR_SPREAD 500
|
||||||
uint32_t h, uint32_t color);
|
#define STAR_SPEED 50
|
||||||
|
|
||||||
|
#define BG_COLOR 0x060616ff
|
||||||
|
#define STAR_COLOR 0xd4d4ddff
|
||||||
|
|
||||||
|
#define PROJECTION_PLANE 1.0
|
||||||
|
|
||||||
|
#define RAD(DEG) ((DEG * M_PI) / 180.0)
|
||||||
|
#define DEG(RAD) ((RAD * 180.0) / M_PI)
|
||||||
|
|
||||||
|
#define FOV_MIN 1.0
|
||||||
|
#define FOV_MAX 170.0
|
||||||
|
#define FOV_INC 3.0
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 x;
|
||||||
|
u32 y;
|
||||||
|
} vec2i_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
f64 x;
|
||||||
|
f64 y;
|
||||||
|
} vec2f_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
f64 x;
|
||||||
|
f64 y;
|
||||||
|
f64 z;
|
||||||
|
} vec3f_t;
|
||||||
|
|
||||||
|
f64 absf(f64 val);
|
||||||
|
void render_clear(SDL_Surface *surface, u32 color);
|
||||||
|
void set_pixel(SDL_Surface *surface, vec2i_t pos, u32 color);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void fill_rect(SDL_Surface *surface, vec2i_t pos, u32 w, u32 h, u32 color);
|
||||||
|
f64 normalise(f64 abs_val, f64 abs_min, f64 abs_max, f64 norm_min,
|
||||||
|
f64 norm_max);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
f64 denormalise(f64 norm_val, f64 norm_min, f64 norm_max, f64 abs_min,
|
||||||
|
f64 abs_max);
|
||||||
|
void init_starfield(vec3f_t *stars, u32 count, i32 spread);
|
||||||
|
void update_startfield(vec3f_t *stars, u32 count, i32 spread, u32 speed,
|
||||||
|
f64 delta);
|
||||||
|
void render_starfield(SDL_Surface *surface, vec3f_t *stars, u32 count,
|
||||||
|
i32 spread, f64 fov);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
|
||||||
SDL_Window *window = SDL_CreateWindow("Starfield", SDL_WINDOWPOS_CENTERED,
|
SDL_Window *window = SDL_CreateWindow("Starfield", SDL_WINDOWPOS_CENTERED,
|
||||||
@@ -35,22 +87,55 @@ int main(void) {
|
|||||||
|
|
||||||
SDL_Event event = {0};
|
SDL_Event event = {0};
|
||||||
|
|
||||||
|
vec3f_t stars[STAR_COUNT];
|
||||||
|
|
||||||
|
init_starfield(stars, STAR_COUNT, STAR_SPREAD);
|
||||||
|
|
||||||
|
f64 delta = 1.0 / 60.0; // constant delta
|
||||||
|
f64 fov = 60.0;
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
running = false;
|
running = false;
|
||||||
break;
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
switch (event.key.keysym.sym) {
|
||||||
|
case SDLK_UP:
|
||||||
|
fov -= FOV_INC;
|
||||||
|
|
||||||
|
if (fov < FOV_MIN) {
|
||||||
|
fov = FOV_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
fov += FOV_INC;
|
||||||
|
|
||||||
|
if (fov > FOV_MAX) {
|
||||||
|
fov = FOV_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_startfield(stars, STAR_COUNT, STAR_SPREAD, STAR_SPEED, delta);
|
||||||
|
|
||||||
render_clear(canvas, BG_COLOR);
|
render_clear(canvas, BG_COLOR);
|
||||||
|
|
||||||
|
render_starfield(canvas, stars, STAR_COUNT, STAR_SPREAD, fov);
|
||||||
|
|
||||||
SDL_BlitSurface(canvas, NULL, surface, NULL);
|
SDL_BlitSurface(canvas, NULL, surface, NULL);
|
||||||
|
|
||||||
SDL_UpdateWindowSurface(window);
|
SDL_UpdateWindowSurface(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_FreeSurface(canvas);
|
||||||
|
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
@@ -58,29 +143,51 @@ int main(void) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_clear(SDL_Surface *surface, uint32_t color) {
|
f64 absf(f64 val) {
|
||||||
uint32_t length = surface->w * surface->h;
|
if (val < 0) {
|
||||||
|
val *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_clear(SDL_Surface *surface, u32 color) {
|
||||||
|
u32 length = surface->w * surface->h;
|
||||||
|
|
||||||
SDL_LockSurface(surface);
|
SDL_LockSurface(surface);
|
||||||
|
|
||||||
uint32_t *pixels = (uint32_t *)(surface->pixels);
|
u32 *pixels = (u32 *)(surface->pixels);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < length; ++i) {
|
for (u32 i = 0; i < length; ++i) {
|
||||||
pixels[i] = color;
|
pixels[i] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_rect(SDL_Surface *surface, uint32_t x, uint32_t y, uint32_t w,
|
void set_pixel(SDL_Surface *surface, vec2i_t pos, u32 color) {
|
||||||
uint32_t h, uint32_t color) {
|
|
||||||
SDL_LockSurface(surface);
|
SDL_LockSurface(surface);
|
||||||
|
|
||||||
uint32_t *pixels = (uint32_t *)(surface->pixels);
|
u32 *pixels = (u32 *)(surface->pixels);
|
||||||
|
|
||||||
for (uint32_t row = 0; row < h; ++row) {
|
u32 index = pos.y * surface->w + pos.x;
|
||||||
for (uint32_t col = 0; col < w; ++col) {
|
|
||||||
uint32_t i = (y + row) * surface->w + (x + col);
|
if (index < surface->w * surface->h) {
|
||||||
|
pixels[index] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_UnlockSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void fill_rect(SDL_Surface *surface, vec2i_t pos, u32 w, u32 h, u32 color) {
|
||||||
|
SDL_LockSurface(surface);
|
||||||
|
|
||||||
|
u32 *pixels = (u32 *)(surface->pixels);
|
||||||
|
|
||||||
|
for (u32 row = 0; row < h; ++row) {
|
||||||
|
for (u32 col = 0; col < w; ++col) {
|
||||||
|
u32 i = (pos.y + row) * surface->w + (pos.x + col);
|
||||||
|
|
||||||
pixels[i] = color;
|
pixels[i] = color;
|
||||||
}
|
}
|
||||||
@@ -88,3 +195,86 @@ void fill_rect(SDL_Surface *surface, uint32_t x, uint32_t y, uint32_t w,
|
|||||||
|
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f64 normalise(f64 abs_val, f64 abs_min, f64 abs_max, f64 norm_min,
|
||||||
|
f64 norm_max) {
|
||||||
|
if (abs_min - abs_max == 0.0) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 ratio = (abs_val - abs_max) / (abs_min - abs_max);
|
||||||
|
|
||||||
|
return ratio * (norm_min - norm_max) + norm_max;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
f64 denormalise(f64 norm_val, f64 norm_min, f64 norm_max, f64 abs_min,
|
||||||
|
f64 abs_max) {
|
||||||
|
if (norm_min - norm_max == 0.0) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 ratio = (norm_val - norm_max) / (norm_min - norm_max);
|
||||||
|
|
||||||
|
return ratio * (abs_min - abs_max) + abs_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3f_t init_star_position(i32 spread) {
|
||||||
|
i32 spread_half = spread / 2;
|
||||||
|
|
||||||
|
return (vec3f_t){.x = ((rand() % spread) - spread_half) * 2.0,
|
||||||
|
.y = ((rand() % spread) - spread_half) * 2.0,
|
||||||
|
.z = (rand() % spread) + PROJECTION_PLANE};
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_starfield(vec3f_t *stars, u32 count, i32 spread) {
|
||||||
|
for (u32 i = 0; i < count; ++i) {
|
||||||
|
stars[i] = init_star_position(spread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_startfield(vec3f_t *stars, u32 count, i32 spread, u32 speed,
|
||||||
|
f64 delta) {
|
||||||
|
for (u32 i = 0; i < count; ++i) {
|
||||||
|
stars[i].z -= speed * delta;
|
||||||
|
|
||||||
|
if (stars[i].z < PROJECTION_PLANE) {
|
||||||
|
stars[i] = init_star_position(spread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_starfield(SDL_Surface *surface, vec3f_t *stars, u32 count,
|
||||||
|
i32 spread, f64 fov) {
|
||||||
|
vec2f_t projected[count];
|
||||||
|
vec2i_t coords;
|
||||||
|
|
||||||
|
f64 tangent = tan(RAD(fov * 0.5));
|
||||||
|
|
||||||
|
for (u32 i = 0; i < count; ++i) {
|
||||||
|
if (stars[i].z == 0.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
projected[i] = (vec2f_t){.x = stars[i].x / stars[i].z / tangent,
|
||||||
|
.y = stars[i].y / stars[i].z / tangent};
|
||||||
|
|
||||||
|
if (projected[i].x < NORMALISED_MIN || projected[i].x > NORMALISED_MAX ||
|
||||||
|
projected[i].y < NORMALISED_MIN || projected[i].y > NORMALISED_MAX ||
|
||||||
|
(projected[i].x == 0.0 && projected[i].y == 0.0)) {
|
||||||
|
stars[i] = init_star_position(spread);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
projected[i].x = denormalise(projected[i].x, NORMALISED_MIN, NORMALISED_MAX,
|
||||||
|
0, WINDOW_WIDTH);
|
||||||
|
projected[i].y = denormalise(projected[i].y, NORMALISED_MIN, NORMALISED_MAX,
|
||||||
|
0, WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
coords =
|
||||||
|
(vec2i_t){.x = (u32)ceil(projected[i].x), .y = (u32)projected[i].y};
|
||||||
|
|
||||||
|
set_pixel(surface, coords, STAR_COLOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user