Browse Source

merged

place-stuff
Joel 4 years ago
parent
commit
471f5408cc
  1. 3
      Makefile
  2. 11
      camera.c
  3. 4
      camera.h
  4. 128
      distfuncs.c
  5. 8
      distfuncs.h
  6. BIN
      img/b1.jpg
  7. BIN
      img/b2.png
  8. BIN
      img/b3.png
  9. BIN
      img/b4.jpg
  10. 125
      main.c
  11. 2
      main.h
  12. 126
      presentation.md
  13. 14
      scene.c
  14. 6
      types.h

3
Makefile

@ -19,5 +19,8 @@ camera.o: camera.c @@ -19,5 +19,8 @@ camera.o: camera.c
scene.o: scene.c
gcc $(LINKS) -c scene.c -o scene.o
pres: presentation.md
pandoc -t beamer presentation.md -o pres.pdf
clean:
rm *.o blackpink

11
camera.c

@ -3,12 +3,12 @@ @@ -3,12 +3,12 @@
#include "math.h"
#include "vect.h"
#include "distfuncs.h"
#include "scene.h"
#include "camera.h"
#define DRAW_DIST 255.0
#define MAX_ITERATIONS 255
#define EPSILON 0.1
#define NORMAL_EPSILON 0.0001
double dabs(double yeet) {
if (yeet > 0) {
@ -29,7 +29,8 @@ double dsign(double yeet) { @@ -29,7 +29,8 @@ double dsign(double yeet) {
double manidist(struct vec *v)
{
// return v->elements[3];
double yeet = (SDL_GetTicks() / 10);
//double yeet = (SDL_GetTicks() / 10);
double yeet = 300;
v->elements[3] -= yeet;
double out = magnitude_vec(v) - yeet;
v->elements[3] += yeet;
@ -54,9 +55,9 @@ estimateNormal(struct vec *r, struct solid *sol) @@ -54,9 +55,9 @@ estimateNormal(struct vec *r, struct solid *sol)
struct vec *out = new_vec(r->dimension);
struct vec *tmp = new_vec(r->dimension);
for (int i = 0; i < out->dimension; i++) {
tmp->elements[i] = EPSILON;
tmp->elements[i] = NORMAL_EPSILON;
double s1 = solid_dist(sol, tmp);
tmp->elements[i] = -EPSILON;
tmp->elements[i] = -NORMAL_EPSILON;
double s2 = solid_dist(sol, tmp);
out->elements[i] = s1 - s2;
@ -110,7 +111,6 @@ manifoldturn(struct ray *r, struct vec *v, double distance) @@ -110,7 +111,6 @@ manifoldturn(struct ray *r, struct vec *v, double distance)
/* move the vector foward in euclid */
add_scaled_vec_ip(r->pos, r->dir, distance);
struct vec *yaxisnew = estimateNormal(r->pos, &manifold);
/* stick it to the manifold */
@ -142,7 +142,6 @@ manifoldstep(struct ray *r, double distance) @@ -142,7 +142,6 @@ manifoldstep(struct ray *r, double distance)
manifoldturn(r, r->dir, distance);
return;
struct vec *yaxisold = estimateNormal(r->pos, &manifold);
/* move the vector foward in euclid */

4
camera.h

@ -15,4 +15,8 @@ double solid_dist(struct solid *s, struct vec *v); @@ -15,4 +15,8 @@ double solid_dist(struct solid *s, struct vec *v);
void place(struct solid *v);
struct vec * estimateNormal(struct vec *r, struct solid *sol);
void manifoldstep(struct ray *r, double distance);
void manifoldturn(struct ray *r, struct vec *v, double distance);
#endif

128
distfuncs.c

@ -1,6 +1,11 @@ @@ -1,6 +1,11 @@
#include "main.h"
#include "types.h"
#include "vect.h"
#include "camera.h"
#define SOFT_LIGHT 1
#define HARD_LIGHT 2
#define WHITE_LIGHT 2
double sdf_sphere(struct vec *x) {
static const double r = 1.4;
@ -77,8 +82,8 @@ double is_pos(double a) { @@ -77,8 +82,8 @@ double is_pos(double a) {
}
double sdf_phat_vert_line(struct vec *x) {
static const double h = 10;
static const double r = 1;
static const double h = 2;
static const double r = 0.5;
struct vec *v = copy_vec(x);
@ -95,22 +100,84 @@ double sdf_box(struct vec *x) { @@ -95,22 +100,84 @@ double sdf_box(struct vec *x) {
struct vec *v = copy_vec(x);
do_on_vec_ip(v, fabs);
static struct vec * box_shape = NULL;
if (!box_shape) {
box_shape = new_vec_of(v->dimension, -0.5);
}
struct vec * box_shape = new_vec_of(v->dimension, 5);
subtract_vec_ip(box_shape, v);
do_on_vec_ip(v, is_pos);
double result = magnitude_vec(v);
free_vec(v);
free(box_shape);
return result;
}
struct colour yeet_col(struct ray *ray) {
struct colour yeet_pho(struct ray *ray, struct object *o) {
double specular = 0.8;
double diffuse = 0.2;
double ambient = 0.0;
double shin = 50;
int light_type = SOFT_LIGHT;
struct colour light_col = {.r = 200, .g = 0, .b = 100, .sp = CS_RGB};
struct vec *light = new_vec4(-1, 1, 1, 0);
//struct vec *colour = new_vec3(o->base_col.r, o->base_col.g, o->base_col.b);
/* ambient */
//scalar_multiply_vec_ip(colour, ambient);
double intensity = ambient;
struct vec *surf_norm = estimateNormal(ray->pos, &o->sol);
// struct vec *light_vec = normalise_vec_ip(subtract_vec(ray->pos, light));
struct vec *light_vec = normalise_vec_ip(subtract_vec_ip(scalar_multiply_vec(light, -1), ray->pos));
double diffuse_val = dot_product_vec(light_vec, surf_norm) * diffuse;
// r = 2 * (l . n) * n - L
struct vec *camera_vec = normalise_vec_ip(scalar_multiply_vec(ray->pos, -1));
struct vec *reflection = scalar_multiply_vec(surf_norm,
2 * dot_product_vec(light_vec, surf_norm));
subtract_vec_ip(reflection, light_vec);
double spec_val = pow(clamp(dot_product_vec(reflection, camera_vec),-1,1), shin) * specular;
struct colour c = get_hsl(o->base_col);
intensity = ambient + diffuse_val + spec_val;
light_col = get_hsl(light_col);
light_col.l = spec_val;
light_col = get_rgb(light_col);
c.l = intensity;
c = get_rgb(c);
if (1 && spec_val > 0.0) {
if (light_type == HARD_LIGHT) {
c.r = light_col.r > c.r ? c.r + (light_col.r - c.r) / 2 : c.r;
c.g = light_col.g > c.g ? c.g + (light_col.g - c.g) / 2 : c.g;
c.b = light_col.b > c.b ? c.b + (light_col.b - c.b) / 2 : c.b;
} else if (light_type == SOFT_LIGHT) {
c.r = light_col.r > c.r ? light_col.r: c.r;
c.b = light_col.b > c.b ? light_col.b: c.b;
c.g = light_col.g > c.g ? light_col.g: c.g;
}
}
free_vec(camera_vec);
free_vec(reflection);
free_vec(surf_norm);
free_vec(light_vec);
free_vec(light);
return c;
}
struct colour yeet_col_og(struct ray *ray, struct object *obj) {
struct vec *l = new_vec4(1,1,1,1);
struct vec *n = subtract_vec_ip(l, ray->pos);
struct vec *nl = normalise_vec(l);
@ -121,15 +188,58 @@ struct colour yeet_col(struct ray *ray) { @@ -121,15 +188,58 @@ struct colour yeet_col(struct ray *ray) {
return (c);
}
/*
struct object new_sphere(double radius) {
struct object s;
struct vec * v = new_vec4(0,0,5,0);
s.base_col = get_random_color();
s.sol.pos = *v;
s.sol.op = B_ADD;
s.col = yeet_col;
s.col = yeet_pho;
s.sol.dist = sdf_sphere;
return s;
*/
/**
* Creates a new struct object with the given parameters. The position passed
* in should be a vec4 as this is converted to a vec3 when the object is added
* to the scene.
*/
struct object
new_object(struct vec* position, double rotation, double scale,
double (*dist)(struct vec*), struct colour (*col)(struct ray *, struct object *))
{
struct object new_obj;
new_obj.base_col = get_random_color();
new_obj.col = col;
new_obj.sol.dist = dist;
new_obj.sol.pos = *position;
new_obj.sol.rotation = rotation;
new_obj.sol.scale = scale;
new_obj.sol.op = B_ADD;
return new_obj;
}
struct object new_sphere(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_sphere, yeet_pho);
}
struct object new_box(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_box, yeet_pho);
}
/* DON'T CALL THIS */
struct object new_cone(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, NULL, NULL);
}
struct object new_vert_line(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_phat_vert_line, yeet_pho);
}

8
distfuncs.h

@ -1,7 +1,13 @@ @@ -1,7 +1,13 @@
#ifndef DISTFU
#define DISTFU
struct object new_sphere(double radius);
struct object new_sphere(struct vec *, double, double);
/* Don't call this, it's just a placeholder rn */
struct object new_cone(struct vec *, double, double);
struct object new_box(struct vec *, double, double);
struct object new_vert_line(struct vec *, double, double);
struct object new_object(struct vec *, double, double, double (*) (struct vec *),
struct colour (*)(struct ray *, struct object *));
double sdf_box(struct vec *);
double sdf_hplane(struct vec *);

BIN
img/b1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
img/b2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
img/b3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

BIN
img/b4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

125
main.c

@ -20,13 +20,14 @@ SDL_Renderer * ren; @@ -20,13 +20,14 @@ SDL_Renderer * ren;
Uint32 pixels[B_INTERNAL_HEIGHT][B_INTERNAL_WIDTH];
struct object scene_object;
struct camera *camera;
struct SDL_Window* make_window(void) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("error initializing SDL: %s\n", SDL_GetError());
}
return SDL_CreateWindow("sdl_tester",
return SDL_CreateWindow("𝕧 𝕒 𝕡 𝕠 𝕣 𝕨 𝕒 𝕧 𝕖",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
B_WINDOW_WIDTH, B_WINDOW_HEIGHT,
@ -35,18 +36,81 @@ struct SDL_Window* make_window(void) { @@ -35,18 +36,81 @@ struct SDL_Window* make_window(void) {
void handle_inputs(void)
{
if (keyboardstate[SDL_SCANCODE_UP])
printf("up");
if (keyboardstate[SDL_SCANCODE_DOWN])
printf("down");
if (keyboardstate[SDL_SCANCODE_LEFT])
printf("left");
if (keyboardstate[SDL_SCANCODE_RIGHT])
printf("right");
/* this is so broken it leaks memory everywhere and crashes and idek why
* Pressing UP will crash immediately and anything else will crash
* eventually
*
* It also makes the object disappear off into the 4th dimension
*/
struct ray r;
r.dir = new_vec(4);
r.pos = new_vec(4);
const double dist = 0.1;
double done = 0;
if (keyboardstate[SDL_SCANCODE_UP]) {
struct ray cameraray = {.pos = copy_vec(camera->pos), .dir = camera->y};
manifoldturn(&cameraray, camera->x, dist);
free_vec(cameraray.pos);
cameraray.pos = copy_vec(camera->pos);
manifoldturn(&cameraray, camera->z, dist);
cameraray.pos = camera->pos;
manifoldstep(&cameraray, dist);
done = dist;
}
if (keyboardstate[SDL_SCANCODE_DOWN]) {
struct ray cameraray = {.pos = copy_vec(camera->pos), .dir = camera->y};
manifoldturn(&cameraray, camera->x, dist);
free_vec(cameraray.pos);
cameraray.pos = copy_vec(camera->pos);
manifoldturn(&cameraray, camera->z, -dist);
free_vec(cameraray.pos);
cameraray.pos = camera->pos;
manifoldstep(&cameraray, -dist);
done = -dist;
}
if (keyboardstate[SDL_SCANCODE_LEFT]) {
struct ray cameraray = {.pos = copy_vec(camera->pos), .dir = camera->x};
manifoldturn(&cameraray, camera->z, dist);
free_vec(cameraray.pos);
cameraray.pos = copy_vec(camera->pos);
manifoldturn(&cameraray, camera->y, dist);
free_vec(cameraray.pos);
cameraray.pos = camera->pos;
manifoldstep(&cameraray, -dist);
done = -dist;
}
if (keyboardstate[SDL_SCANCODE_RIGHT]) {
struct ray cameraray = {.pos = copy_vec(camera->pos), .dir = camera->x};
manifoldturn(&cameraray, camera->z, dist);
free_vec(cameraray.pos);
cameraray.pos = copy_vec(camera->pos);
manifoldturn(&cameraray, camera->y, dist);
free_vec(cameraray.pos);
cameraray.pos = camera->pos;
manifoldstep(&cameraray, dist);
done = -dist;
}
r.dir->elements[0] = -1;
if (keyboardstate[SDL_SCANCODE_ESCAPE]) {
exitnow = 1;
}
if (fabs(done) > 0.00001)
manifoldstep(&r, done);
free_vec(r.dir);
free_vec(r.pos);
return;
};
@ -69,8 +133,8 @@ int input_loop(void *ptr) { @@ -69,8 +133,8 @@ int input_loop(void *ptr) {
break;
}
}
handle_inputs();
SDL_Delay(50);
handle_inputs();
}
return 0;
}
@ -96,25 +160,26 @@ static int raymarch_threadfn(void *data) { @@ -96,25 +160,26 @@ static int raymarch_threadfn(void *data) {
}
struct colour yeet_whit(struct ray *ray) {
struct colour yeet_whit(struct ray *ray, struct object* obj) {
struct colour c = {.r = 200, .g = 200, .b = 200, .a = 255, .sp=CS_RGB};
return c;
}
void setup_camera_scene()
{
struct object white_sphere = new_sphere(10);
white_sphere.sol.pos.elements[0] = 0.75;
white_sphere.sol.pos.elements[1] = 0;
white_sphere.sol.pos.elements[2] = 7;
white_sphere.sol.dist = sdf_hplane;
white_sphere.col = yeet_whit;
struct object other_white_sphere = new_sphere(10);
other_white_sphere.sol.pos.elements[0] = 0;
other_white_sphere.sol.pos.elements[1] = 0;
other_white_sphere.sol.pos.elements[2] = 7;
other_white_sphere.sol.dist = sdf_sphere;
//struct object white_sphere = new_object(new_vec3(0.75, 0, 8), 0, 1, sdf_box, yeet_whit);
camera = calloc(1, sizeof(struct camera));
camera->pos = new_vec(4);
camera->x = new_vec(4);
camera->y = new_vec(4);
camera->z = new_vec(4);
camera->x->elements[0] = 1;
camera->y->elements[1] = 1;
camera->z->elements[2] = 1;
struct object white_sphere = new_sphere(new_vec3(-0.75, 0, 8), 0, 1);
struct object other_white_sphere = new_sphere(new_vec3(0.75, 0, 8), 0, 1);
struct object* scene_objects = malloc(2 * sizeof(struct object));
scene_objects[1] = white_sphere;
@ -124,6 +189,8 @@ void setup_camera_scene() @@ -124,6 +189,8 @@ void setup_camera_scene()
}
int main(int argc, char **argv) {
SDL_Window * win = make_window();
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_RenderSetLogicalSize(ren, B_INTERNAL_HEIGHT, B_INTERNAL_HEIGHT);
@ -131,26 +198,25 @@ int main(int argc, char **argv) { @@ -131,26 +198,25 @@ int main(int argc, char **argv) {
// use this to turn on antristroptic filtering
// SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
SDL_Thread *input_thread = SDL_CreateThread(input_loop, "input", (void *)NULL);
double elapsed;
int framct = 0;
Uint64 start, end;
/* texture for drawing into */
SDL_Rect view = {.w = B_INTERNAL_WIDTH, .h = B_INTERNAL_HEIGHT, .x = 0, .y = 0};
SDL_Texture *texture = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC, B_INTERNAL_WIDTH, B_INTERNAL_HEIGHT);
SDL_Thread ** threads = calloc(B_NUM_RAYMARCH_THREADS, sizeof(SDL_Thread *));
SDL_Thread *input_thread = SDL_CreateThread(input_loop, "input", (void *)NULL);
setup_camera_scene();
while (!exitnow) {
/* clear the view */
start = SDL_GetPerformanceCounter();
SDL_RenderClear(ren);
for (int i = 0; i < B_NUM_RAYMARCH_THREADS; i++) {
int *tid = malloc(sizeof(int));
*tid = i;
@ -163,7 +229,7 @@ int main(int argc, char **argv) { @@ -163,7 +229,7 @@ int main(int argc, char **argv) {
SDL_WaitThread(threads[i], &status);
}
SDL_UpdateTexture(texture, &view, pixels, B_INTERNAL_WIDTH * sizeof(Uint32));
SDL_UpdateTexture(texture, NULL, pixels, B_INTERNAL_WIDTH * sizeof(Uint32));
SDL_RenderCopy(ren, texture, NULL, NULL);
@ -175,8 +241,11 @@ int main(int argc, char **argv) { @@ -175,8 +241,11 @@ int main(int argc, char **argv) {
elapsed = 1000 / el;
}
printf("\rframerate: %f", elapsed);
fflush(stdout);
// fflush(stdout);
framct++;
if (framct++ > 2) {
}
}
SDL_DestroyTexture(texture);

2
main.h

@ -32,4 +32,6 @@ void sdlb_set_colour(struct colour col); @@ -32,4 +32,6 @@ void sdlb_set_colour(struct colour col);
void sdlb_draw_col_pixel(struct colour col, int x, int y);
extern struct object scene_object;
extern int keyboardstate[322]; // 322 is the number of SDLK_DOWN events
extern struct camera *camera;
#endif

126
presentation.md

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
---
title: BlackPink (Manifold Raymarching Rendering Engine)
author: _"A Blazing 100x100px at 10FPS"_
...
(we had to name it that because Joel likes naming things after pop artists.)
---
# Objective
Can we use raymarching to render primitive objects inside an arbitrary manifold
in real time?
"Non-euclidean rendering" in the most generalised form possible.
---
# Raymarching
- an approximate and fast form of 'raytracing'
- good for primitives (spheres, boxes et cetera.)
- still very expensive
---
# Manifolds
Only one of us does galaxy brain maths.
---
# Tech Stack Requirements
- Fast, compiled code
- We are relatively familiar with it (that disqualifies any _modern_ or "good"
language, and C++)
- Need n-dimensional vectors
- Need to draw pixels on a window
- not Java
---
# C and libSDL2
Its fast (to run) and we "know" it. C is a nice language if only for the
simplicity of its mental model.
libSDL2 is what the big kids like Valve use.
- nicely handles threading, drawing, timers, and gets out of the way.
---
Richal spent 10 hours writing a vector library from scratch.
N-dimentional determinants and cross products _sound_ simple.
---
At one point we were leaking memory at approximately 150Mb per second.
![lots of vagrind errors](img/b1.jpg)
---
![1pm Saturday](img/b3.png)
---
![Fail states were often interesting](img/b2.png)
---
12 Hours later, we could render
- circles
- boxes, and
- straight lines
from one angle, and move them around the scene
- as long as we got lucky with whatever the 4th dimension was doing.
Plus some post-processing and lighting.
---
![a green sphere](img/b4.jpg)
---
# Results
video? image? demo?
---
# Takeaways 1
- sticking raymarching vectors to manifolds in 4 dimensions is possible but has
a lot of edge cases
---
# Takeaways 2
- having RAII would be really nice when writing a vector library
```c
if (1 || keyboardstate[SDL_SCANCODE_UP]) {
struct ray cameraray = {.pos = copy_vec(camera->pos), .dir = camera->y};
manifoldturn(&cameraray, camera->x, 0);
free_vec(cameraray.pos);
cameraray.pos = copy_vec(camera->pos);
manifoldturn(&cameraray, camera->y, 0);
free_vec(cameraray.pos);
cameraray.pos = camera->pos;
manifoldstep(&cameraray, dist);
free_vec(cameraray.pos);
}
```

14
scene.c

@ -8,7 +8,7 @@ struct scene_objects { @@ -8,7 +8,7 @@ struct scene_objects {
struct scene_objects scene;
struct colour
colour_function(struct ray* ray)
colour_function(struct ray* ray, struct object* obj)
{
if (scene.num_objects == 0) {
return (struct colour) {};
@ -32,7 +32,7 @@ distance_function(struct vec* position) @@ -32,7 +32,7 @@ distance_function(struct vec* position)
{
double min = DBL_MAX;
for (int i = 0; i < scene.num_objects; i++) {
double distance = solid_dist(&(scene.objects[i].sol), position); //scene.objects->sol.dist(position);
double distance = solid_dist(&(scene.objects[i].sol), position);
if (distance < min) {
min = distance;
}
@ -42,14 +42,18 @@ distance_function(struct vec* position) @@ -42,14 +42,18 @@ distance_function(struct vec* position)
}
struct object
new_scene(int num_scene_objects, struct object* scene_objects) {
new_scene(int num_scene_objects, struct object* scene_objects)
{
scene.num_objects = num_scene_objects;
scene.objects = scene_objects;
// for (int i = 0; i < num_scene_objects; i++) {
// place(&(scene.objects[i].sol));
// }
struct object scene_rep;
scene_rep.sol.dist = distance_function;
scene_rep.sol.op = B_ADD;
scene_rep.sol.pos = *new_vec4(0,0,0,0);
scene_rep.sol.rotation = 0;
scene_rep.sol.scale = 1;
@ -57,3 +61,5 @@ new_scene(int num_scene_objects, struct object* scene_objects) { @@ -57,3 +61,5 @@ new_scene(int num_scene_objects, struct object* scene_objects) {
return scene_rep;
}

6
types.h

@ -22,8 +22,11 @@ struct ray @@ -22,8 +22,11 @@ struct ray
struct camera
{
struct vec *x;
struct vec *y;
struct vec *z;
struct vec *pos;
struct vec *rot;
//struct vec *rot;
int dims;
};
@ -47,6 +50,7 @@ struct solid { @@ -47,6 +50,7 @@ struct solid {
struct object
{
struct solid sol;
struct colour base_col;
struct colour (*col)(struct ray *, struct object *o);
};

Loading…
Cancel
Save