レイトレーサーを作るシリーズ:

グローバルイルミネーションどころか、レイトレーサーもよくわかってないので、lucille development blog » Blog Archive » Rendering with Proce55ing. のプログラムを参考にProce55ingで作ってみたい。

まずは基本。球と線分の交差判定を調べて色を塗る:

int renderY = 0;
color LineBuf[];

void setup() {
  size(256, 256);
  LineBuf = new color[width];
}

void draw() {
  render_line(LineBuf, width, height, renderY);
  copy_line(LineBuf, renderY);
  if (++renderY >= height) {
    noLoop();
  }
}

void copy_line(color[] img, int y) {
  loadPixels();
  for (int i = 0; i < width; ++i) {
    pixels[y * width + i] = img[i];
  }
  updatePixels();
}

// 線分と球の交差判定
float intersect_line_sphere(vec orig, vec dir, vec sphere_center, float sphere_radius) {
  vec c = sphere_center;
  vec s = orig;
  vec d = dir;
  float r = sphere_radius;
  vec v = s.sub(c);

  float dd = sq(v.dot(d)) - (v.dot(v) - sq(r));
  if (dd < 0) {
    return -1;  // not intersect
  } else {
    float sqdd = sqrt(dd);
    float t1 = -v.dot(d) - sqdd;
    return t1;  // maybe intersect
  }
}

vec eyepos = new vec(0, 0, -1);
vec sphere_center = new vec(0, 0, 0);
float sphere_radius = 0.5;

void render_line(color[] img, int width, int height, int iy) {
  float w2 = width / 2;
  float h2 = height / 2;
  float xofs = w2 - 0.5;
  float yofs = h2 - 0.5;
  float py = -((iy - yofs) / h2);    // flip Y

  for (int j=0; j<width; ++j) {
    float px = (j - xofs) / w2;
    vec raydir = (new vec(px, py, 1)).normal();

    float t = intersect_line_sphere(eyepos, raydir, sphere_center, sphere_radius);
    if (t >= 0) {
      img[j] = color(255, 0, 0);
    } else {
      img[j] = color(0, 0, 0);
    }
  }
}