summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--LICENCE13
-rw-r--r--Makefile24
-rw-r--r--ray.c177
4 files changed, 215 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e027563
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+ray
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..6daef8d
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,13 @@
+Copyright (c) 2010, Martin StensgÄrd <mastensg@ping.uio.no>.
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..892125d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+DEBUG = -O0 -ggdb -g3
+DEBUG = -O3
+CFLAGS = -Wall -pedantic -std=gnu99 $(DEBUG)
+LDFLAGS = -lGL -lGLU -lglut
+BINARY = ray
+VERSION = 0.1
+PREFIX = /usr/local
+OBJECTS = $(BINARY).o
+
+all: $(BINARY)
+
+clean:
+ rm -f $(BINARY).o $(BINARY)
+
+install: all
+ mkdir -p $(PREFIX)/bin
+ cp -f $(BINARY) $(PREFIX)/bin/$(BINARY)
+ chmod 755 $(PREFIX)/bin/$(BINARY)
+ mkdir -p $(PREFIX)/man/man1
+ sed "s/VERSION/$(VERSION)/g" < $(BINARY).1 > $(PREFIX)/man/man1/$(BINARY).1
+ chmod 644 $(PREFIX)/man/man1/$(BINARY).1
+
+uninstall:
+ rm -f $(BINARY) $(PREFIX)/bin/$(BINARY)
diff --git a/ray.c b/ray.c
new file mode 100644
index 0000000..f96f5f0
--- /dev/null
+++ b/ray.c
@@ -0,0 +1,177 @@
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glut.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define WIDTH 1080
+#define HEIGHT 1080
+#define BUFFER_SIZE (WIDTH * HEIGHT * 4)
+
+#define LENGTH(array) (sizeof(array) / sizeof(array[0]))
+#define MAX(x, y) (x > y ? x : y)
+#define MIN(x, y) (x < y ? x : y)
+#define POW2(x) ((x) * (x))
+#define POW3(x) ((x) * (x) * (x))
+#define POW4(x) ((x) * (x) * (x) * (x))
+#define POW5(x) ((x) * (x) * (x) * (x) * (x))
+
+typedef struct {
+ float position[3];
+ float radius;
+ float diffuse[3];
+} Object;
+
+typedef struct {
+ float position[3];
+ float diffuse[3];
+} Light;
+
+static Object objects[2] = {{.position={1.5, 0, -20}, .radius=.1, .diffuse={0, 0, .3}},
+ {.position={-1.5, 0, -30}, .radius=.1, .diffuse={0, 0, .3}}};
+static Light lights[1] = {{.position={0, 2, -4}, .diffuse={0, .7, .7}}};
+static unsigned char buffer[BUFFER_SIZE];
+
+static float
+dot(float x[3], float y[3]) {
+ return x[0] * y[0] + x[1] * y[1] + x[2] * y[2];
+}
+
+static void
+normalize(float x[3]) {
+ float len;
+ int i;
+
+ len = sqrt(dot(x, x));
+
+ for(i = 0; i < 3; ++i)
+ x[i] /= len;
+}
+
+static void
+trace(float s[3], float d[3], float pixel[3], int N) {
+ int i, j;
+ float D;
+ float l[3];
+ float n[3];
+ float t;
+ float v[3];
+ float vd, vv;
+ float y[3];
+ Object *object = objects;
+ Light *light = lights;
+
+ for(j = 0; j < LENGTH(objects); ++j) {
+ object = &objects[j];
+
+ for(i = 0; i < 3; ++i)
+ v[i] = s[i] - object->position[i];
+
+ vd = dot(v, d);
+ vv = dot(v, v);
+
+ D = POW2(2 * vd) - 4 * (vv - POW2(object->radius));
+
+ if(D < 0) {
+ pixel[0] += .3;
+ pixel[1] += .15;
+ pixel[2] += .075;
+ } else {
+
+ t = MIN(-vd + sqrt(D), -vd - sqrt(D));
+
+ for(i = 0; i < 3; ++i) {
+ y[i] = s[i] + t * d[i];
+ n[i] = y[i] - object->position[i];
+ l[i] = light->position[i] - object->position[i];
+ }
+
+ normalize(n);
+ normalize(l);
+
+ for(i = 0; i < 3; ++i) {
+ n[i] = (object->diffuse[i] + light->diffuse[i]) * dot(n, l);
+ //n[i] = object->diffuse[i];
+ pixel[i] += n[i];
+ }
+
+ if(N)
+ trace(y, n, pixel, N - 1);
+ }
+ }
+}
+
+static void
+display(void) {
+ int i, j;
+ float x, y;
+ float s[3] = {0, 0, 1};
+ float d[3];
+ float pixel[3];
+
+ memset(buffer, '\0', sizeof(buffer));
+
+ for(i = 0; i < BUFFER_SIZE; i += 4) {
+ x = (i / 4) % WIDTH - WIDTH / 2;
+ y = (i / 4) / WIDTH - HEIGHT / 2;
+
+ d[0] = x / (WIDTH / 2);
+ d[1] = y / (HEIGHT / 2);
+ d[2] = -1;
+
+ memset(pixel, '\0', sizeof(pixel));
+ trace(s, d, pixel, 0);
+
+ //printf("%f %f %f\n", pixel[0], pixel[1], pixel[2]);
+
+ for(j = 0; j < 3; ++j)
+ buffer[i + j] = MIN(255 * pixel[j], 255);
+ }
+
+ glDrawPixels(WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+
+ glutSwapBuffers();
+}
+
+static void
+reshape(int w, int h) {
+ glViewport(0, 0, w, h);
+}
+
+static void
+keyboard(unsigned char key, int x, int y) {
+ if (key == 27)
+ exit(0);
+}
+
+static int
+init(int argc, char **argv, int w, int h) {
+ glutInit(&argc, argv);
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(w, h);
+ glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
+ glutCreateWindow(argv[0]);
+
+ glDepthMask(0);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+
+ return 0;
+}
+
+int
+main(int argc, char **argv) {
+ if (init(argc, argv, WIDTH, HEIGHT))
+ return 1;
+
+ glutDisplayFunc(display);
+ glutReshapeFunc(reshape);
+ glutKeyboardFunc(keyboard);
+
+ glutMainLoop();
+
+ return 0;
+}