commit 545ff5be825e3fa35ee502e9bc041bca47845825
parent 4f249861bda9257aae0b8568da0f352b4e28cab2
Author: glenda <glenda@9front.local>
Date: Fri, 19 Mar 2021 13:08:57 +0000
render: implement ray marching
Diffstat:
M | render.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;