Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Ray Tracing
final int WIDTH = 683;
final int HEIGHT= 384;
public void settings(){
size(WIDTH, HEIGHT, P2D);
}
public void printf(Object o){
System.out.println(o);
}
Ball[] balls = new Ball[3];
public void setup(){
balls[0] = new Ball(new float[]{0, 0, 0}, 1, new Color(1, 1, 1), 0.9);
balls[1] = new Ball(new float[]{-3, 0, 0}, 0.5, new Color(0.3, 0.6, 0.9), 0.7);
balls[2] = new Ball(new float[]{0, -3, 0}, 0.3, new Color(1, 0.2, 0), 0.5);
}
float alfa = 0, beta = PI/2, r = 1.9;
public void draw(){
loadPixels();
Camera cam = new Camera(r,alfa,beta);
for(int i=0;i<HEIGHT;i++){
for(int j=0;j<WIDTH;j++){
float[] origin ={
cam.x,
cam.y,
cam.z
};
float[] unit= {
-((float)(j-WIDTH/2)+0.5)/(float)(WIDTH/2),
((float)(i-HEIGHT/2)+0.5)/(float)(WIDTH/2),
-1
};
transformVector(unit, cam.matrix);
unit[0] -= cam.x;
unit[1] -= cam.y;
unit[2] -= cam.z;
normalize(unit);
Color luminance = cam.rayTrace(origin,unit,balls,1,0.3,5).mul(256);
pixels[i * width + j] = color((int)luminance.red, (int)luminance.green, (int)luminance.blue);
}
}
updatePixels();
beta = map(mouseY, 0, width, -PI, PI);
alfa = map(mouseX, 0, height, -PI, PI);
}
public void mouseWheel(MouseEvent e){
int amt = e.getCount();
r += amt;
}
class Ball {
float[] center;
float radius;
Color col; //on the interval from 0 (dark) to 1 (light)
float coeff;
Ball(float[] center, float radius, Color col, float coeff){
this.center = center;
this.radius = radius;
this.col = col;
this.coeff = coeff;
}
}
class Camera {
float x,y,z;
float[] matrix = new float[16];
float[] inv = new float[16];
public Camera(float r, float alfa, float beta) {
float a = sin(alfa), b = cos(alfa), c = sin(beta), d = cos(beta);
x=r*b*d;
y=r*a*d;
z=r*c;
//matrix
matrix[3]=matrix[7]=matrix[11]=0;
matrix[15]=1;
//x
matrix[0]=-a;
matrix[1]=b;
matrix[2]=0;
//y
matrix[4]=b*c;
matrix[5]=a*c;
matrix[6]=-d;
//z
matrix[8]=b*d;
matrix[9]=a*d;
matrix[10]=c;
matrix[12]=x;
matrix[13]=y;
matrix[14]=z;
//invert
inv = invert(matrix);
}
Color rayTrace(float[] origin,float[] unit, Ball[] balls, float altitude, float coeff, int limit){
float distanceToPlane =- (origin[2] + altitude) / unit[2]; //this is signed distance
int index = -1;
float distance = 0;
for(int i=0;i < balls.length;i++) {
float[] diff = diff(origin, balls[i].center);
float discriminant = dot(unit, diff) * dot(unit, diff) + balls[i].radius * balls[i].radius - dot(diff, diff);
if (discriminant < 0) continue;
distance =- dot(unit, diff) - sqrt(discriminant);
if (distance<=0) continue;
index = i;
break;
}
if (index == -1){
if(unit[2] > 0){
return new Color(0, 0, 0);
} else {
float
tx = origin[0] + distanceToPlane * unit[0],
ty = origin[1] + distanceToPlane * unit[1];
float shade = clamp(1 / (1 + distanceToPlane / 10),0,1);
Color col = new Color(shade, shade, shade);
float[] origin2 = {
origin[0] + distanceToPlane * unit[0],
origin[1] + distanceToPlane * unit[1],
origin[2] + distanceToPlane * unit[2]
};
float[] unit2 ={
unit[0],
unit[1],
-unit[2]
};
if( (int)(floor(tx) + floor(ty)) % 2 == 0)
return col.mul(1-coeff).add(rayTrace(origin2,unit2,balls,altitude,coeff,limit-1).mul(coeff));
else
return new Color(0, 0, 0);
}
}
// Ray hit the ground
if (unit[2] < 0 && distance > distanceToPlane){
float
tx=origin[0]+distanceToPlane*unit[0],
ty=origin[1]+distanceToPlane*unit[1];
float checker = (int)(floor(tx)+floor(ty))%2;
return new Color(checker, checker, checker);
}
//ray hit a ball
float[] origin2 = new float[]{
origin[0] + unit[0] * distance,
origin[1] + unit[1] * distance,
origin[2] + unit[2] * distance
};
float[] normal = diff(origin2, balls[index].center);
normalize(normal);
float k = 2 * dot(unit, normal);
scale(normal, k);
float[] unit2 = diff(unit, normal);
if (limit == 0) return balls[index].col;
return balls[index].col.mul(1-balls[index].coeff).add(rayTrace(origin2,unit2,balls,altitude,coeff,limit-1).mul(balls[index].coeff));
}
}
class Color {
float red;
float green;
float blue;
Color(float red, float green, float blue){
this.red = red;
this.green = green;
this.blue = blue;
}
Color mul(float f){
return new Color(this.red * f,
this.green * f,
this.blue * f);
}
Color add(float k){
return
new Color(this.red + k,
this.green + k,
this.blue + k);
}
Color add(Color other){
return new Color(this.red + other.red,
this.green + other.green,
this.blue + other.blue);
}
}
public static void transformVector(float[] vec, final float[] m){
float tx=vec[0]*m[0]+vec[1]*m[4]+vec[2]*m[8]+m[12],
ty=vec[0]*m[1]+vec[1]*m[5]+vec[2]*m[9]+m[13],
tz=vec[0]*m[2]+vec[1]*m[6]+vec[2]*m[10]+m[14];
vec[0]=tx;
vec[1]=ty;
vec[2]=tz;
}
public static float[] invert(final float[] matrix){
float[] inv = new float[16];
float det;
int i;
inv[0] = matrix[5] * matrix[10] * matrix[15] -
matrix[5] * matrix[11] * matrix[14] -
matrix[9] * matrix[6] * matrix[15] +
matrix[9] * matrix[7] * matrix[14] +
matrix[13] * matrix[6] * matrix[11] -
matrix[13] * matrix[7] * matrix[10];
inv[4] = -matrix[4] * matrix[10] * matrix[15] +
matrix[4] * matrix[11] * matrix[14] +
matrix[8] * matrix[6] * matrix[15] -
matrix[8] * matrix[7] * matrix[14] -
matrix[12] * matrix[6] * matrix[11] +
matrix[12] * matrix[7] * matrix[10];
inv[8] = matrix[4] * matrix[9] * matrix[15] -
matrix[4] * matrix[11] * matrix[13] -
matrix[8] * matrix[5] * matrix[15] +
matrix[8] * matrix[7] * matrix[13] +
matrix[12] * matrix[5] * matrix[11] -
matrix[12] * matrix[7] * matrix[9];
inv[12] = -matrix[4] * matrix[9] * matrix[14] +
matrix[4] * matrix[10] * matrix[13] +
matrix[8] * matrix[5] * matrix[14] -
matrix[8] * matrix[6] * matrix[13] -
matrix[12] * matrix[5] * matrix[10] +
matrix[12] * matrix[6] * matrix[9];
inv[1] = -matrix[1] * matrix[10] * matrix[15] +
matrix[1] * matrix[11] * matrix[14] +
matrix[9] * matrix[2] * matrix[15] -
matrix[9] * matrix[3] * matrix[14] -
matrix[13] * matrix[2] * matrix[11] +
matrix[13] * matrix[3] * matrix[10];
inv[5] = matrix[0] * matrix[10] * matrix[15] -
matrix[0] * matrix[11] * matrix[14] -
matrix[8] * matrix[2] * matrix[15] +
matrix[8] * matrix[3] * matrix[14] +
matrix[12] * matrix[2] * matrix[11] -
matrix[12] * matrix[3] * matrix[10];
inv[9] = -matrix[0] * matrix[9] * matrix[15] +
matrix[0] * matrix[11] * matrix[13] +
matrix[8] * matrix[1] * matrix[15] -
matrix[8] * matrix[3] * matrix[13] -
matrix[12] * matrix[1] * matrix[11] +
matrix[12] * matrix[3] * matrix[9];
inv[13] = matrix[0] * matrix[9] * matrix[14] -
matrix[0] * matrix[10] * matrix[13] -
matrix[8] * matrix[1] * matrix[14] +
matrix[8] * matrix[2] * matrix[13] +
matrix[12] * matrix[1] * matrix[10] -
matrix[12] * matrix[2] * matrix[9];
inv[2] = matrix[1] * matrix[6] * matrix[15] -
matrix[1] * matrix[7] * matrix[14] -
matrix[5] * matrix[2] * matrix[15] +
matrix[5] * matrix[3] * matrix[14] +
matrix[13] * matrix[2] * matrix[7] -
matrix[13] * matrix[3] * matrix[6];
inv[6] = -matrix[0] * matrix[6] * matrix[15] +
matrix[0] * matrix[7] * matrix[14] +
matrix[4] * matrix[2] * matrix[15] -
matrix[4] * matrix[3] * matrix[14] -
matrix[12] * matrix[2] * matrix[7] +
matrix[12] * matrix[3] * matrix[6];
inv[10] = matrix[0] * matrix[5] * matrix[15] -
matrix[0] * matrix[7] * matrix[13] -
matrix[4] * matrix[1] * matrix[15] +
matrix[4] * matrix[3] * matrix[13] +
matrix[12] * matrix[1] * matrix[7] -
matrix[12] * matrix[3] * matrix[5];
inv[14] = -matrix[0] * matrix[5] * matrix[14] +
matrix[0] * matrix[6] * matrix[13] +
matrix[4] * matrix[1] * matrix[14] -
matrix[4] * matrix[2] * matrix[13] -
matrix[12] * matrix[1] * matrix[6] +
matrix[12] * matrix[2] * matrix[5];
inv[3] = -matrix[1] * matrix[6] * matrix[11] +
matrix[1] * matrix[7] * matrix[10] +
matrix[5] * matrix[2] * matrix[11] -
matrix[5] * matrix[3] * matrix[10] -
matrix[9] * matrix[2] * matrix[7] +
matrix[9] * matrix[3] * matrix[6];
inv[7] = matrix[0] * matrix[6] * matrix[11] -
matrix[0] * matrix[7] * matrix[10] -
matrix[4] * matrix[2] * matrix[11] +
matrix[4] * matrix[3] * matrix[10] +
matrix[8] * matrix[2] * matrix[7] -
matrix[8] * matrix[3] * matrix[6];
inv[11] = -matrix[0] * matrix[5] * matrix[11] +
matrix[0] * matrix[7] * matrix[9] +
matrix[4] * matrix[1] * matrix[11] -
matrix[4] * matrix[3] * matrix[9] -
matrix[8] * matrix[1] * matrix[7] +
matrix[8] * matrix[3] * matrix[5];
inv[15] = matrix[0] * matrix[5] * matrix[10] -
matrix[0] * matrix[6] * matrix[9] -
matrix[4] * matrix[1] * matrix[10] +
matrix[4] * matrix[2] * matrix[9] +
matrix[8] * matrix[1] * matrix[6] -
matrix[8] * matrix[2] * matrix[5];
det = matrix[0] * inv[0] + matrix[1] * inv[4] + matrix[2] * inv[8] + matrix[3] * inv[12];
det = 1.0 / det;
for (i = 0; i < 16; i++)
inv[i] *= det;
return inv;
}
public static void cross(float[] r,float[] a, float[] b)
{
r[0]=a[1]*b[2]-a[2]*b[1];
r[1]=a[2]*b[0]-a[0]*b[2];
r[2]=a[0]*b[1]-a[1]*b[0];
}
public static float magnitute(float[] r){
return sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]);
}
public static void normalize(float[] r){
float len=magnitute(r);
r[0]/=len;
r[1]/=len;
r[2]/=len;
}
public static void scale(float[] a,float k){
a[0]*=k;
a[1]*=k;
a[2]*=k;
}
public static float dot(float[] a, float[] b){
return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
}
public static float[] diff(float[] a, float[] b){
float[] diff = new float[3];
diff[0]= a[0] - b[0];
diff[1]= a[1] - b[1];
diff[2]= a[2] - b[2];
return diff;
}
public static float clamp(float x, float min, float max)
{
if (x < min)
x = min;
else if (x > max)
x = max;
return x;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment