Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Here's a list of WebGL resources that will help you learn and create great 2D and 3D graphics.
Microsoft websites
Demos
- Lookaround A cool Three.js based demo where you can view a waterfront boardwalk in 360 degrees.
- Flight to Everest Find your base camp, check ice flows, and scale heights with this 3D demo.
- Warp The full version of the trimmed down demo presented here.
Reference content
- WebGL API reference Reference pages for the WebGL API supported by Internet Explorer 11.
- GLSL errors pages for the WebGL and GLSL features supported by IE11.
Third-party websites
Learning sites
- Babylon.js A 3D engine based on WebGL and Javascript that includes demos, tutorials, and a drag and drop sandbox to try out your code.
- Learning WebGL This site has 16 lessons to take you through initial flat graphics creation to a number of advanced techniques.
- Learning Three.js A blog with a series of small tutorials and demos using Three.js.
- WebGL Academy Build and test small projects.
- Hyper-Fast Web Graphics with WebGL A talk by Frank Olivier of Microsoft presented at the 2013 //build/ conference.
- WebGL Earth This tutorial takes you through building a 3D virtual globe.
- HTML5 Rocks Tutorials - WebGL fundamentals Another WebGL tutorial.
- Interactive 3D graphics at Udacity An entertaining and deep class on 3D graphics featuring Three.js.
Libraries
- Three.js One of the most widely used general purpose WebGL libraries.
- GLMatrix A commonly used library to simplify using matrices.
- PhiloGL A framework for game development, data visualization, and creative coding.
- GLGE: WebGL for the lazy A general purpose library that abstracts graphics and 3D concepts.
- Babylon.js A general purpose library with an emphasis on gaming.
The full example
For this WebGL discussion, we've used snippets of code from a larger example. Here's the complete code listing. There are two files, demo.js and default.html. We've combined the Cascading Style Sheets (CSS) portion with the HTML file, while it's a separate file in the Warp sample.
This is the default.html file
<!DOCTYPE html>
<html>
<head>
<!-- Copyright � Microsoft Corporation. All Rights Reserved. -->
<!-- Demo Author: Frank Olivier, Microsoft Corporation -->
<!-- Updates by Jay Munro -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Photo warping with WebGL</title>
<style>
/* 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;
}
</style>
</head>
<body>
<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 on the GPU...<br /><br />
<div class="heading">Vertex shader</div>
<img src="vertex.png"/><br />
...The GPU runs the vertex shader below to distort the mesh using the uniform points...<br /><br />
<pre id="vertexshadersource"></pre>
<br />
<div class="heading">Fragment shader</div>
<img src="fragment.png"/><br />
...and the fragment shader paints photo pixels using the distorted mesh.<br /><br />
<pre id="fragmentshadersource"></pre>
<br />
<!-- For more information on WebGL, see <a href="http://docs.webplatform.org/wiki/webgl">webplatform.org</a>.</div> -->
</div>
<script type="text/javascript" src="demo.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
// outgoing coordinate
varying vec2 v_texCoord;
// incoming coordinate (point)
attribute vec2 a_texCoord;
// maximum number of changes to grid
#define MAXPOINTS 10
uniform vec2 p1[MAXPOINTS]; // Where the drag started
uniform vec2 p2[MAXPOINTS]; // Where the drag ended
void main() {
v_texCoord = a_texCoord;
// Set up position variable with current coordinate normalized from 0 - 1 to -1 to 1 range
vec2 position = a_texCoord * 2.0 - 1.0;
for (int i = 0; i < MAXPOINTS; i++) // loop through
{
float dragdistance = distance(p1[i], p2[i]); // Calculate the distance between two start and end of mouse drag for each of the drags
float mydistance = distance(p1[i], position); // Calculate the distance between the start of the mouse drag and the last position
if (mydistance < dragdistance)
{
vec2 maxdistort = (p2[i] - p1[i]) / 4.0; // only affect vertices within 4 x the drag distance (
float normalizeddistance = mydistance / dragdistance;
float normalizedimpact = (cos(normalizeddistance*3.14159265359)+1.0)/2.0;
position += (maxdistort * normalizedimpact);
}
}
// gl_Position always specifies where to render this vector
gl_Position = vec4(position, 0.0, 1.0); // x,y,z,
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
// uniform to use for texture
uniform sampler2D u_image;
// Output of the vertex shader
varying vec2 v_texCoord;
void main() {
// gl_FragColor always specifies the color to make the current pixel
gl_FragColor = texture2D(u_image, v_texCoord);
}
</script>
<!-- fragment shader -->
<script id="red" type="x-shader/x-fragment">
precision mediump float;
varying vec2 v_texCoord;
// Set a solid color for the grid
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
</script>
</body>
</html>
This is the demo.js file
'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 = new Array;
var MAXMOVES = 10;
var currentMove = 0;
var resolution = 20; // 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("experimental-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) {
document.getElementById("ErrorMessage").style.display = "block";
return;
}
try {
// Load the GLSL source written in the HTML file.
// Create a program with the two shaders
this.lineprogram = loadProgram(gl, getShader(gl, "2d-vertex-shader"), getShader(gl, "red"));
// Tell webGL to use this program
gl.useProgram(this.lineprogram);
// Look up where the vertex data needs to go.
this.texCoordLocation2 = gl.getAttribLocation(this.lineprogram, "a_texCoord");
// Provide texture coordinates for the rectangle.
this.texCoordBuffer2 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer2);
// Create a buffer and set it use the array set up above.
// Set it to be modified once, use many.
// createRedGrid sets up the vector array itself.
gl.bufferData(gl.ARRAY_BUFFER, createRedGrid(), gl.STATIC_DRAW); // Fill buffer data
// Turns on the vertex attributes in the GPU program.
gl.enableVertexAttribArray(this.texCoordLocation2);
// Set up the data format for the vertex array - set to points (x/y).
// Use floats.
gl.vertexAttribPointer(this.texCoordLocation2, 2, gl.FLOAT, false, 0, 0);
}
catch (e) {
// Display the fail on the screen if the shaders/program fail.
log('shader fail');
return;
}
try {
var vertexshader = getShader(gl, "2d-vertex-shader");
var fragmentshader = getShader(gl, "2d-fragment-shader");
this.pictureprogram = loadProgram(gl, vertexshader, fragmentshader);
gl.useProgram(this.pictureprogram);
// Put the shader source into the <divs>.
document.getElementById("vertexshadersource").innerText = gl.getShaderSource(vertexshader);
document.getElementById("fragmentshadersource").innerText = gl.getShaderSource(fragmentshader);
// Look up where the vertex data needs to go.
this.texCoordLocation = gl.getAttribLocation(this.pictureprogram, "a_texCoord");
// Provide texture coordinates for the rectangle.
this.texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);
// createImageGrid sets up the vector array itself
gl.bufferData(gl.ARRAY_BUFFER, createImageGrid(), gl.STATIC_DRAW); // Fill buffer data
gl.vertexAttribPointer(this.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.texCoordLocation);
// Set up uniforms variables (image).
this.pictureprogram.u_image = gl.getUniformLocation(this.pictureprogram, "u_image");
// Set the texture to use.
gl.uniform1i(this.pictureprogram.u_image, 0);
}
catch (e) {
log('shader fail');
return;
}
this.loadImage();
}
// Load a default image.
this.loadImage = function () {
var image = new Image();
image.onload = function () {
renderer.loadImage2(image);
}
image.src = "photos/demophoto.jpg"; // Default image
}
// load a the user's image.
this.loadImageX = function (dataURL) {
var image = new Image();
image.onload = function () {
renderer.loadImage2(image);
}
image.src = dataURL;
}
// This function does the heavy lifting of creating the texture from the image.
this.loadImage2 = function (image) {
// Convert the image to a square image via the temporary 2d canvas.
var canvas = document.getElementById("2dcanvas");
var ctx = canvas.getContext("2d");
var canvHeight = document.getElementById("2dcanvas").height;
var x = 0;
var y = 0;
var xx = canvHeight;
var yy = canvHeight;
ctx.clearRect(0, 0, canvHeight, canvHeight);
// If image isn't square, adjust width, height, and origin so it's centered.
if (image.width < image.height) {
// Change origin and dimensions if the image isn't square.
// Change x, xx
xx = image.width / image.height * canvHeight;
x = (canvHeight - xx) / 2;
}
if (image.width > image.height) {
// Change y, yy
yy = image.height / image.width * canvHeight;
y = (canvHeight - yy) / 2;
}
// Put the image on the canvas, scaled using xx & yy.
ctx.drawImage(image, 0, 0, image.width, image.height, x, y, xx, yy);
var gl = this.gl;
// Create a texture object that will contain the image.
var texture = gl.createTexture();
// Bind the texture the target (TEXTURE_2D) of the active texture unit.
gl.bindTexture(gl.TEXTURE_2D, texture);
// Flip the image's Y axis to match the WebGL texture coordinate space.
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// Upload the resized canvas image into the texture.
// Note: a canvas is used here but can be replaced by an image object.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
ctx.clearRect(0, 0, canvHeight, canvHeight);
this.reset();
}
// This code checks the Show uniform points checkbox and changes the mode and initializes the canvas.
this.modeOff = 0;
this.modeHint = 1;
this.modeHint2 = 2;
this.modeUniform = 3;
// Modes tell the app to show uniforms or not
this.canvasMode = this.modeHint;
this.changeMode = function () {
if (document.getElementById("showUniforms").checked) {
this.canvasMode = this.modeUniform;
}
else {
this.canvasMode = this.modeOff;
var canvas = document.getElementById("2dcanvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}
this.render = function () {
var gl = this.gl;
// Create two arrays to hold start and end point uniforms
var p1 = new Float32Array(MAXMOVES * 2); //x and y
var p2 = new Float32Array(MAXMOVES * 2); //x and y
// Set up the arrays of points
{
var index = 0;
for (var i = 0; i < MAXMOVES; i++) {
// Working values
var x1, y1, x2, y2;
if (moves[i]) {
x1 = moves[i].point1.x;
y1 = moves[i].point1.y;
x2 = moves[i].point2.x;
y2 = moves[i].point2.y;
}
else {
x1 = 1;
y1 = 1;
x2 = 0.9999999;
y2 = 0.9999999;
}
p1[index] = x1;
p1[index + 1] = y1;
p2[index] = x2;
p2[index + 1] = y2;
index += 2;
}
}
// Clear color buffer and set it to light gray
gl.clearColor(1.0, 1.0, 1.0, 0.5);
gl.clear(this.gl.COLOR_BUFFER_BIT);
// This draws either the grid or the photo for stretching
if (document.getElementById("renderLines").checked)
{
gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer2);
gl.useProgram(this.lineprogram);
gl.uniform2fv(gl.getUniformLocation(this.lineprogram, "p1"), p1);
gl.uniform2fv(gl.getUniformLocation(this.lineprogram, "p2"), p2);
gl.vertexAttribPointer(this.texCoordLocation2, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.texCoordLocation2);
gl.drawArrays(gl.LINES, 0, resolution * resolution * 10);
}
else
{
gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);
gl.useProgram(this.pictureprogram);
gl.uniform2fv(gl.getUniformLocation(this.pictureprogram, "p1"), p1);
gl.uniform2fv(gl.getUniformLocation(this.pictureprogram, "p2"), p2);
gl.vertexAttribPointer(this.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.texCoordLocation);
gl.drawArrays(gl.TRIANGLES, 0, resolution * resolution * 2 * 3);
}
// Draw uniform points
if (this.canvasMode == this.modeUniform) {
var canvas = document.getElementById("2dcanvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < MAXMOVES; i++) {
if (moves[i]) {
var x1 = (moves[i].point1.x + 1) * canvas.width / 2;
var y1 = (-moves[i].point1.y + 1) * canvas.height / 2;
var x2 = (moves[i].point2.x + 1) * canvas.width / 2;
var y2 = (-moves[i].point2.y + 1) * canvas.height / 2;
// The raio is used here to show where the pixel started and ended
var ratio = 0.3;
x2 = x1 + (x2 - x1) * ratio;
y2 = y1 + (y2 - y1) * ratio;
var radius = 6;
ctx.beginPath(); // Start a fresh path
// Create a 2D gradient
var grd = ctx.createLinearGradient(x1, y1, x2, y2);
grd.addColorStop(0, 'pink'); // Set one side to pink
grd.addColorStop(1, 'red'); // The other side to red
ctx.setLineDash([5, 5]); // Use a dotted line
ctx.lineWidth = radius / 2;
ctx.moveTo(x1, y1); // Create a line from start to end poing
ctx.lineTo(x2, y2);
ctx.strokeStyle = grd;
ctx.stroke();
ctx.beginPath(); // Start a new path for pink dot
ctx.arc(x1, y1, radius, 0, 2 * Math.PI, false); // full circle (2*pi)
ctx.fillStyle = 'pink';
ctx.fill();
ctx.beginPath(); // Start a new path for red dot
ctx.arc(x2, y2, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
}
}
}
}
// (point) is where the mouse was clicked
this.newMove = function(point) // Where the warp starts (-1 to 1 range)
{
var move = new Move(point);
// Adds move to beginning of moves array (pushes onto array)
moves.unshift(move);
return move;
}
this.reset = function () {
moves = [];
this.render();
}
this.undo = function () {
// Removes the first element in moves array (pops off array)
moves.shift();
this.render();
}
this.save = function () {
// First create a dataURL string from the canvas in jpeg format.
var dataURL = document.getElementById("webglcanvas").toDataURL("image/png");
// Split the dataURL and decode it from ASCII to base-64 binary.
var binArray = atob(dataURL.split(',')[1]);
// Create an 8-bit unsigned array
var array = [];
// Add the unicode numeric value of each element to the new array.
for (var i = 0; i < binArray.length; i++) {
array.push(binArray.charCodeAt(i));
}
var blobObject = new Blob([new Uint8Array(array)], { type: 'image/png' });
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blobObject, 'warpedphoto.png');
}else if (window.navigator.saveBlob) {
window.navigator.saveBlob(blobObject, 'warpedphoto.png');
}
else {
dataURL = dataURL.replace("image/png", "image/octet-stream");
window.location.href = dataURL;
// alert("Sorry, your browser does not support navigator.saveBlob");
}
}
// Grid making section
function createRedGrid() {
// Make a 0,0 to 1,1 triangle mesh, using n = resolution steps.
var q = 0.001; // A fudge factor to ensure that the wireframe lines are rendered inside the canvas boundary.
var r = (1 - q * 2) / resolution;
//2 numbers per coord; three coords per triangle; 2 triagles per square; resolution * resolution squares.
var c = new Float32Array(resolution * resolution * 20);
// Array index.
var i = 0;
// Build the mesh top to bottom, left to right.
for (var xs = 0; xs < resolution; xs++) {
for (var ys = 0; ys < resolution; ys++) {
var x = r * xs + q;
var y = r * ys + q;
// Top of square - first triangle.
c[i++] = x;
c[i++] = y;
c[i++] = x + r;
c[i++] = y;
// Center line - hypotonose of triangles.
c[i++] = x;
c[i++] = y + r;
c[i++] = x + r;
c[i++] = y;
// Bottom line of 2nd triangle.
c[i++] = x;
c[i++] = y + r;
c[i++] = x + r;
c[i++] = y + r;
// First triangle, left side.
c[i++] = x;
c[i++] = y;
c[i++] = x;
c[i++] = y + r;
// Right side of 2nd triangle.
c[i++] = x + r;
c[i++] = y;
c[i++] = x + r;
c[i++] = y + r;
}
}
return c;
}
function createImageGrid() {
var q = 0.001;
var r = (1 - q * 2) / resolution;
var c = new Float32Array(resolution * resolution * 12); //2 numbers per coord; three coords per triangle; 2 triagles per square; resolution * resolution squares.
var i = 0;
for (var xs = 0; xs < resolution; xs++) {
for (var ys = 0; ys < resolution; ys++) {
var x = r * xs + q;
var y = r * ys + q;
c[i++] = x;
c[i++] = y;
c[i++] = x + r;
c[i++] = y;
c[i++] = x;
c[i++] = y + r;
c[i++] = x + r;
c[i++] = y;
c[i++] = x;
c[i++] = y + r;
c[i++] = x + r;
c[i++] = y + r;
}
}
return c;
}
}
// getMousePoint
// input - mouse event e
function getMousePoint(e) {
var x;
var y;
// The standard way to get mouse coordinates
if (e.offsetX) {
x = e.offsetX;
y = e.offsetY;
}
// LayerX and layerY are provided for cross-browser compatibility
else if (e.layerX) {
x = e.layerX;
y = e.layerY;
}
else {
return undefined; //Work around Chrome
}
return normalizedPoint(x, y); // Converts pixels to -1 to 1
}
var inputHandler = new function() {
var move; // Pointer to a uniform variable in the renderer object
this.init = function () {
var canvas = document.getElementById("2dcanvas");
// Set up mouse events on the canvas object.
canvas.onmousedown = function (e) {
console.log("onmousedown");
this.move = renderer.newMove(getMousePoint(e));
}
canvas.onmouseup = function (e) {
console.log("onmouseup");
this.move = undefined;
renderer.render();
}
canvas.onmouseout = function (e) {
console.log("onmouseout");
this.move = undefined;
renderer.render();
};
canvas.onmousemove = function (e) {
console.log("onmousemove");
var point = getMousePoint(e);
if (typeof this.move != 'undefined')
{
if (typeof point != 'undefined')
{
this.move.move(point);
}
renderer.render();
}
};
canvas.ondragstart = function (e) { //Workaround for Chrome
console.log("ondragstart");
e.preventDefault();
};
}
}
// Program starts here
function main() {
renderer.init(); // Initialize WebGL shapes and image
inputHandler.init(); // Initialize mouse and UI handler
}
// Resets the current distortion to 0
function reset(point) {
point1[currentPoint].x = 1;
point1[currentPoint].y = 1;
point2[currentPoint].x = 1.00001;
point2[currentPoint].y = 1.00001;
setVec2PointArray("p1", point1);
setVec2PointArray("p2", point2);
}
function undo() {
renderer.undo();
}
function reset() {
renderer.reset();
}
function save() {
renderer.save();
}
function normalizedPoint(x, y)
{
// converts screen coordinates to -1 to 1
var canvas = document.getElementById("2dcanvas");
x = (x / canvas.width) * 2 - 1;
y = (1 - (y / canvas.height)) * 2 - 1;
return new Point(x, y);
}
function setVec2(id, a, b) {
gl.uniform2f(gl.getUniformLocation(program, id), a, b);
}
// Adds a string to the log in the web page
function log(result) {
var resultDiv = document.getElementById("log");
resultDiv.innerHTML += result + "<br />";
}
// Adds a string to the log in the web page; overwrites everything in the log with the new string
function logi(result) {
var resultDiv = document.getElementById('log');
resultDiv.innerHTML = result;
}
// Loads a shader from a script tag
// Parameters:
// WebGL context
// id of script element containing the shader to load
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
// error - element with supplied id couldn't be retrieved
if (!shaderScript) {
return null;
}
// If successful, build a string representing the shader source
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
// Create shaders based on the type we set
// note: these types are commonly used, but not required
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
// Check the compile status, return an error if failed
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function loadProgram(gl, vertexShader, fragmentShader)
{
// create a progam object
var program = gl.createProgram();
// attach the two shaders
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// link everything
gl.linkProgram(program);
// Check the link status
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
// An error occurred while linking
var lastError = gl.getProgramInfoLog(program);
console.warn("Error in program linking:" + lastError);
gl.deleteProgram(program);
return null;
}
// if all is well, return the program object
return program;
};
function handleFileSelect(evt) {
document.getElementById("openphoto1").style.display = "inline";
document.getElementById("openphoto2").style.display = "none";
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var file = files[0];
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = function (e) {
renderer.loadImageX(this.result);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
function OpenPhoto1() {
document.getElementById("openphoto1").style.display = "none";
document.getElementById("openphoto2").style.display = "inline";
}