You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
9.3 KiB
363 lines
9.3 KiB
<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: -->
|