Skip to content

Instantly share code, notes, and snippets.

@AVGP
Created June 8, 2016 20:17
Show Gist options
  • Save AVGP/b091f23baf6399ffc388015b3d57cc71 to your computer and use it in GitHub Desktop.
Save AVGP/b091f23baf6399ffc388015b3d57cc71 to your computer and use it in GitHub Desktop.
Comparison: Repeat & scale image -- Canvas 2D vs. WebGL
<!doctype html>
<html>
<head>
</head>
<body>
<canvas width="1920" height="1080"></canvas>
<script>
var frameCount = 0, fps = 0, tStart = 0
var ctx = document.querySelector('canvas').getContext('2d')
var img = new Image()
img.src = 'logo.png'
img.onload = function() {
runTest()
}
function runTest() {
renderWithFPS()
}
function renderWithFPS() {
for(var i=0; i<1000; i++) {
var x = Math.random() * 1920, y = Math.random() * 1080, size = Math.random() * 512
ctx.drawImage(img, x - 90, y - 90, size, size) // draw & scale
}
if(Date.now() - tStart >= 1000) {
fps = frameCount
console.log(fps)
frameCount = 0
tStart = Date.now()
}
frameCount++
requestAnimationFrame(renderWithFPS)
}
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Shaderpad</title>
<style>
body {
width: 100%;
}
</style>
</head>
<body>
<canvas width="1920" height="1080"></canvas>
<div class="column" style="display: none">
<textarea id="vs" rows="50" cols="120">
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform float uXOffset;
uniform float uYOffset;
uniform float uScale;
varying highp vec2 vTextureCoord;
void main(void) {
vTextureCoord = aTextureCoord;
vec2 scaledPos = (aVertexPosition + vec2(uXOffset, uYOffset)) * uScale;
gl_Position = vec4(scaledPos, 0.0, 1.0);
}
</textarea>
<textarea id="fs" rows="50" cols="120">
precision highp float;
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</textarea>
</div>
<script>
var frameCount = 0, fps = 0, tStart = 0
// WebGL related code
var canvas = document.querySelector('canvas');
var gl = canvas.getContext('webgl');
var texture = gl.createTexture()
var vertices = [
0.1, 0.1,
-0.1, 0.1,
0.1, -0.1,
-0.1, -0.1
]
var texCoordinates = [
1.0, 0.0,
0.0, 0.0,
1.0, 1.0,
0.0, 1.0
]
var vertexPosBuffer = gl.createBuffer();
var texCoordBuffer = gl.createBuffer()
// Setup
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0, 0, canvas.width, canvas.height);
// filling in the vertices
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
vertexPosBuffer.itemSize = 2;
vertexPosBuffer.numItems = 4;
var vertexShaderSrc = document.getElementById("vs").value;
var fragmentShaderSrc = document.getElementById("fs").value;
var shaderProgram = gl.createProgram();
var vs = gl.createShader(gl.VERTEX_SHADER);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vs, vertexShaderSrc);
gl.compileShader(vs);
if(!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
alert('Vertex shader failed compilation:\n' + gl.getShaderInfoLog(vs))
console.log(gl.getShaderInfoLog(shaderProgram))
}
gl.shaderSource(fs, fragmentShaderSrc);
gl.compileShader(fs);
if(!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
alert('Fragment shader failed compilation:\n' + gl.getShaderInfoLog(fs))
console.log(gl.getShaderInfoLog(shaderProgram))
}
gl.attachShader(shaderProgram, vs);
gl.attachShader(shaderProgram, fs);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
// compiling, attaching, linking the shaders
function renderWithFPS() {
gl.clear(gl.COLOR_BUFFER_BIT);
// bind the uniforms
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uXOffset"), 0);
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uYOffset"), 0);
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uScale"), 1);
// Texture coordinate attribute
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
// Vertex position attribute
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexPosBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexPosBuffer.numItems);
for(var i=0; i<1000; i++) {
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uXOffset"), Math.random() * 2 - 1);
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uYOffset"), Math.random() * 2 - 1);
gl.uniform1f(gl.getUniformLocation(shaderProgram, "uScale"), Math.random() * 2);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexPosBuffer.numItems);
}
if(Date.now() - tStart >= 1000) {
fps = frameCount
console.log(fps)
frameCount = 0
tStart = Date.now()
}
frameCount++
requestAnimationFrame(renderWithFPS)
}
function runTest() {
var img = new Image()
img.onload = function() {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoordinates), gl.STATIC_DRAW);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);
renderWithFPS()
}
img.src = 'logo.png'
}
runTest()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment