<h1 id="DemoTitle">
Photo warping with WebGL
</h1>
<h2>click and drag</h2>
<div id="DemoContent">
<div style='width:600px; height:600px'>
<div style='position: relative'>
<!-- WebGL canvas -->
<canvas style='position: absolute' id='webglcanvas' width='600' height='600'></canvas>
<!-- notation cavas -->
<canvas style='position: absolute' id='2dcanvas' width='600' height='600'></canvas>
</div>
</div>
<div style="text-align:center">
<button id="openphoto1" onclick="OpenPhoto1()">Open a photo</button>
<span id="openphoto2" style="display:none">Pick a photo: <input type="file" id="files" /></span> <br />
<button onclick="undo()">Undo</button>
<button onclick="reset()">Start over</button>
<button onclick="save()">Save</button>
</div>
</div>
<div id="ErrorMessage" style="display:none">
<div class="heading">Sorry!</div>
This demonstation requires a browser with WebGL support.
</div>
<div id="log"></div>
<div id="Details">
<div class="heading">WebGL 101</div>
To render the warped photo above, a mesh of 400 triangle coordinates, a photo, a vertex &
fragment shader program and uniform points are uploaded to the GPU using WebGL.<br />
<br />
<!-- The show uniform points checkbox -->
<label><input type="checkbox" name="showUniforms" id="showUniforms" onchange="renderer.changeMode();renderer.render()" />Show uniform points</label>
<div>
<label><input type="radio" name="rendertype" id="renderLines" onclick="renderer.render()" />Show triangle mesh</label>
<label><input type="radio" name="rendertype" id="renderTriangles" onclick="renderer.render()" checked />Show rendered photo</label>
</div>
<br />
When you click and drag on the photo, new uniform points are set...
CSS
/* Prevent text selection from being displayed when the user drags out of the canvas */
*::selection {
background:transparent;
}
#DemoContent {
margin-top:10px;
}
#DemoContent {
width:600px;
margin-left:auto;
margin-right:auto;
margin-top:10px;
}
#Details {
margin-top:10px;
margin-bottom:10px;
padding:20px;
border-radius:4px;
}
body {
-ms-user-select: none; /* turn off user selection */
font-size: 12pt;
}
canvas {
-ms-touch-action: none; /* turn off panning and zooming */
}
.heading
{
font-size: 20pt;
font-weight: normal;
}
#ErrorMessage {
position:absolute;
top:100px;
left:20%;
right:20%;
background-color:lightcoral;
padding:20px;
border-radius:4px;
}
JavaScript
'use strict';
window.onload = main; // Startup
// Point object - converts incoming values to a -1 to 1 range).
function Point(x, y) {
if (x<-1) x = -1;
if (y<-1) y = -1;
if (x>1) x = 1;
if (y>1) y = 1;
this.x = x;
this.y = y;
}
// A new mouse manipulation.
function Move(point) {
this.point1 = new Point(point.x, point.y);
this.point2 = new Point(point.x, point.y);
this.move = function (point) {
this.point2.x = point.x;
this.point2.y = point.y;
}
}
var renderer = new function () {
var gl; // Handle to the context.
var lineprogram; // Handle to GLSL program that draws lines.
var pictureprogram; // Handle to GLSL program that draws a picture.
this.texCoordLocation; // Location of the texture for the picture fragment shader.
this.texCoordLocation2; // Location of the texture for the line fragment shader.
this.texCoordBuffer; // The buffer for the texture for the picture fragment shader.
this.texCoordBuffer2; // The buffer for the texture for the line fragment shader.
var moves = [];
var MAXMOVES = 10;
var currentMove = 0;
var resolution = 300; // Resolution of the mesh.
// First init called by main().
// Initialize the gl context variable.
this.init = function () {
// Get a context from our canvas object with id = "webglcanvas".
var canvas = document.getElementById("webglcanvas");
try {
// Get the context into a local gl and and a public gl.
// Use preserveDrawingBuffer:true to keep the drawing buffer after presentation
var gl = this.gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
}
catch (e) {
// Fail quietly
}
// If we can't get a WebGL context (no WebGL support), then display an error message.
if (!this.gl) {
...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.