Permalink
Browse files

Perlin is now working correctly. Added portal

  • Loading branch information...
1 parent 8e63244 commit 934699d0a6c12a1544858a94cbd984b7700b6fc7 @vjeux committed Jan 1, 2012
View
4 examples/perlin.rt
@@ -26,7 +26,7 @@ item
coords 0 0 0
rot 0 -90 0
pnoise 1
- pnoise_freq 1
+ pnoise_freq 0.1
pnoise_octave 8
pnoise_pers .3
}
@@ -39,7 +39,7 @@ item
coords 0 0 0
radius 30
pnoise 1
- pnoise_freq 1
+ pnoise_freq 0.1
pnoise_octave 8
pnoise_pers .3
}
View
94 examples/perlin_sphere.rt
@@ -0,0 +1,94 @@
+#####################
+# Global parameters #
+#####################
+
+global
+{
+ width 1024
+ height 500
+ l_color FFFFFF
+ l_intensity 40
+ highdef 1
+}
+
+###############
+# Camera info #
+###############
+
+eye
+{
+ coords -300 0 0
+ rot 0 5 0
+}
+
+##############
+# light list #
+##############
+
+light
+{
+ color ffffff
+ coords -100 0 50
+}
+
+##############
+# item list #
+##############
+
+### Left
+item
+{
+ type sphere
+ color 404040
+ color2 b57118
+ radius 30
+ brightness 20
+ coords 0 100 -25
+ pnoise 1
+ pnoise_freq 0.2
+ pnoise_octave 2
+ pnoise_pers 5
+ bump 100
+}
+
+# Center
+item
+{
+ type sphere
+ radius 30
+ pnoise 3
+ pnoise_octave 2
+ pnoise_freq 0.1
+ pnoise_pers 6.5
+ coords 0 0 -25
+}
+
+# Right
+item
+{
+ type sphere
+ color 3b2b15
+ color2 776144
+ radius 30
+ coords 0 -100 -25
+ pnoise 2
+ pnoise_octave 1
+ pnoise_freq 0.02
+ pnoise_pers 1
+ bump 150
+}
+
+# Floor
+item
+{
+ type plane
+ color 303030
+ color2 101010
+ coords 0 0 -60
+ pnoise 1
+ pnoise_freq .05
+ pnoise_pers .5
+ reflect 20
+ bump 100
+}
+
View
109 examples/portal.rt
@@ -0,0 +1,109 @@
+global {
+ width 600
+ height 480
+# highdef 0.25
+}
+eye {
+ coords -400 0 10
+}
+light {
+ color ffffff
+ coords 500 40 100
+}
+# Green Portals
+item {
+ type portal
+ color ff0000
+ coords 799.99 120 0
+ radius 100
+ rot 0 270 180
+ portal_id 0
+}
+item {
+ type portal
+ color ff0000
+ coords 799.99 -120 0
+ radius 100
+ rot 0 90 0
+ portal_id 0
+}
+# Blue portals
+item { # floor
+ type portal
+ color 0000ff
+ coords 400 0 -149.99
+ rot 0 0 180
+ radius 100
+ portal_id 1
+}
+item { # right
+ type portal
+ color 0000ff
+ coords 400 -199.99 0
+ rot 90 0 90
+ radius 100
+ portal_id 1
+}
+
+# Props
+
+item {
+ type sphere
+ color ff0000
+ coords 600 120 0
+ radius 20
+}
+item {
+ type sphere
+ color 0000ff
+ coords 410 -180 -100
+ radius 10
+}
+item {
+ type sphere
+ color 00ff00
+ coords 410 180 -100
+ radius 10
+}
+
+
+item { # floor
+ type plane
+ coords 0 0 -150
+ color ffff00
+ tex tex/white-tile-texture.jpg
+ tex_coef 8
+ tex_rep 1
+}
+item { # ceiling
+ type plane
+ color 00ffff
+ coords 0 0 150
+ tex tex/ceiling-textures.s600x600.jpg
+ tex_rep 1
+}
+item { # left wall
+ type plane
+ color ff00ff
+ coords 0 200 0
+ rot 90 0 90
+ tex tex/masonry-wall-texture.jpg
+ tex_coef 4
+ tex_rep 1
+}
+item { # Right wall
+ type plane
+ color 00ff00
+ coords 0 -200 0
+ rot 90 0 90
+ tex tex/brickwork-texture.jpg
+ tex_rep 1
+}
+item { # Back wall
+ type plane
+ color 00ff00
+ tex tex/arroway.de_concrete-06_s025-g050.png
+ tex_rep 1
+ coords 800 0 0
+ rot 0 90 0
+}
View
1 examples/reflect.rt
@@ -8,7 +8,6 @@ global
height 768
l_color AAAAAA
l_intensity 50
- light_collision 1
# max_reflect 200
highdef 1
}
View
2 examples/single_light.rt
@@ -69,7 +69,7 @@ item
group_id 1
pnoise 2
pnoise_octave 1
- pnoise_freq 0.1
+ pnoise_freq 0.01
pnoise_pers 1
bump 150
}
View
BIN lib/fork.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
8 raytracer.html
@@ -19,6 +19,7 @@
<div id="selection" class="well">
<h3>Ray Tracer by <a href="http://blog.vjeux.com/">Vjeux</a></h3>
+ <img src="images/examples/portal_small.png" title="portal"/>
<img src="images/examples/pokeball_small.png" title="pokeball"/>
<img src="images/examples/texturing_cut_small.png" title="texturing_cut"/>
<img src="images/examples/reflect_small.png" title="reflect"/>
@@ -30,14 +31,17 @@
<img src="images/examples/single_light_small.png" title="single_light"/>
<img src="images/examples/light_3_small.png" title="light_3"/>
<img src="images/examples/perlin_small.png" title="perlin"/>
- <img src="images/examples/sphere_checkerboard_small.png" title="sphere_checkerboard"/>
+ <img src="images/examples/perlin_sphere_small.png" title="perlin_sphere"/>
+<!--
+ <img src="images/examples/sphere_checkerboard_small.png" title="sphere_checkerboard"/>
<img src="images/examples/example_1_small.png" title="example_1"/>
<img src="images/examples/example_2_small.png" title="example_2"/>
<img src="images/examples/example_3_small.png" title="example_3"/>
<img src="images/examples/example_4_small.png" title="example_4"/>
- <img src="images/examples/example_5_small.png" title="example_5"/>
<img src="images/examples/example_6_small.png" title="example_6"/>
+-->
+ <img src="images/examples/example_5_small.png" title="example_5"/>
<img src="images/examples/example_7_small.png" title="example_7"/>
</div>
View
3 src/parser.coffee
@@ -25,7 +25,8 @@ class self.Parser
func: (input) -> +input[0]
fields: ['radius', 'width', 'height', 'checkerboard', 'distscreen', 'brightness',
'group_id', 'id', 'max_reflect', 'tex_rep', 'tex_coef', 'size_mul', 'reflect',
- 'l_intensity', 'pnoise', 'pnoise_octave', 'pnoise_freq', 'pnoise_pers', 'bump', 'opacity']
+ 'l_intensity', 'pnoise', 'pnoise_octave', 'pnoise_freq', 'pnoise_pers', 'bump',
+ 'opacity', 'portal_id']
}, { # Array of Number
func: (input) -> input.map (x) -> +x
fields: ['highdef', 'coords', 'limits', 'rot']
View
129 src/perlin.coffee
@@ -1,77 +1,84 @@
-saved = {}
-noise = (i, x, y, z) ->
- key = i + '|' + x + '|' + y + '|' + z
- val = saved[key]
- if val is undefined
- val = saved[key] = Math.random()
- val
+`
+// http://asserttrue.blogspot.com/2011/12/perlin-noise-in-javascript_31.html
+// This is a port of Ken Perlin's Java code. The
+// original Java code is at http://cs.nyu.edu/%7Eperlin/noise/.
+// Note that in this version, a number from 0 to 1 is returned.
+PerlinNoise = new function() {
-div = (a, b) ->
- Math.floor(a / b)
+this.noise = function(x, y, z) {
-clamp = (x, min, max) ->
- x = min if x < min
- x = max if x > max
- x
-
-interpolate = (a, b, x) ->
-# x = (1 - cos(x * Math.PI)) / 2
- a * (1 - x) + b * x
-
-interpolatedNoise = (i, x, y, z, freq) ->
- x += Math.pow 2, 30 # Hack to deal with negative modulo
- y += Math.pow 2, 30
- z += Math.pow 2, 30
-
- low_x = x - x % freq
- hig_x = low_x + freq
- alp_x = (x - low_x) / (hig_x - low_x)
- alp_x = alp_x * alp_x * (3 - 2 * alp_x)
+ var p = new Array(512)
+ var permutation = [ 151,160,137,91,90,15,
+ 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+ 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+ 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+ 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+ 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+ 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+ 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+ 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+ 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+ 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+ 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+ 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
+ ];
+ for (var i=0; i < 256 ; i++)
+ p[256+i] = p[i] = permutation[i];
- low_y = y - y % freq
- hig_y = low_y + freq
- alp_y = (y - low_y) / (hig_y - low_y)
- alp_y = alp_y * alp_y * (3 - 2 * alp_y)
+ var X = Math.floor(x) & 255, // FIND UNIT CUBE THAT
+ Y = Math.floor(y) & 255, // CONTAINS POINT.
+ Z = Math.floor(z) & 255;
+ x -= Math.floor(x); // FIND RELATIVE X,Y,Z
+ y -= Math.floor(y); // OF POINT IN CUBE.
+ z -= Math.floor(z);
+ var u = fade(x), // COMPUTE FADE CURVES
+ v = fade(y), // FOR EACH OF X,Y,Z.
+ w = fade(z);
+ var A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF
+ B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS,
- low_z = z - z % freq
- hig_z = low_z + freq
- alp_z = (z - low_z) / (hig_z - low_z)
- alp_z = alp_z * alp_z * (3 - 2 * alp_z)
+ return scale(lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
+ grad(p[BA ], x-1, y , z )), // BLENDED
+ lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS
+ grad(p[BB ], x-1, y-1, z ))),// FROM 8
+ lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS
+ grad(p[BA+1], x-1, y , z-1 )), // OF CUBE
+ lerp(u, grad(p[AB+1], x , y-1, z-1 ),
+ grad(p[BB+1], x-1, y-1, z-1 )))));
+ }
+ function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); }
+ function lerp( t, a, b) { return a + t * (b - a); }
+ function grad(hash, x, y, z) {
+ var h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
+ var u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
+ v = h<4 ? y : h==12||h==14 ? x : z;
+ return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+ }
+ function scale(n) { return n; /*return (1 + n)/2;*/ }
+}
+`
- v000 = noise i, low_x, low_y, low_z
- v001 = noise i, low_x, low_y, hig_z
- v010 = noise i, low_x, hig_y, low_z
- v011 = noise i, low_x, hig_y, hig_z
- v100 = noise i, hig_x, low_y, low_z
- v101 = noise i, hig_x, low_y, hig_z
- v110 = noise i, hig_x, hig_y, low_z
- v111 = noise i, hig_x, hig_y, hig_z
- i1 = interpolate v000, v001, alp_z
- i2 = interpolate v010, v011, alp_z
- i3 = interpolate v100, v101, alp_z
- i4 = interpolate v110, v111, alp_z
-
- j1 = interpolate i1, i2, alp_y
- j2 = interpolate i3, i4, alp_y
-
- interpolate j1, j2, alp_x
+clamp = (x, min, max) ->
+ return min if x < min
+ return max if x > max
+ x
self.perlin = (pos, id, persistence, octaves, frequence) ->
- pos = vec3.scale pos, 0.1 * frequence, vec3.create()
- total = 0
+ pos = vec3.scale pos, frequence, vec3.create()
+ noise = 0
frequency = 1
amplitude = 1
for i in [0 ... octaves]
- total += amplitude * interpolatedNoise i, pos[0], pos[1], pos[2], frequency
- frequency /= 2
+ noise += amplitude * PerlinNoise.noise pos[0] * frequency, pos[1] * frequency, pos[2] * frequency
+ frequency *= 2
amplitude *= persistence
if id == 2
- total *= 20
- total = total - Math.floor total
- else if id == 3
- total = Math.cos pos[1] + total
+ noise *= 20
+ noise = noise - Math.floor noise
+ if id == 3
+ noise = Math.cos noise
- total = clamp(total, -1, 1)
+ (clamp(noise, -1, 1) + 1) / 2
View
50 src/ray.coffee
@@ -88,6 +88,10 @@ objects.cylinder =
normal[2] = 0
normal
+objects.portal = copy objects.plane
+objects.portal.normal = (item, ray_, pos_) ->
+ [0, 0, 1]
+
inLimits = (limits, pos_) ->
limits[0] <= pos_[0] <= limits[1] and
@@ -102,10 +106,11 @@ isValid = (ray, distances, item, min_distance) ->
pos = vec3.create()
pos = vec3.add ray.origin, (vec3.scale ray.dir, distance, pos), pos
pos_ = mat4.multiplyVec3 item.inverse, pos, vec3.create()
+
if inLimits item.limits, pos_
return [pos, pos_, distance]
- [null, null, null]
+ [null, null, null, null]
intersectItem = (item, ray, min_distance) ->
ray_ = # underscore means in the object's coordinates
@@ -119,15 +124,8 @@ intersectItem = (item, ray, min_distance) ->
color = item.color
opacity = item.opacity
-
- if item.checkerboard?
- pos2d = obj.pos2d item, pos_, 500, 500
- if (mod(pos2d[0] / item.checkerboard, 1) > 0.5) == (mod(pos2d[1] / item.checkerboard, 1) > 0.5)
- color = item.color2
-
- if item.pnoise > 0
- alpha = perlin pos_, item.pnoise, item.pnoise_pers, item.pnoise_octave, item.pnoise_freq
- color = vec3.mix item.color, item.color2, alpha
+ reflect = item.reflect
+ dir = ray.dir
if item.tex?
texture = textures[item.tex]
@@ -141,13 +139,31 @@ intersectItem = (item, ray, min_distance) ->
opacity *= texture.data[idx + 3] / 255
color = [texture.data[idx] / 255, texture.data[idx + 1] / 255, texture.data[idx + 2] / 255]
+ if item.checkerboard?
+ pos2d = obj.pos2d item, pos_, 500, 500
+ if (mod(pos2d[0] / item.checkerboard, 1) > 0.5) == (mod(pos2d[1] / item.checkerboard, 1) > 0.5)
+ color = item.color2
+
+ if item.pnoise > 0
+ alpha = perlin pos_, item.pnoise, item.pnoise_pers, item.pnoise_octave, item.pnoise_freq
+ color = vec3.mix color, item.color2, alpha
+
+ if item.type == 'portal'
+ dist = item.radius2 - (pos_[0] * pos_[0] + 2 * pos_[1] * pos_[1])
+ return if dist < 0
+
+ opacity *= 1 - Math.exp -dist / 2000
+ opacity = 1 - opacity
+ pos = mat4.multiplyVec3 item.other.transform, pos_, vec3.create()
+ dir = vec3.normalize mat4.multiplyDelta3 item.other.transform, vec3.create ray_.dir
+
normal = obj.normal item, ray_, pos_
normal = vec3.normalize mat4.multiplyDelta3 item.transform, vec3.create normal
if opacity == 0
return
- {distance, pos, normal, color, item, opacity}
+ {distance, pos, normal, color, item, opacity, reflect, dir}
intersect = (ray, min_distance=Infinity) ->
min_isect = null
@@ -199,17 +215,17 @@ launchRay = (ray, count) ->
if isect
color = lightning isect
- if isect.opacity < 1
+ if count > 0 and isect.opacity < 1
ray2 =
- origin: (vec3.add isect.pos, (vec3.scale ray.dir, epsilon, vec3.create()), vec3.create())
- dir: (vec3.normalize vec3.create ray.dir)
- color = vec3.mix color, (launchRay ray2, count), 1 - isect.opacity
+ origin: (vec3.add isect.pos, (vec3.scale isect.dir, epsilon, vec3.create()), vec3.create())
+ dir: (vec3.normalize vec3.create isect.dir)
+ color = vec3.mix color, (launchRay ray2, count - 1), 1 - isect.opacity
- if count > 0 and isect.item.reflect > 0
+ if count > 0 and isect.reflect > 0
ray2 =
origin: (vec3.add isect.pos, (vec3.scale isect.normal, epsilon, vec3.create()), vec3.create())
dir: (vec3.normalize vec3.reflect ray.dir, (vec3.normalize isect.normal), vec3.create())
- color = vec3.mix color, (launchRay ray2, count - 1), isect.item.reflect
+ color = vec3.mix color, (launchRay ray2, count - 1), isect.reflect
color
View
14 src/trace.coffee
@@ -12,11 +12,15 @@ $ ->
lineNumbers: true
$('#selection img').click ->
- title = $(this).attr('title') + '.rt'
- $.get 'examples/' + title, (file) ->
- editor.setValue '# ' + title + '\n\n' + file.trim()
-
- $('#selection img').eq(0).click()
+ title = $(this).attr('title')
+ document.location.hash = title
+ $.get 'examples/' + title + '.rt', (file) ->
+ editor.setValue '# ' + title + '.rt\n\n' + file.trim()
+
+ default_img = $('#selection [title=' + document.location.hash[1...] + ']')
+ if default_img.length == 0
+ default_img = $('#selection img')
+ default_img.eq(0).click()
$('#stop').click ->
worker.terminate() if worker
View
22 src/worker.coffee
@@ -1,8 +1,4 @@
-
-importScripts('glmatrix.js', 'parser.js', 'ray.js', 'perlin.js');
-
-log = (x...) -> postMessage ['log', x...]
-copy = (obj) ->
+self.copy = (obj) ->
if Array.isArray obj
obj.slice()
else if obj instanceof Object and not (obj instanceof Function)
@@ -13,8 +9,12 @@ copy = (obj) ->
else
obj
+importScripts('glmatrix.js', 'parser.js', 'ray.js', 'perlin.js');
+
+self.log = (x...) -> postMessage ['log', x...]
+
scene = null
-textures = {}
+self.textures = {}
textures_remaining = 0
@onmessage = (data: [type, value]) ->
@@ -42,6 +42,7 @@ textures_remaining = 0
realH: scene.global.height}]
groups = {}
+ portals = {}
for light in scene.light || []
light.coords ?= [0, 0, 0]
@@ -78,6 +79,15 @@ textures_remaining = 0
groups[item.group_id] ?= []
groups[item.group_id].push item
+ if item.portal_id?
+ if item.portal_id not of portals
+ portals[item.portal_id] = []
+ portals[item.portal_id].push item
+
+ for id, two_portals of portals
+ two_portals[0].other = two_portals[1]
+ two_portals[1].other = two_portals[0]
+
for group in scene.group || []
group.size_mul ?= 1
group.rot = vec3.scale (group.rot ? [0, 0, 0]), Math.PI / 180

0 comments on commit 934699d

Please sign in to comment.