Created
March 8, 2014 16:39
-
-
Save Akiyah/9434634 to your computer and use it in GitHub Desktop.
forked: レイトレーシング練習
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html { | |
height:100%; | |
} | |
body { | |
margin: 0; | |
padding: 0; | |
background: gray; | |
width:100%; | |
height:100%; | |
overflow : hidden; | |
} | |
canvas { | |
width:100%; | |
height:100%; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id="canvas" width="400"></canvas> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sum(p, q) { | |
return [p[0]+q[0], p[1]+q[1], p[2]+q[2]]; | |
} | |
function multi(p, m) { | |
return [p[0]*m, p[1]*m, p[2]*m]; | |
} | |
function innerProduct(p, q) { | |
return p[0]*q[0] + p[1]*q[1] + p[2]*q[2]; | |
} | |
function norm(p) { | |
return Math.sqrt(innerProduct(p, p)); | |
} | |
function normalization(p) { | |
return multi(p, 1/norm(p)); | |
} | |
function cos(v, w) { | |
return innerProduct(v, w)/norm(v)/norm(w); | |
} | |
function diffuseReflection(normal, light) { | |
return Math.max(-cos(light, normal), 0); | |
} | |
function specularReflection(normal, light, eye, n) { | |
var m = -2 * innerProduct(light,normal)/innerProduct(normal,normal) | |
var light1 = sum(light, multi(normal, m)); | |
var c = -cos(light1, eye); | |
if (c < 0) { | |
return 0; | |
} | |
return Math.pow(c, n); | |
} | |
function init() { | |
var canvas = document.getElementById('canvas'); | |
var context = canvas.getContext("2d"); | |
var WIDTH = canvas.width; | |
var HEIGHT = canvas.height; | |
var r = 200; | |
var r2 = 20; | |
var x0 = 200; | |
var y0 = 200; | |
function mapxy(f) { | |
var data = []; | |
for (var x = 0; x < WIDTH; x++) { | |
data[x] = []; | |
for (var y = 0; y < HEIGHT; y++) { | |
var i = (y * WIDTH + x) * 4; | |
data[x][y] = f(x, y, i); | |
} | |
} | |
return data; | |
} | |
var imageData = context.getImageData(0, 0, WIDTH, HEIGHT); | |
var data = imageData.data; | |
var bump = mapxy(function(x, y, i) { | |
//var x = x1 - x0; // 右が大きくなる方向 | |
//var y = y0 - y1; // 上が大きくなる方向 | |
var lx = 27*3; | |
var ly = 17*3; | |
var dx = 5*3; | |
var dy = 5*3; | |
var dz = 8*3; | |
var x2 = x - lx; | |
var y2 = y - ly; | |
if (Math.abs(y2) < ly && Math.abs(x2) < lx ) { | |
if (Math.abs(y2) < ly-dy && Math.abs(x2) < lx-dx ) { | |
return [0,0,1,10]; | |
} | |
if (0 < y2 && 0 <= dx*(y2-ly)-dy*(x2-lx) && 0 <= dx*(y2-ly)-dy*(-x2-lx)) { | |
return [0,dz,dx, 10]; | |
} | |
if (y2 < 0 && 0 <= dx*(-y2-ly)-dy*(x2-lx) && 0 <= dx*(-y2-ly)-dy*(-x2-lx)) { | |
return [0,-dz,dx, 10]; | |
} | |
if (0 < x2 && dx*(y2-ly)-dy*(x2-lx) < 0 && dx*(-y2-ly)-dy*(x2-lx) < 0) { | |
return [dz,0,dy, 10]; | |
} | |
if (x2 < 0 && dx*(y2-ly)-dy*(-x2-lx) < 0 && dx*(-y2-ly)-dy*(-x2-lx) < 0) { | |
return [-dz,0,dy, 10]; | |
} | |
} | |
/* | |
if (y > r2) { | |
return null; | |
} | |
if (y > 0) { | |
if (Math.abs(x) < r-r2) { | |
var z = Math.sqrt(r2*r2 - y*y); | |
return {p: [x,y,z], n: [0,y,z]}; | |
} | |
var x2 = x > 0 ? x-(r-r2) : x+(r-r2); | |
if (x2*x2+y*y < r2*r2) { | |
var z = Math.sqrt(r2*r2 - (x2*x2 + y*y)); | |
return {p: [x,y,z], n: [x2,y,z]}; | |
} | |
return null; | |
} | |
if (x*x + y*y < r*r) { | |
var normal; | |
if (x*x + y*y < (r-r2)*(r-r2)) { | |
return {p: [x,y,r2], n: [0,0,1]}; | |
} else { | |
var x2 = x - x / Math.sqrt(x*x+y*y) * (r-r2); | |
var y2 = y - y / Math.sqrt(x*x+y*y) * (r-r2); | |
var z2 = Math.sqrt(r2*r2 - (x2*x2 + y2*y2)); | |
return {p: [x,y,z2], n: [x2,y2,z2]}; | |
} | |
return null; | |
} | |
*/ | |
return null; | |
}); | |
// ゆらす | |
/* | |
var heights = mapxy(function(x, y, i) { | |
var d = heights[x][y]; | |
if (d) { | |
var n = normalization(d.n); | |
var m = normalization([Math.cos((x+y)/30)/10,Math.cos((x-2*y)/30)/10,1]); | |
d.n = normalization(sum(n, m)) | |
} | |
return d; | |
}); | |
*/ | |
// 複製 | |
var bump = mapxy(function(x, y, i) { | |
if (x < 5 || y < 5) { | |
return null; | |
} | |
return bump[(x-5) % (27*3*2+10)][(y-5) % (17*3*2+10)]; | |
}); | |
function draw(light) { | |
var eye_position = [0, 0, 100]; | |
mapxy(function(x, y, i) { | |
var d = bump[x][y]; | |
if (d) { | |
var position = [x, y, d[3]]; | |
var normal = d; | |
var eye = sum(position, multi(eye_position, -1)); | |
var c0 = 1; | |
var c1 = diffuseReflection(normal, light); | |
var c2 = specularReflection(normal, light, eye, 10); | |
data[i+0] = (c0 + c1 + c2)/3* 0xa0; | |
data[i+1] = (c0 + c1 + c2)/3* 0x64; | |
data[i+2] = (c0 + c1 + c2)/3* 0x13; | |
data[i+3] = 255; | |
} | |
}); | |
context.putImageData(imageData, 0, 0); | |
} | |
var i = 0; | |
setInterval(function() { | |
var y = Math.sin(-i / 180 * Math.PI * 5) * 10; | |
draw([-1,y,-1]); | |
i++; | |
}, 100); | |
$("body").mousemove(function(e) { | |
//console.log(e); | |
//draw([-1,y,-1]); | |
}); | |
} | |
$(function() { | |
var obj = $('#canvas'); | |
$('#canvas').attr({width:obj.width(), height:obj.height()}); | |
console.log(obj); | |
init(); | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment