octree

octree tools and accessories
git clone git://nsmpr.xyz/octree.git
Log | Files | Refs

commit 545ff5be825e3fa35ee502e9bc041bca47845825
parent 4f249861bda9257aae0b8568da0f352b4e28cab2
Author: glenda <glenda@9front.local>
Date:   Fri, 19 Mar 2021 13:08:57 +0000

render: implement ray marching

Diffstat:
Mrender.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/render.c b/render.c @@ -3,10 +3,12 @@ #include "octree.h" +#define SQR(X) (X * X) + typedef struct Pixel Pixel; typedef struct Dot Dot; -typedef struct Rad Rad; typedef struct Ray Ray; +typedef struct Sphere Sphere; struct Pixel { double r; @@ -20,38 +22,80 @@ struct Dot { double z; }; -struct Rad { - double u; - double v; - double z; -}; struct Ray { Dot pos; - Rad dir; + Dot dir; +}; + +struct Sphere { + Dot pos; + double radius; }; Pixel Pwhite = {1, 1, 1}; Pixel Pblack = {0, 0, 0}; -Ray sphere = {{0.5, 0.5, 0}, {0, 0, 0.5}}; +Sphere sphere = {{0.5, 0.5, 0}, 0.5}; + +double +dotmod(Dot d) +{ + return sqrt(SQR(d.x) + SQR(d.y) + SQR(d.z)); +} + +Dot +dotnorm(Dot d) +{ + double m; + m = dotmod(d); + return (Dot){d.x/m, d.y/m, d.z/m}; +} + +Dot +dotxdot(Dot d1, Dot d2) +{ + return (Dot){d1.x * d2.x, d1.y * d2.y, d1.z * d2.z,}; +} + +Dot +adddot(Dot d1, Dot d2) +{ + return (Dot){d1.x + d2.x, d1.y + d2.y, d1.z + d2.z,}; +} + + +Dot +subdot(Dot d1, Dot d2) +{ + return adddot(d1, (Dot){-d2.x, -d2.y, -d2.z}); +} int -spherehit(Ray v, Ray s) +spherehit(Ray *v, Sphere s) { - return (hypot(v.pos.x -s.pos.x, v.pos.y - s.pos.y) <= s.dir.z); + double d, old; + int i; + old = Inf(1); + for (i = 0; i < 1024; i++) { + d = dotmod(subdot(v->pos, s.pos)) - s.radius; + v->pos = adddot(v->pos, + dotxdot(dotnorm(v->dir), (Dot){d, d, d})); + if (d < 0.0001) { + return 1; + } + if (d > old) return 0; + old = d; + } + return 0; } Pixel ray(Ray v) { - Pixel p = { - .r = (v.pos.x + v.pos.y)/2, - .g = 0, - .b = 0, - }; - if (spherehit(v, sphere)) { - p = Pblack; + Pixel p = Pblack; + if (spherehit(&v, sphere)) { + p = Pwhite; } return p; } @@ -62,7 +106,8 @@ render(int x, int y) Pixel p; int r, g, b; Ray v; - v.pos = (Dot){ (double)x/256.0, (double)y/256.0, 0 }; + v.pos = (Dot){ (double)x/256.0, (double)y/256.0, -100 }; + v.dir = (Dot){ 0, 0, 1 }; p = ray(v); r = 0xff * p.r; g = 0xff * p.g;