texture.html 9.27 KB
<html>
	<head>
		<title>First very simple WebGL example...</title>

		<script src="./gl-matrix-min.js" type="text/javascript"></script>

		<script type="text/javascript">
			var projectionMatrix, modelViewMatrix;
			var rotationAxis;
			var shaderProgram, shaderVertexPositionAttribute
			var shaderTexCoordAttribute, shaderSamplerUniform;
			var shaderProjectionMatrixUniform, shaderModelViewMatrixUniform;

			var duration = 5000; // ms
			var currentTime = Date.now();

			var okToRun = false;
			var webGLTexture;

			function handleTextureLoaded(gl, texture) {
				gl.bindTexture(gl.TEXTURE_2D, texture);
				gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
				gl.texImage2D(
						gl.TEXTURE_2D,
						0,
						gl.RGBA,
						gl.RGBA,
						gl.UNSIGNED_BYTE,
						texture.image);
				gl.texParameteri(
						gl.TEXTURE_2D,
						gl.TEXTURE_MAG_FILTER,
						gl.NEAREST);
				gl.texParameteri(
						gl.TEXTURE_2D,
						gl.TEXTURE_MIN_FILTER,
						gl.NEAREST);
				gl.bindTexture(gl.TEXTURE_2D, null);
				okToRun = true;
			}

			function initTexture(gl) {
				webGLTexture = gl.createTexture();
				webGLTexture.image = new Image();
				webGLTexture.image.onload = function () {
					handleTextureLoaded(gl, webGLTexture)
				}
				//webGLTexture.image.src = "P3D/images/webgl-logo-256.jpg";
				webGLTexture.image.src = "gravatar-256.jpg";
			}

			function initWebGL(canvas) {
				var gl = null;
				var msg = "Your browser does not support WebGL, " +
					"or it is not enabled by default.";
				try {
					gl = canvas.getContext("experimental-webgl");
				}
				catch (e) {
					msg = "Error creating WebGL Context!: " + e.toString();
				}
				if (!gl) {
					alert(msg);
					throw new Error(msg);
				}

				return gl;
			}

			function initViewport(gl, canvas) {
				gl.viewport(0, 0, canvas.width, canvas.height);
			}

			// Create the vertex, color, and index data for a
			// multicolored cube
			function createCube(gl) {
				// Vertex Data
				var vertexBuffer;
				vertexBuffer = gl.createBuffer();
				gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
				var verts = [
					// Front face
					-1.0, -1.0, 1.0,
					1.0,  -1.0, 1.0,
					1.0,  1.0,  1.0,
					-1.0, 1.0,  1.0,
					// Back face
					-1.0, -1.0, -1.0,
					-1.0, 1.0,  -1.0,
					1.0,  1.0,  -1.0,
					1.0,  -1.0, -1.0,
					// Top face
					-1.0, 1.0, -1.0,
					-1.0, 1.0, 1.0,
					1.0,  1.0, 1.0,
					1.0,  1.0, -1.0,
					// Bottom face
					-1.0, -1.0, -1.0,
					1.0,  -1.0, -1.0,
					1.0,  -1.0, 1.0,
					-1.0, -1.0, 1.0,
					// Right face
					1.0, -1.0, -1.0,
					1.0, 1.0,  -1.0,
					1.0, 1.0,  1.0,
					1.0, -1.0, 1.0,
					// Left face
					-1.0, -1.0, -1.0,
					-1.0, -1.0, 1.0,
					-1.0, 1.0,  1.0,
					-1.0, 1.0,  -1.0
				];
				gl.bufferData(
						gl.ARRAY_BUFFER,
						new Float32Array(verts),
						gl.STATIC_DRAW);

				var texCoordBuffer = gl.createBuffer();
				gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
				var textureCoords = [
					// Front face
					0.0, 0.0,
					1.0, 0.0,
					1.0, 1.0,
					0.0, 1.0,

					// Back face
					1.0, 0.0,
					1.0, 1.0,
					0.0, 1.0,
					0.0, 0.0,

					// Top face
					0.0, 1.0,
					0.0, 0.0,
					1.0, 0.0,
					1.0, 1.0,

					// Bottom face
					1.0, 1.0,
					0.0, 1.0,
					0.0, 0.0,
					1.0, 0.0,

					// Right face
					1.0, 0.0,
					1.0, 1.0,
					0.0, 1.0,
					0.0, 0.0,

					// Left face
					0.0, 0.0,
					1.0, 0.0,
					1.0, 1.0,
					0.0, 1.0,
				];
				gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);

				// Index data (defines the triangles to be drawn)
				var cubeIndexBuffer = gl.createBuffer();
				gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer);
				var cubeIndices = [
					0,  1,  2,  0,  2,  3,  // Front face
					4,  5,  6,  4,  6,  7,  // Back face
					8,  9,  10, 8,  10, 11, // Top face
					12, 13, 14, 12, 14, 15, // Bottom face
					16, 17, 18, 16, 18, 19, // Right face
					20, 21, 22, 20, 22, 23  // Left face
				];
				gl.bufferData(
						gl.ELEMENT_ARRAY_BUFFER,
						new Uint16Array(cubeIndices),
						gl.STATIC_DRAW);
				var cube = {
					buffer:vertexBuffer,
					texCoordBuffer:texCoordBuffer,
					indices:cubeIndexBuffer,
					vertSize:3,
					nVerts:24,
					texCoordSize:2,
					nTexCoords: 24,
					nIndices:36,
					primtype:gl.TRIANGLES};

				return cube;
			}

			function initMatrices(canvas) {
				modelViewMatrix = mat4.create();
				mat4.translate(
						modelViewMatrix, modelViewMatrix, [0, 0, -8]);

				// Create a project matrix with 45 degree field of view
				projectionMatrix = mat4.create();
				mat4.perspective(projectionMatrix, Math.PI / 4,
						canvas.width / canvas.height, 1, 10000);

				rotationAxis = vec3.create();
				vec3.normalize(rotationAxis, [1, 1, 1]);
			}

			function createShader(gl, id, type) {
				var shader;
				var str = document.getElementById(id).text;
				if (type == "fragment") {
					shader = gl.createShader(gl.FRAGMENT_SHADER);
				} else if (type == "vertex") {
					shader = gl.createShader(gl.VERTEX_SHADER);
				} else {
					return null;
				}

				gl.shaderSource(shader, str);
				gl.compileShader(shader);

				if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
					alert(gl.getShaderInfoLog(shader));
					return null;
				}

				return shader;
			}

			function initShader(gl, vertex, fragment) {
				// load and compile the fragment and vertex shader
				var fragmentShader = createShader(gl, fragment, "fragment");
				var vertexShader = createShader(gl, vertex, "vertex");

				// link them together into a new program
				shaderProgram = gl.createProgram();
				gl.attachShader(shaderProgram, vertexShader);
				gl.attachShader(shaderProgram, fragmentShader);
				gl.linkProgram(shaderProgram);

				// get pointers to the shader params
				shaderVertexPositionAttribute = gl.getAttribLocation(
						shaderProgram, "vertexPos");
				gl.enableVertexAttribArray(shaderVertexPositionAttribute);
				shaderTexCoordAttribute = gl.getAttribLocation(
						shaderProgram, "texCoord");
				gl.enableVertexAttribArray(shaderTexCoordAttribute);

				shaderProjectionMatrixUniform = gl.getUniformLocation(
						shaderProgram, "projectionMatrix");
				shaderModelViewMatrixUniform = gl.getUniformLocation(
						shaderProgram, "modelViewMatrix");
				shaderSamplerUniform = gl.getUniformLocation(
						shaderProgram, "uSampler");

				if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
					alert("Could not initialise shaders");
				}
			}

			function draw(gl, obj) {
				// clear the background (transparent)
				gl.clearColor(0.0, 0.0, 0.0, 0.0);
				// // clear the background (black)
				// gl.clearColor(0.0, 0.0, 0.0, 1.0);
				gl.enable(gl.DEPTH_TEST);
				gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

				// set the shader to use
				gl.useProgram(shaderProgram);

				// connect up the shader parameters: vertex position,
				// color, and projection/model matrices
				// set up the buffers
				gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
				gl.vertexAttribPointer(
						shaderVertexPositionAttribute,
						obj.vertSize,
						gl.FLOAT,
						false, 0, 0);
				gl.bindBuffer(gl.ARRAY_BUFFER, obj.texCoordBuffer);
				gl.vertexAttribPointer(
						shaderTexCoordAttribute,
						obj.texCoordSize,
						gl.FLOAT,
						false, 0, 0);
				gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.indices);
				gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false,
					  projectionMatrix);
				gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false,
					  modelViewMatrix);

				gl.activeTexture(gl.TEXTURE0);
				gl.bindTexture(gl.TEXTURE_2D, webGLTexture);
				gl.uniform1i(shaderSamplerUniform, 0);

				// draw the object
				gl.drawElements(
						obj.primtype, obj.nIndices, gl.UNSIGNED_SHORT, 0);
			}

			function animate() {
				var now = Date.now();
				var deltat = now - currentTime;
				currentTime = now;
				var fract = deltat / duration;
				var angle = Math.PI * 2 * fract;
				mat4.rotate(
						modelViewMatrix,
						modelViewMatrix,
						angle,
						rotationAxis);
			}

			function run(gl, cube) {
				requestAnimationFrame(function() { run(gl, cube); });
				if (okToRun) {
					draw(gl, cube);
					animate();
				}
			}

			function startGl() {
				// Get A WebGL context
				var canvas = document.getElementById("cube");
				var gl = initWebGL(canvas);
				var obj = createCube(gl);

				initViewport(gl, canvas);
				initMatrices(canvas);
				initShader(
						gl,
						"texture-vertex-shader",
						"texture-fragment-shader");
		        initTexture(gl);
				run(gl, obj);
			}
		</script>

		<script id="texture-vertex-shader" type="x-shader/x-vertex">
			attribute vec3 vertexPos;
			attribute vec2 texCoord;
			uniform mat4 modelViewMatrix;
			uniform mat4 projectionMatrix;
			varying vec2 vTexCoord;
			void main(void) {
				// Return the transformed and projected vertex value
				gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPos, 1.0);
				// Output the texture coordinate in vTexCoord
				vTexCoord = texCoord;
			}
		</script>

		<script id="texture-fragment-shader" type="x-shader/x-fragment">
			precision mediump float;
			varying vec2 vTexCoord;
			uniform sampler2D uSampler;
			void main(void) {
				// Return the pixel color: always output white
				gl_FragColor = texture2D(uSampler, vec2(vTexCoord.s, vTexCoord.t));
			}
		</script>
	</head>

	<body onLoad="startGl()">
		<canvas id="cube" width="500" height="500"></canvas>
	</body>
</html>
<!-- vim: set ts=4 sw=4: -->