Skip to content

Instantly share code, notes, and snippets.

@sp4cemonkey
Last active December 17, 2015 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sp4cemonkey/5605858 to your computer and use it in GitHub Desktop.
Save sp4cemonkey/5605858 to your computer and use it in GitHub Desktop.
--# Main
-- RayTracer 3Balls
-- Use this function to perform your initial setup
function setup()
displayMode(FULLSCREEN)
myMesh = mesh()
--myMesh.shader = shader("Documents:ray")
myMesh.shader = shader(rayShader.vertexShader, rayShader.fragmentShader)
aVPosBuffer = myMesh:buffer("aVertexPosition")
aPPosBuffer = myMesh:buffer("aPlotPosition")
aVPosBuffer:resize(6)
aPPosBuffer:resize(6)
size = 1.0 -- 1.0 is fullscreen
aVPosBuffer[1] = vec2(size,size)
aVPosBuffer[2] = vec2(-size,size)
aVPosBuffer[3] = vec2(size,-size)
aVPosBuffer[4] = vec2(size,-size)
aVPosBuffer[5] = vec2(-size,size)
aVPosBuffer[6] = vec2(-size,-size)
t=0
s1 = vec3(0,0,0)
s2 = vec3(0,0,0)
s3 = vec3(0,0,0)
sphere = Primitive:Sphere(3)
end
function calcCamera()
cameraFrom = vec3(math.sin(t*0.4)*28, math.sin(t*0.13)*5+5, math.cos(t*0.4)*28)
cameraTo = vec3(0,0,0)
cameraPersp = 6
up = vec3(0,1,0)
cameraDir = (cameraTo - cameraFrom):normalize()
cameraLeft = cameraDir:cross(up):normalize()
cameraUp = cameraLeft:cross(cameraDir):normalize()
cameraCenter = cameraFrom + cameraDir * cameraPersp
ratio = WIDTH/HEIGHT
cameraTopLeft = cameraCenter + cameraUp + cameraLeft * ratio
cameraBotLeft = cameraCenter - cameraUp + cameraLeft * ratio
cameraTopRight = cameraCenter + cameraUp - cameraLeft * ratio
cameraBotRight = cameraCenter - cameraUp - cameraLeft * ratio
aPPosBuffer[1] = cameraTopLeft
aPPosBuffer[2] = cameraTopRight
aPPosBuffer[3] = cameraBotLeft
aPPosBuffer[4] = cameraBotLeft
aPPosBuffer[5] = cameraTopRight
aPPosBuffer[6] = cameraBotRight
end
function calcBalls()
s1.x = math.sin(t * 1.1) * 1.5
s1.y = math.cos(t * 1.3) * 1.5
s1.z = math.sin(t + math.pi/3) * 1.5
s2.x = math.cos(t * 1.2) * 1.5
s2.y = math.sin(t * 1.4) * 1.5
s2.z = math.sin(t*1.25 - math.pi/3) * 1.5
s3.x = math.cos(t * 1.15) * 1.5
s3.y = math.sin(t * 1.37) * 1.5
s3.z = math.sin(t*1.27) * 1.5
end
-- This function gets called once every frame
function draw()
noSmooth()
strokeWidth(0)
calcBalls()
calcCamera()
myMesh.shader.cameraPos = cameraFrom
myMesh.shader.sphere1Center = s1
myMesh.shader.sphere2Center = s2
myMesh.shader.sphere3Center = s3
background(0, 0, 0)
camera(cameraFrom.x, cameraFrom.y, cameraFrom.z, cameraTo.x, cameraTo.y, cameraTo.z)
perspective(19)
translate(s1.x, s1.y, s1.z)
fill(0,0,255,255)
sphere:draw()
resetMatrix()
translate(s2.x, s2.y, s2.z)
fill(255,0,0,255)
sphere:draw()
resetMatrix()
translate(s3.x, s3.y, s3.z)
fill(0,255,0,255)
sphere:draw()
resetMatrix()
translate(0, -2.7, 0)
rotate(90, 1, 0, 0)
fill(255,255,0,255)
ellipse(0, 0, 10.95464)
myMesh:draw()
t = t + 0.03
if t> math.pi * 200 then
t = t - math.pi * 200
end
--output.clear()
--print(1/DeltaTime)
end
rayShader = {
vertexShader = [[
attribute vec2 aVertexPosition;
attribute vec3 aPlotPosition;
varying vec3 vPosition;
void main(void)
{
gl_Position = vec4(aVertexPosition, 1.0, 1.0);
vPosition = aPlotPosition;
}
]],
fragmentShader = [[
#extension GL_EXT_shader_framebuffer_fetch : require
precision highp float;
const vec3 lightDir = vec3(0.577350269, 0.577350269, -0.577350269);
varying vec3 vPosition;
uniform vec3 cameraPos;
uniform vec3 sphere1Center;
uniform vec3 sphere2Center;
uniform vec3 sphere3Center;
uniform lowp sampler2D texture;
bool intersectSphere(vec3 center, vec3 lStart, vec3 lDir, out float dist) {
vec3 c = center - lStart;
float b = dot(lDir, c);
float d = b*b - dot(c, c) + 1.0;
if (d < 0.0) {
dist = 10000.0;
return false;
}
dist = b - sqrt(d);
if (dist < 0.0) {
dist = 10000.0;
return false;
}
return true;
}
vec3 lightAt(vec3 N, vec3 V, vec3 color, vec3 p) {
vec3 L = lightDir;
vec3 R = reflect(-L, N);
float spec = max(dot(R,V), 0.0);
float diff = max(dot(L,N), 0.0);
float c, d;
bool h1, h2, h3;
if (spec > 0.0 || diff > 0.0) {
h1 = intersectSphere(sphere1Center, p, L, d);
h2 = intersectSphere(sphere2Center, p, L, d);
h3 = intersectSphere(sphere3Center, p, L, d);
if (h1 || h2 || h3) {
c = 0.3;
}
else {
c = 0.3 + 0.4 * pow(spec, 30.0) + 0.7 * diff;
}
}
else {
c = 0.3;
}
if (c > 1.0) {
return mix(color, vec3(1.6, 1.6, 1.6), c - 1.0);
}
return c * color;
}
bool intersectWorld(vec3 lStart, vec3 lDir, out vec3 pos, out vec3 normal, out vec3 color) {
float d1, d2, d3;
bool h1, h2, h3;
h1 = intersectSphere(sphere1Center, lStart, lDir, d1);
h2 = intersectSphere(sphere2Center, lStart, lDir, d2);
h3 = intersectSphere(sphere3Center, lStart, lDir, d3);
if (h1 && d1 < d2 && d1 < d3) {
pos = lStart + d1 * lDir;
normal = pos - sphere1Center;
color = vec3(0.0, 0.0, 0.9);
}
else if (h2 && d2 < d3) {
pos = lStart + d2 * lDir;
normal = pos - sphere2Center;
color = vec3(0.9, 0.0, 0.0);
}
else if (h3) {
pos = lStart + d3 * lDir;
normal = pos - sphere3Center;
color = vec3(0.0, 0.9, 0.0);
}
else if (lDir.y < -0.01) {
pos = lStart + ((lStart.y + 2.7) / -lDir.y) * lDir;
if ((pos.x + pos.z) > 20.0) {
return false;
}
if (pos.x*pos.x + pos.z*pos.z > 30.0) {
return false;
}
normal = vec3(0.0, 1.0, 0.0);
if (fract(pos.x / 5.0) > 0.5 == fract(pos.z / 5.0) > 0.5) {
color = vec3(1.0);
}
else {
color = vec3(0.0);
}
}
else {
return false;
}
return true;
}
void main(void)
{
vec3 cameraDir = normalize(vPosition - cameraPos);
float d;
vec3 p1, norm, p2;
vec3 col, colT, colM, col3;
lowp vec4 curCol = gl_LastFragData[0];
bool hit;
hit = false;
if (curCol.r > 0.1 && curCol.g > 0.1) {
p1 = cameraPos + ((cameraPos.y + 2.7) / -cameraDir.y) * cameraDir;
norm = vec3(0.0, 1.0, 0.0);
if (fract(p1.x / 5.0) > 0.5 == fract(p1.z / 5.0) > 0.5) {
colT = vec3(1.0);
}
else {
colT = vec3(0.0);
}
hit = true; //intersectWorld(cameraPos, cameraDir, p1, norm, colT);
}
else if (curCol.b > 0.1) {
intersectSphere(sphere1Center, cameraPos, cameraDir, d);
p1 = cameraPos + d * cameraDir;
norm = p1 - sphere1Center;
colT = vec3(0.0, 0.0, 0.9);
hit = true;
}
else if (curCol.r > 0.1) {
intersectSphere(sphere2Center, cameraPos, cameraDir, d);
p1 = cameraPos + d * cameraDir;
norm = p1 - sphere2Center;
colT = vec3(0.9, 0.0, 0.0);
hit = true;
}
else if (curCol.g > 0.1) {
intersectSphere(sphere3Center, cameraPos, cameraDir, d);
p1 = cameraPos + d * cameraDir;
norm = p1 - sphere3Center;
colT = vec3(0.0, 0.9, 0.0);
hit = true;
}
if (hit) {
col = lightAt(norm, -cameraDir, colT, p1);
colM = (colT + vec3(0.7)) / 1.7;
cameraDir = reflect(cameraDir, norm);
if (intersectWorld(p1, cameraDir, p2, norm, colT)) {
col += lightAt(norm, -cameraDir, colT, p2) * colM;
colM *= (colT + vec3(0.7)) / 1.7;
cameraDir = reflect(cameraDir, norm);
if (intersectWorld(p2, cameraDir, p1, norm, colT)) {
col += lightAt(norm, -cameraDir, colT, p1) * colM;
}
}
gl_FragColor = vec4(col, 1.0);
}
else {
discard;
//gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}]]
}
--# Primitive
Primitive = class()
--primitves gives basic mesh building for cubes and isospheres
--triangles are wound consistently to avoid gl_facing issues
function Primitive:Cube()
m = mesh()
local vertices = {
vec3(-0.5, -0.5, 0.5), -- Left bottom front
vec3( 0.5, -0.5, 0.5), -- Right bottom front
vec3( 0.5, 0.5, 0.5), -- Right top front
vec3(-0.5, 0.5, 0.5), -- Left top front
vec3(-0.5, -0.5, -0.5), -- Left bottom back
vec3( 0.5, -0.5, -0.5), -- Right bottom back
vec3( 0.5, 0.5, -0.5), -- Right top back
vec3(-0.5, 0.5, -0.5), -- Left top back
}
-- now construct a cube out of the vertices above
m.vertices = {
-- Front
vertices[1], vertices[2], vertices[3],
vertices[1], vertices[3], vertices[4],
-- Right
vertices[2], vertices[6], vertices[7],
vertices[2], vertices[7], vertices[3],
-- Back
vertices[6], vertices[5], vertices[8],
vertices[6], vertices[8], vertices[7],
-- Left
vertices[5], vertices[1], vertices[4],
vertices[5], vertices[4], vertices[8],
-- Top
vertices[4], vertices[3], vertices[7],
vertices[4], vertices[7], vertices[8],
-- Bottom
vertices[5], vertices[6], vertices[2],
vertices[5], vertices[2], vertices[1],
}
return m
end
function Primitive:Sphere(depth)
m = mesh()
local t = (1 + math.sqrt(5)) / 2
--all the vertices of an icosohedron
local vertices = {
vec3(-1 , t, 0):normalize(),
vec3(1 , t, 0):normalize(),
vec3(-1 , -t, 0):normalize(),
vec3(1 , -t, 0):normalize(),
vec3(0 , -1, t):normalize(),
vec3(0 , 1, t):normalize(),
vec3(0 , -1, -t):normalize(),
vec3(0 , 1, -t):normalize(),
vec3(t , 0, -1):normalize(),
vec3(t , 0, 1):normalize(),
vec3(-t , 0, -1):normalize(),
vec3(-t , 0, 1):normalize()
}
--20 faces
icovertices = {
-- 5 faces around point 0
vertices[1], vertices[12], vertices[6],
vertices[1], vertices[6], vertices[2],
vertices[1], vertices[2], vertices[8],
vertices[1], vertices[8], vertices[11],
vertices[1], vertices[11], vertices[12],
-- 5 adjacent faces
vertices[2], vertices[6], vertices[10],
vertices[6], vertices[12], vertices[5],
vertices[12], vertices[11], vertices[3],
vertices[11], vertices[8], vertices[7],
vertices[8], vertices[2], vertices[9],
-- 5 faces around point 3
vertices[4], vertices[10], vertices[5],
vertices[4], vertices[5], vertices[3],
vertices[4], vertices[3], vertices[7],
vertices[4], vertices[7], vertices[9],
vertices[4], vertices[9], vertices[10],
--5 adjacent faces
vertices[5], vertices[10], vertices[6],
vertices[3], vertices[5], vertices[12],
vertices[7], vertices[3], vertices[11],
vertices[9], vertices[7], vertices[8],
vertices[10], vertices[9], vertices[2]
}
local finalVertices = {}
--divide each triangle into 4 sub triangles to make an isosphere
--this can be repeated (based on depth) for higher res spheres
for j=1,depth do
for i=1,#icovertices/3 do
midpoint1 = ((icovertices[i*3-2] + icovertices[i*3-1])/2):normalize()
midpoint2 = ((icovertices[i*3-1] + icovertices[i*3])/2):normalize()
midpoint3 = ((icovertices[i*3] + icovertices[i*3-2])/2):normalize()
--triangle 1
table.insert(finalVertices,icovertices[i*3-2])
table.insert(finalVertices,midpoint1)
table.insert(finalVertices,midpoint3)
--triangle 2
table.insert(finalVertices,midpoint1)
table.insert(finalVertices,icovertices[i*3-1])
table.insert(finalVertices,midpoint2)
--triangle 3
table.insert(finalVertices,midpoint2)
table.insert(finalVertices,icovertices[i*3])
table.insert(finalVertices,midpoint3)
--triangle 4
table.insert(finalVertices,midpoint1)
table.insert(finalVertices,midpoint2)
table.insert(finalVertices,midpoint3)
end
icovertices = finalVertices
finalVertices = {}
end
m.vertices = icovertices
return m
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment