Files
batomorph/demo.c

109 lines
2.4 KiB
C

#include "ff.h"
#include "vec3.h"
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#define W 800
#define H 600
#define VP_H 2.0
#define VP_W (VP_H * W / H)
#define FOCLEN 1.0
typedef struct {
vec3_t orig, dir;
} ray_t;
typedef struct {
vec3_t centre;
double rad;
} sphere_t;
static const vec3_t lightblue = { 0.4, 0.6, 1.0 };
static const vec3_t white = { 1.0, 1.0, 1.0 };
static const vec3_t red = { 1.0, 0.1, 0.2 };
static const vec3_t camera = { 0, 0, 0 };
static const vec3_t vp_disp = { 0, 0, FOCLEN };
static const vec3_t vp_u = { VP_W, 0, 0 };
static const vec3_t vp_v = { 0, -VP_H, 0 };
static const vec3_t pix_x_step = { VP_W / W, 0, 0 };
static const vec3_t pix_y_step = { 0, -VP_H / H, 0 };
static const sphere_t obj = {
.centre = { 1.0, 0.0, -3.0 },
.rad = 1.0,
};
static pix_t pix[W * H];
static double intersect(sphere_t sphere, ray_t ray)
{
const vec3_t disp = vec3_sub(sphere.centre, ray.orig);
const double a = vec3_dot(ray.dir, ray.dir);
const double b = -2.0 * vec3_dot(ray.dir, disp);
const double c = vec3_dot(disp, disp) - sphere.rad * sphere.rad;
const double discriminant = b * b - 4 * a * c;
if (discriminant < 0)
return -1.0;
else
return (-b - sqrt(discriminant)) / (2.0 * a);
}
static vec3_t raycol(ray_t ray)
{
const double t = intersect(obj, ray);
if (t > 0.0)
return red;
const double a = (ray.dir.y + 1.0) / 2.0;
return vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a));
}
static void setpix(vec3_t col, pix_t *out)
{
out->r = UINT16_MAX * col.x;
out->g = UINT16_MAX * col.y;
out->b = UINT16_MAX * col.z;
out->a = UINT16_MAX;
}
int main()
{
img_t img = { .w = W, .h = H, .pix = pix };
const vec3_t vp_topleft = vec3_sub(
vec3_sub(vec3_sub(camera, vp_disp), vec3_scale(vp_u, 0.5)),
vec3_scale(vp_v, 0.5));
const vec3_t pix_orig = vec3_add(
vec3_add(vp_topleft, vec3_scale(pix_x_step, 0.5)),
vec3_scale(pix_y_step, 0.5));
for (unsigned y = 0; y < H; ++y) {
fprintf(stderr, "\r[%3d/%3d]", y, H);
fflush(stderr);
const vec3_t row = vec3_add(pix_orig, vec3_scale(pix_y_step, y));
for (unsigned x = 0; x < W; ++x) {
const ray_t ray = {
.orig = camera,
.dir = vec3_unit(vec3_add(row, vec3_scale(pix_x_step, x))),
};
const vec3_t col = raycol(ray);
setpix(col, pix + (W * y + x));
}
}
fprintf(stderr, "\r[%3d/%3d]\n", H, H);
ff_write(STDOUT_FILENO, img);
return 0;
}