Created
November 27, 2012 11:39
-
-
Save williame/4153824 to your computer and use it in GitHub Desktop.
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 Sphere(iterations) { | |
// returns an object with a 'draw' method | |
// we cache ready-built spheres | |
if(!Sphere.spheres) | |
Sphere.spheres = []; | |
if(iterations in Sphere.spheres) | |
return Sphere.spheres[iterations]; | |
// we have to create it... | |
var vertices = [], | |
vIndex = {}, | |
indices = [], | |
addTriangle = function(a,b,c) { | |
indices.push(a); | |
indices.push(b); | |
indices.push(c); | |
}, | |
addVertex = function(v) { | |
if(!(v in vIndex)) { | |
vIndex[v] = vertices.length/3; | |
vertices.push(v[0]); | |
vertices.push(v[1]); | |
vertices.push(v[2]); | |
} | |
return vIndex[v]; | |
}, | |
halfway = function(a,b) { | |
a = [vertices[a*3],vertices[a*3+1],vertices[a*3+2]]; | |
b = [vertices[b*3],vertices[b*3+1],vertices[b*3+2]]; | |
return addVertex(vec3_normalise(vec3_add(a,vec3_scale(vec3_sub(b,a),0.5)))); | |
}, | |
bisect = function(a,b,c,iteration) { | |
var ab = halfway(a,b), | |
ac = halfway(a,c), | |
bc = halfway(b,c), | |
func = iteration==iterations? addTriangle: bisect; | |
func(a,ab,ac,iteration+1); | |
func(b,bc,ab,iteration+1); | |
func(c,ac,bc,iteration+1); | |
func(ab,bc,ac,iteration+1); | |
}, | |
top = addVertex([0,-1,0]), | |
bottom = addVertex([0,1,0]), | |
leftFront = addVertex(vec3_normalise([-1,0,-1])), | |
leftBack = addVertex(vec3_normalise([-1,0,1])), | |
rightFront = addVertex(vec3_normalise([1,0,-1])), | |
rightBack = addVertex(vec3_normalise([1,0,1])); | |
bisect(leftFront,top,rightFront,0); | |
bisect(rightFront,bottom,leftFront,0); | |
bisect(leftBack,top,leftFront,0); | |
bisect(bottom,leftBack,leftFront,0); | |
bisect(rightFront,top,rightBack,0); | |
bisect(bottom,rightFront,rightBack,0); | |
bisect(rightBack,top,leftBack,0); | |
bisect(bottom,rightBack,leftBack,0); | |
// and now all the code below is to actually draw it... | |
// do we have to create our (shared) program for rendering the spheres? | |
if(!Sphere.program) { | |
Sphere.program = createProgram( | |
"precision mediump float;\n"+ | |
"uniform mat4 mvMatrix, pMatrix, nMatrix;\n"+ | |
"attribute vec3 vertex;\n"+ | |
"varying vec3 lighting;\n"+ | |
"void main() {\n"+ | |
" vec3 normal = vertex;\n"+ | |
" gl_Position = pMatrix * mvMatrix * vec4(vertex,1.0);\n"+ | |
" vec3 ambientLight = vec3(0.6,0.6,0.6);\n"+ | |
" vec3 lightColour = vec3(0.8,0.9,0.75);\n"+ | |
" vec3 lightDir = vec3(0.85,0.8,0.75);\n"+ | |
" vec3 transformed = normalize(nMatrix * vec4(normal,1.0)).xyz;\n"+ | |
" float directional = clamp(dot(transformed,lightDir),0.0,1.0);\n"+ | |
" lighting = ambientLight + (lightColour*directional);\n"+ | |
"}", | |
"precision mediump float;\n"+ | |
"uniform vec4 colour;\n"+ | |
"varying vec3 lighting;\n"+ | |
"void main() {\n"+ | |
" gl_FragColor = vec4(lighting*colour.rgb,colour.a);\n"+ | |
"}"); | |
Sphere.program.vertex = gl.getAttribLocation(Sphere.program,"vertex"); | |
Sphere.program.nMatrix = gl.getUniformLocation(Sphere.program,"nMatrix"); | |
Sphere.program.mvMatrix = gl.getUniformLocation(Sphere.program,"mvMatrix"); | |
Sphere.program.pMatrix = gl.getUniformLocation(Sphere.program,"pMatrix"); | |
Sphere.program.colour = gl.getUniformLocation(Sphere.program,"colour"); | |
} | |
// return an object that actually can be drawn | |
var self = { | |
vVbo: gl.createBuffer(), | |
iVbo: gl.createBuffer(), | |
indexCount: indices.length, | |
draw: function(pMatrix,mvMatrix,sphere,colour,invert) { | |
var frontFace = gl.getParameter(gl.FRONT_FACE); | |
gl.frontFace(invert? gl.CCW: gl.CW); // we support inverting so you can draw the sphere as seen from the inside | |
mvMatrix = mat4_multiply(mvMatrix,mat4_translation(sphere)); | |
mvMatrix = mat4_multiply(mvMatrix,mat4_scale(sphere[3])); | |
gl.useProgram(Sphere.program); | |
gl.uniformMatrix4fv(Sphere.program.pMatrix,false,pMatrix); | |
gl.uniformMatrix4fv(Sphere.program.mvMatrix,false,mvMatrix); | |
gl.uniformMatrix4fv(Sphere.program.nMatrix,false,mat4_transpose(mvMatrix)); | |
gl.uniform4fv(Sphere.program.colour,colour||[1,1,1,1]); | |
gl.enableVertexAttribArray(Sphere.program.vertex); | |
gl.bindBuffer(gl.ARRAY_BUFFER,self.vVbo); | |
gl.vertexAttribPointer(Sphere.program.vertex,3,gl.FLOAT,false,3*4,0); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,self.iVbo); | |
gl.drawElements(gl.TRIANGLES,self.indexCount,gl.UNSIGNED_SHORT,0); | |
gl.disableVertexAttribArray(Sphere.program.vertex); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null); | |
gl.bindBuffer(gl.ARRAY_BUFFER,null); | |
gl.useProgram(null); | |
gl.frontFace(frontFace); | |
}, | |
}; | |
gl.bindBuffer(gl.ARRAY_BUFFER,self.vVbo); | |
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertices),gl.STATIC_DRAW); | |
gl.bindBuffer(gl.ARRAY_BUFFER,null); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,self.iVbo); | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indices),gl.STATIC_DRAW); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null); | |
Sphere.spheres[iterations] = self; | |
return self; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment