Last active
February 9, 2019 06:10
-
-
Save reccanti/d4345f868487c6388ddc1c9b4d1684ed to your computer and use it in GitHub Desktop.
Example from the first tutorial on WebGL Fundamentals https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>WebGL Source</title> | |
<style> | |
html { | |
height: 100%; | |
} | |
body { | |
background-color: #DDD; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
height: 100%; | |
} | |
canvas { | |
width: 500px; | |
height: 500px; | |
background-color: white; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="webgl" width="500" height="500"></canvas> | |
<script src="./webglFundamentals1.js"></script> | |
</body> | |
</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"; | |
const glsl = x => x; | |
function createShader(gl, type, source) { | |
const shader = gl.createShader(type); | |
gl.shaderSource(shader, source); | |
gl.compileShader(shader); | |
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); | |
if (success) { | |
return shader; | |
} | |
console.log(gl.getShaderInfoLog(shader)); | |
gl.deleteShader(shader); | |
} | |
function createProgram(gl, vertexShader, fragmentShader) { | |
const program = gl.createProgram(); | |
gl.attachShader(program, vertexShader); | |
gl.attachShader(program, fragmentShader); | |
gl.linkProgram(program); | |
const success = gl.getProgramParameter(program, gl.LINK_STATUS); | |
if (success) { | |
return program; | |
} | |
console.log(gl.getProgramInfoLog(program)); | |
gl.deleteProgram(program); | |
} | |
function main() { | |
// Get A WebGL context | |
const canvas = document.getElementById("webgl"); | |
const gl = canvas.getContext("webgl"); | |
if (!gl) { | |
return; | |
} | |
// Define the shader source | |
const vertexShaderSource = glsl` | |
attribute vec2 a_position; | |
uniform vec2 u_resolution; | |
void main() { | |
// convert the position from pixels 0.0 to 1.0 | |
vec2 zeroToOne = a_position / u_resolution; | |
// convert from 0->1 to 0->2 | |
vec2 zeroToTwo = zeroToOne * 2.0; | |
// convert from 0->2 to -1->+1 (clipspace) | |
vec2 clipSpace = zeroToTwo - 1.0; | |
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); | |
} | |
`; | |
const fragmentShaderSource = glsl` | |
// fragment shaders don't have a default precision | |
// so we need to pick one. mediump is a good default | |
precision mediump float; | |
uniform vec4 u_color; | |
void main() { | |
// gl_FragColor is a special variable a fragment | |
// shader is responsible for setting | |
gl_FragColor = u_color; | |
} | |
`; | |
// create GLSL shaders, upload the GLSL source, compile the shaders | |
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); | |
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource); | |
// Link the two shaders into a program | |
const program = createProgram(gl, vertexShader, fragmentShader); | |
// look up where the vertex data needs to go. | |
const positionAttributeLocation = gl.getAttribLocation(program, "a_position"); | |
const resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); | |
const colorUniformLocation = gl.getUniformLocation(program, "u_color"); | |
// Create a buffer and put three 2d clip space points in it | |
const positionBuffer = gl.createBuffer(); | |
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
var positions = [ | |
10, 20, | |
80, 20, | |
10, 30, | |
10, 30, | |
80, 20, | |
80, 30 | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); | |
// CODE ABOVE THIS LINE IS INITIALIZATION CODE | |
// CODE BELOW THIS LINE IS RENDERING CODE | |
// 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.viewport(0, 0, gl.canvas.width, gl.canvas.height); | |
// Clear the canvas | |
gl.clearColor(0, 0, 0, 0); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
// Tell it to use our program (pair of shaders) | |
gl.useProgram(program); | |
// Turn on the attribute | |
gl.enableVertexAttribArray(positionAttributeLocation); | |
gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height); | |
// Bind the position buffer. | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
function randomInt(range) { | |
return Math.floor(Math.random() * range); | |
} | |
function setRectangle(gl, x, y, width, height) { | |
const x1 = x; | |
const x2 = x + width; | |
const y1 = y; | |
const y2 = y + height; | |
// NOTE: gl.bufferData(gl.ARRAY_BUFFER, ...) will affect | |
// whatever buffer is bound to the `ARRAY_BUFFER` bind point | |
// but so far we only have one buffer. If we had more than one | |
// buffer we'd want to bind that buffer to `ARRAY_BUFFER` first. | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ | |
x1, y1, | |
x2, y1, | |
x1, y2, | |
x1, y2, | |
x2, y1, | |
x2, y2 | |
]), gl.STATIC_DRAW); | |
} | |
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) | |
const size = 2; // 2 components per iteration | |
const type = gl.FLOAT; // the data is 32bit floats | |
const normalize = false; // don't normalize the data | |
const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position | |
const offset = 0; // start at the beginning of the buffer | |
gl.vertexAttribPointer( | |
positionAttributeLocation, size, type, normalize, stride, offset); | |
for (let ii = 0; ii < 50; ++ii) { | |
// Setup a random rectangle | |
// This will write to positionBuffer because | |
// its the last thing we bound on the ARRAY_BUFFER | |
// bind point | |
setRectangle(gl, randomInt(gl.canvas.width), randomInt(gl.canvas.width), randomInt(gl.canvas.height), randomInt(gl.canvas.height)); | |
// set a random color | |
gl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1); | |
// draw the rectangle | |
gl.drawArrays(gl.TRIANGLES, 0, 6); | |
} | |
console.log(gl.canvas.width); | |
// // draw | |
// const primitiveType = gl.TRIANGLES; | |
// const drawoffset = 0; | |
// const count = 6; | |
// gl.drawArrays(primitiveType, drawoffset, count); | |
} | |
window.addEventListener("load", main); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment