Created
January 27, 2022 09:02
-
-
Save keeyanajones/cf5362748c35b2cab325631d77f18b6a to your computer and use it in GitHub Desktop.
Webgl Demo
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
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>WebGL Demo</title> | |
<link rel="stylesheet" href="webgl.css" type="text/css"> | |
<script src="webgl-demo.js" defer></script> | |
</head> | |
<body> | |
<canvas id="canvas"></canvas> | |
</body> | |
<!-- vertex shader --> | |
<script id="vertex-shader-3d" type="x-shader/x-vertex"> | |
attribute vec4 a_position; | |
uniform mat4 u_matrix; | |
varying vec3 v_normal; | |
void main() { | |
// Multiply the position by the matrix. | |
gl_Position = u_matrix * a_position; | |
// Pass a normal. Since the positions | |
// centered around the origin we can just | |
// pass the position | |
v_normal = normalize(a_position.xyz); | |
} | |
</script> | |
<!-- fragment shader --> | |
<script id="fragment-shader-3d" type="x-shader/x-fragment"> | |
precision mediump float; | |
// Passed in from the vertex shader. | |
varying vec3 v_normal; | |
// The texture. | |
uniform samplerCube u_texture; | |
void main() { | |
gl_FragColor = textureCube(u_texture, normalize(v_normal)); | |
} | |
</script> | |
<!-- | |
for most samples webgl-utils only provides shader compiling/linking and | |
canvas resizing because why clutter the examples with code that's the same in every sample. | |
See https://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html | |
and https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html | |
for webgl-utils, m3, m4, and webgl-lessons-ui. | |
--> | |
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script> | |
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script> | |
</html> | |
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
"use strict"; | |
function main() { | |
// Get A WebGL context | |
/** @type {HTMLCanvasElement} */ | |
var canvas = document.querySelector("#canvas"); | |
var gl = canvas.getContext("webgl"); | |
if (!gl) { | |
return; | |
} | |
// setup GLSL program | |
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]); | |
// look up where the vertex data needs to go. | |
var positionLocation = gl.getAttribLocation(program, "a_position"); | |
// lookup uniforms | |
var matrixLocation = gl.getUniformLocation(program, "u_matrix"); | |
var textureLocation = gl.getUniformLocation(program, "u_texture"); | |
// Create a buffer for positions | |
var positionBuffer = gl.createBuffer(); | |
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
// Put the positions in the buffer | |
setGeometry(gl); | |
// Create a texture. | |
var texture = gl.createTexture(); | |
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); | |
// Get A 2D context | |
/** @type {Canvas2DRenderingContext} */ | |
const ctx = document.createElement("canvas").getContext("2d"); | |
ctx.canvas.width = 128; | |
ctx.canvas.height = 128; | |
const faceInfos = [ | |
{ target: gl.TEXTURE_CUBE_MAP_POSITIVE_X, faceColor: '#F00', textColor: '#0FF', text: '+X' }, | |
{ target: gl.TEXTURE_CUBE_MAP_NEGATIVE_X, faceColor: '#FF0', textColor: '#00F', text: '-X' }, | |
{ target: gl.TEXTURE_CUBE_MAP_POSITIVE_Y, faceColor: '#0F0', textColor: '#F0F', text: '+Y' }, | |
{ target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, faceColor: '#0FF', textColor: '#F00', text: '-Y' }, | |
{ target: gl.TEXTURE_CUBE_MAP_POSITIVE_Z, faceColor: '#00F', textColor: '#FF0', text: '+Z' }, | |
{ target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, faceColor: '#F0F', textColor: '#0F0', text: '-Z' }, | |
]; | |
faceInfos.forEach((faceInfo) => { | |
const {target, faceColor, textColor, text} = faceInfo; | |
generateFace(ctx, faceColor, textColor, text); | |
// Upload the canvas to the cubemap face. | |
const level = 0; | |
const internalFormat = gl.RGBA; | |
const format = gl.RGBA; | |
const type = gl.UNSIGNED_BYTE; | |
gl.texImage2D(target, level, internalFormat, format, type, ctx.canvas); | |
}); | |
gl.generateMipmap(gl.TEXTURE_CUBE_MAP); | |
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); | |
function radToDeg(r) { | |
return r * 180 / Math.PI; | |
} | |
function degToRad(d) { | |
return d * Math.PI / 180; | |
} | |
var fieldOfViewRadians = degToRad(60); | |
var modelXRotationRadians = degToRad(0); | |
var modelYRotationRadians = degToRad(0); | |
// Get the starting time. | |
var then = 0; | |
requestAnimationFrame(drawScene); | |
// Draw the scene. | |
function drawScene(time) { | |
// convert to seconds | |
time *= 0.001; | |
// Subtract the previous time from the current time | |
var deltaTime = time - then; | |
// Remember the current time for the next frame. | |
then = time; | |
webglUtils.resizeCanvasToDisplaySize(gl.canvas); | |
// Tell WebGL how to convert from clip space to pixels | |
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); | |
gl.enable(gl.CULL_FACE); | |
gl.enable(gl.DEPTH_TEST); | |
// Animate the rotation | |
modelYRotationRadians += -0.7 * deltaTime; | |
modelXRotationRadians += -0.4 * deltaTime; | |
// Clear the canvas AND the depth buffer. | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
// Tell it to use our program (pair of shaders) | |
gl.useProgram(program); | |
// Turn on the position attribute | |
gl.enableVertexAttribArray(positionLocation); | |
// Bind the position buffer. | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
// Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) | |
var size = 3; // 3 components per iteration | |
var type = gl.FLOAT; // the data is 32bit floats | |
var normalize = false; // don't normalize the data | |
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position | |
var offset = 0; // start at the beginning of the buffer | |
gl.vertexAttribPointer( | |
positionLocation, size, type, normalize, stride, offset); | |
// Compute the projection matrix | |
var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; | |
var projectionMatrix = | |
m4.perspective(fieldOfViewRadians, aspect, 1, 2000); | |
var cameraPosition = [0, 0, 2]; | |
var up = [0, 1, 0]; | |
var target = [0, 0, 0]; | |
// Compute the camera's matrix using look at. | |
var cameraMatrix = m4.lookAt(cameraPosition, target, up); | |
// Make a view matrix from the camera matrix. | |
var viewMatrix = m4.inverse(cameraMatrix); | |
var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix); | |
var matrix = m4.xRotate(viewProjectionMatrix, modelXRotationRadians); | |
matrix = m4.yRotate(matrix, modelYRotationRadians); | |
// Set the matrix. | |
gl.uniformMatrix4fv(matrixLocation, false, matrix); | |
// Tell the shader to use texture unit 0 for u_texture | |
gl.uniform1i(textureLocation, 0); | |
// Draw the geometry. | |
gl.drawArrays(gl.TRIANGLES, 0, 6 * 6); | |
requestAnimationFrame(drawScene); | |
} | |
} | |
function generateFace(ctx, faceColor, textColor, text) { | |
const {width, height} = ctx.canvas; | |
ctx.fillStyle = faceColor; | |
ctx.fillRect(0, 0, width, height); | |
ctx.font = `${width * 0.7}px sans-serif`; | |
ctx.textAlign = 'center'; | |
ctx.textBaseline = 'middle'; | |
ctx.fillStyle = textColor; | |
ctx.fillText(text, width / 2, height / 2); | |
} | |
// Fill the buffer with the values that define a cube. | |
function setGeometry(gl) { | |
var positions = new Float32Array( | |
[ | |
-0.5, -0.5, -0.5, | |
-0.5, 0.5, -0.5, | |
0.5, -0.5, -0.5, | |
-0.5, 0.5, -0.5, | |
0.5, 0.5, -0.5, | |
0.5, -0.5, -0.5, | |
-0.5, -0.5, 0.5, | |
0.5, -0.5, 0.5, | |
-0.5, 0.5, 0.5, | |
-0.5, 0.5, 0.5, | |
0.5, -0.5, 0.5, | |
0.5, 0.5, 0.5, | |
-0.5, 0.5, -0.5, | |
-0.5, 0.5, 0.5, | |
0.5, 0.5, -0.5, | |
-0.5, 0.5, 0.5, | |
0.5, 0.5, 0.5, | |
0.5, 0.5, -0.5, | |
-0.5, -0.5, -0.5, | |
0.5, -0.5, -0.5, | |
-0.5, -0.5, 0.5, | |
-0.5, -0.5, 0.5, | |
0.5, -0.5, -0.5, | |
0.5, -0.5, 0.5, | |
-0.5, -0.5, -0.5, | |
-0.5, -0.5, 0.5, | |
-0.5, 0.5, -0.5, | |
-0.5, -0.5, 0.5, | |
-0.5, 0.5, 0.5, | |
-0.5, 0.5, -0.5, | |
0.5, -0.5, -0.5, | |
0.5, 0.5, -0.5, | |
0.5, -0.5, 0.5, | |
0.5, -0.5, 0.5, | |
0.5, 0.5, -0.5, | |
0.5, 0.5, 0.5, | |
]); | |
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); | |
} | |
main(); |
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
@import url("https://webglfundamentals.org/webgl/resources/webgl-tutorials.css"); | |
body { | |
margin: 0; | |
} | |
canvas { | |
width: 100vw; | |
height: 100vh; | |
display: block; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just saw someone poking around so I gave it a whirl ¯_(ツ)_/¯