Last active
July 14, 2022 17:52
-
-
Save highfestiva/3cbd9ab9eedea3aa51270a8e5a93f27b to your computer and use it in GitHub Desktop.
Rotating WebGL Donut
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> | |
<head> | |
</head> | |
<body> | |
<canvas style="width:100%; height:100%;"></canvas> | |
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script> | |
<script type="text/javascript"> | |
const o = { | |
sectionVerts: 30, | |
sections: 60, | |
innerRad: 0.8, | |
outerRad: 2, | |
makeVerts() { | |
this.vertices = []; | |
this.indices = []; | |
this.normals = []; | |
this.texCoords = []; | |
for (let sectionVert = 0; sectionVert <= this.sectionVerts; ++sectionVert) { | |
const v = sectionVert / this.sectionVerts; | |
const slice_angle = v * 2 * Math.PI; | |
const cos_slices = Math.cos(slice_angle); | |
const sin_slices = Math.sin(slice_angle); | |
const slice_rad = this.outerRad + this.innerRad * cos_slices; | |
for (let section = 0; section <= this.sections; ++section) { | |
// x=(R+r·cos(v))cos(w) | |
// y=(R+r·cos(v))sin(w) | |
// z=r.sin(v) | |
const u = section / this.sections; | |
const loop_angle = u * 2 * Math.PI; | |
const cos_loops = Math.cos(loop_angle); | |
const sin_loops = Math.sin(loop_angle); | |
const x = slice_rad * cos_loops; | |
const y = slice_rad * sin_loops; | |
const z = this.innerRad * sin_slices; | |
this.vertices.push(x, y, z); | |
this.normals.push( | |
cos_loops * cos_slices, | |
sin_loops * cos_slices, | |
sin_slices); | |
this.texCoords.push(u); | |
this.texCoords.push(v); | |
} | |
} | |
// 0 1 2 3 4 5 | |
// 6 7 8 9 10 11 | |
// 12 13 14 15 16 17 | |
const vertsPerSlice = this.sections + 1; | |
for (let i = 0; i < this.sectionVerts; ++i) { | |
let v1 = i * vertsPerSlice; | |
let v2 = v1 + vertsPerSlice; | |
for (let j = 0; j < this.sections; ++j) { | |
this.indices.push(v1); | |
this.indices.push(v1 + 1); | |
this.indices.push(v2); | |
this.indices.push(v2); | |
this.indices.push(v1 + 1); | |
this.indices.push(v2 + 1); | |
v1 += 1; | |
v2 += 1; | |
} | |
} | |
}, | |
}; | |
o.makeVerts(); | |
const c = document.querySelector('canvas'); | |
c.width = c.clientWidth; | |
c.height = c.clientHeight; | |
const gl = c.getContext('webgl'); | |
const m4 = twgl.m4; | |
const vertexShader = ` | |
attribute vec4 position; | |
attribute vec3 normal; | |
attribute vec2 texcoord; | |
uniform mat4 u_matrix; | |
varying vec3 v_normal; | |
void main() { | |
gl_Position = u_matrix * (position + vec4(normal, 0)); | |
v_normal = normal; // just for testing | |
//v_normal = vec3(texcoord, 0); // comment in to see texcoords | |
gl_PointSize = 3.0; | |
} | |
`; | |
const fragmentShader = ` | |
precision highp float; | |
varying vec3 v_normal; | |
void main() { | |
gl_FragColor = vec4(v_normal * 0.5 + 0.5, 1); | |
} | |
`; | |
const programInfo = twgl.createProgramInfo(gl, [vertexShader, fragmentShader]); | |
const bufferInfo = twgl.createBufferInfoFromArrays(gl, { | |
position: o.vertices, | |
normal: o.normals, | |
texcoord: o.texCoords, | |
indices: o.indices, | |
}); | |
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo); | |
gl.useProgram(programInfo.program); | |
function render(time) { | |
gl.enable(gl.DEPTH_TEST); | |
gl.enable(gl.CULL_FACE); | |
let mat = m4.perspective( | |
45 * Math.PI / 180, // fov | |
2, // aspect | |
0.1, // near | |
100, // far | |
); | |
mat = m4.translate(mat, [0, 0, -10]); | |
mat = m4.rotateY(mat, Math.sin(time * 0.00083) * 0.9); | |
mat = m4.rotateX(mat, Math.cos(time * 0.00053) * 0.5); | |
mat = m4.rotateZ(mat, time * 0.00227); | |
twgl.setUniforms(programInfo, { u_matrix: mat }); | |
twgl.drawBufferInfo(gl, bufferInfo); | |
//twgl.drawBufferInfo(gl, bufferInfo, gl.POINTS); | |
requestAnimationFrame(render); | |
} | |
requestAnimationFrame(render); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment