Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
* Build with:
* g++ aaraymarcher.cpp $(aalib-config --cflags) $(aalib-config --libs) -lm -o aaraymarcher
*/
#include <math.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <aalib.h>
aa_context *aactx;
double t = 0.0;
int WIDTH;
int HEIGHT;
struct vec3 {
float x;
float y;
float z;
float length() {
return sqrt(x*x + y*y + z*z);
}
void normalize() {
float l = length();
x = x / l; y = y / l; z = z / l;
}
struct vec3 operator*(float fac) {
struct vec3 r;
r.x = x * fac; r.y = y * fac; r.z = z * fac;
return r;
}
struct vec3 operator+(struct vec3 other) {
struct vec3 r;
r.x = x +other.x; r.y = y +other.y; r.z = z + other.z;
return r;
}
struct vec3 operator-(struct vec3 other) {
struct vec3 r;
r.x = x - other.x; r.y = y - other.y; r.z = z - other.z;
return r;
}
};
void raymarch();
float sdf(struct vec3);
float shade(struct vec3);
void raymarch() {
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
struct vec3 pos = {0.0, 0.0, -3.0};
struct vec3 target = {
x / (float) WIDTH - 0.5f,
(y / (float) HEIGHT - 0.5f) * (HEIGHT / (float) WIDTH) * 1.5f,
-1.5f
};
struct vec3 ray = target - pos;
ray.normalize();
float pxl = 0.0;
float dist;
float max = 9999.0f;
for (int i = 0; i < 15000; i++) {
if (fabs(pos.x) > max
|| fabs(pos.y) > max
|| fabs(pos.z) > max)
break;
dist = sdf(pos);
if (dist < 1e-6) {
pxl = shade(pos);
break;
}
pos = pos + ray * dist;
} // end for (i)
//printf("aa_putpixel(aactx, %d, %d, %d)\n", x, y, (int)(pxl * 256));
aa_putpixel(aactx, x, y, (int)(pxl * 256));
} // end for(x)
} // end for(y)
} // end raymarch()
float sdf(struct vec3 pos) {
struct vec3 center = {0.0, 0.0, 0.0};
return (pos - center).length() - 0.2;
}
float shade(struct vec3 pos) {
struct vec3 L = {
50.0 * sin(t),
20.0,
50.0 * cos(t)
};
L.normalize();
float dt = 1e-6;
float current_val = sdf(pos);
struct vec3 x = {pos.x + dt, pos.y, pos.z};
float dx = sdf(x) - current_val;
struct vec3 y = {pos.x, pos.y + dt, pos.z};
float dy = sdf(y) - current_val;
struct vec3 z = {pos.x, pos.y, pos.z + dt};
float dz = sdf(z) - current_val;
struct vec3 N; // N for normal
N.x = (dx - pos.x) / dt;
N.y = (dy - pos.y) / dt;
N.z = (dz - pos.z) / dt;
if (N.length() < 1e-9) {
return 0.0;
}
N.normalize();
float diffuse = L.x * N.x + L.y * N.y + L.z * N.z;
return (diffuse + 1.0) / 2.0;
}
void showfb()
{
int sw = aa_scrwidth(aactx);
int sh = aa_scrheight(aactx);
aa_render(aactx, &aa_defrenderparams,
0, 0,
sw, sh);
aa_flush(aactx);
}
void update_dimensions()
{
HEIGHT = aa_imgheight(aactx);
WIDTH = aa_imgwidth(aactx);
}
int main(int argc, char **argv) {
if(!aa_parseoptions(&aa_defparams, &aa_defrenderparams, &argc, argv) || argc!=1) {
// if(!aa_parseoptions(NULL, NULL, &argc, argv) || argc!=1) {
printf("Usage: %s [options]\n"
"Options:\n"
"%s", argv[0], aa_help);
exit(1);
}
aactx = aa_autoinit(&aa_defparams);
if (aactx == NULL) {
fprintf(stderr, "Cannot initialize AA-lib.\n");
exit(1);
}
aa_autoinitkbd(aactx, 0);
update_dimensions();
while(true) {
double last_frame = t;
if (aa_getevent(aactx, 0) != AA_NONE) {
break;
}
raymarch();
showfb();
do {
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
t = time.tv_sec + time.tv_nsec * 1e-9;
} while ((t - last_frame) < 1.0 / 60.0);
}
aa_close(aactx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment