PDA

View Full Version : WebGL Help



cgardner5
09-15-2012, 10:49 AM
Hello, I am trying to learn webgl from the various tutorials online. I started with something simple, the spinning cube, and have been slowly adding more complexity. I was doing great until I tried to texture 3 sides of the cube with one image and three sides with another. I also want the user to be able to toggle to one of images on all sides and then back to two images if they choose, as well as toggling lighting off/on. I did this in openGL and it was pretty easy. I would appreciate any direction you can offer.


<html>
<head>
<script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript" src="webgl-utils.js"></script>

<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec2 vTextureCoord;
varying vec3 vLightWeighting;

uniform sampler2D uDroidSampler;
uniform sampler2D uAppleSampler;

void main(void) {
vec4 textureColorApple = texture2D(uAppleSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColorApple.rgb * vLightWeighting, textureColorApple.a);

vec4 textureColorDroid = texture2D(uDroidSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColorApple.rgb * vLightWeighting, textureColorDroid.a);
}
</script>

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;

uniform vec3 uAmbientColor;

uniform vec3 uLightingDirection;
uniform vec3 uDirectionalColor;

uniform bool uUseLighting;

varying vec2 vTextureCoord;
varying vec3 vLightWeighting;

void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;

if (!uUseLighting) {
vLightWeighting = vec3(1.0, 1.0, 1.0);
} else {
vec3 transformedNormal = uNMatrix * aVertexNormal;
float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
}
}
</script>


<script type="text/javascript">

var gl;

function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}


function getShader(gl, id)
{
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}

str = shaderScript.text;

var shader;
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);

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

return shader;
}


var shaderProgram;


function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");

shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

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

gl.useProgram(shaderProgram);

shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPos itionAttribute);

shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCo ordAttribute);

shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNor malAttribute);

shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.appleUniform = gl.getUniformLocation(shaderProgram, "uAppleSampler");
shaderProgram.droidUniform = gl.getUniformLocation(shaderProgram, "uDroidSampler");

}



//var txtr = new Array();
var apple = 0;
var droid = 1;
var tex;
function initTexture(filename,tex)
{
/*var pic = txtr.length;
txtr[pic] = {};
txtr[pic].texture = gl.createTexture();
txtr[pic].image = new Image();
txtr[pic].image.onload = function()
{
gl.bindTexture(gl.TEXTURE_2D, txtr[pic]);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, txtr[pic].image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
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.bindTexture(gl.TEXTURE_2D, null);
}

txtr[pic].image.src = sFilename;
return txtr[pic];*/

this.loadTex = function(filename) {
tex = gl.createTexture();
var img = new Image();
img.onload = function() {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
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);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE0, null);
};
img.src = filename;
return tex;
}
}



var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();

function mvPushMatrix()
{
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}

function mvPopMatrix()
{
if (mvMatrixStack.length == 0)
{
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}


function setMatrixUniforms()
{
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);

var normalMatrix = mat3.create();
mat4.toInverseMat3(mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
//gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
//gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}


function degToRad(degrees)
{
return degrees * Math.PI / 180;
}



var xRot = 0;
var xSpeed = 3;

var yRot = 0;
var ySpeed = -3;

var z = -5.0


var currentlyPressedKeys = {};

function handleKeyDown(event)
{
currentlyPressedKeys[event.keyCode] = true;
}


function handleKeyUp(event)
{
currentlyPressedKeys[event.keyCode] = false;
}


/* function handleKeys()
{
if (currentlyPressedKeys[65] || currentlyPressedKeys[97])
{
apple=droid=0;
}
if (currentlyPressedKeys[68] || currentlyPressedKeys[100])
{
// Page Down
apple=droid=1;
}
if (currentlyPressedKeys[1])
{
lighting = 1;
}
if (currentlyPressedKeys[2])
{
lighting = 0;
}
if (currentlyPressedKeys[38])
{
// Up cursor key
xSpeed -= 1;
}
if (currentlyPressedKeys[40])
{
// Down cursor key
xSpeed += 1;
}
}
*/
var cubeVertexPositionBuffer;
var cubeVertexTextureCoordBuffer;
var cubeVertexIndexBuffer;
var cubeVertexPositionBuffer1;
var cubeVertexTextureCoordBuffer1;
var cubeVertexIndexBuffer1;

function initBuffers() {

//cubeVertexPositionBuffer{};
cubeVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
vertices = [
// 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,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numItems = 12;

//cubeVertexPositionBuffer1{};
cubeVertexPositionBuffer1 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1);
vertices = [
// 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(vertices), gl.STATIC_DRAW);
cubeVertexPositionBuffer1.itemSize = 3;
cubeVertexPositionBuffer1.numItems = 12;


//cubeVertexTextureCoordBuffer{};
cubeVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
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,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
cubeVertexTextureCoordBuffer.itemSize = 2;
cubeVertexTextureCoordBuffer.numItems = 12;


//cubeVertexTextureCoordBuffer1{};
cubeVertexTextureCoordBuffer1 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer1);
var textureCoords = [
// 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);
cubeVertexTextureCoordBuffer1.itemSize = 2;
cubeVertexTextureCoordBuffer1.numItems = 12;

//cubeVertexIndexBuffer{};
cubeVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numItems = 18;

//cubeVertexIndexBuffer1{};
cubeVertexIndexBuffer1 = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer1);
var cubeVertexIndices = [
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(cubeVertexIndices), gl.STATIC_DRAW);
cubeVertexIndexBuffer1.itemSize = 1;
cubeVertexIndexBuffer1.numItems = 18;
}


var lighting = new Boolean(1);
function drawScene()
{
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

mat4.identity(mvMatrix);

mat4.translate(mvMatrix, [0.0, 0.0, z]);

mat4.rotate(mvMatrix, degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, degToRad(yRot), [0, 1, 0]);


gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositio nAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

//gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
//gl.vertexAttribPointer(shaderProgram.vertexNormalA ttribute, cubeVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordA ttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);

/*
// Draw face 0
gl.bindTexture(gl.TEXTURE_2D, txtr[0]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

// Draw face 1
gl.bindTexture(gl.TEXTURE_2D, txtr[1]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 12);

// Draw face 2
gl.bindTexture(gl.TEXTURE_2D, txtr[2]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 24);

// Draw face 3
gl.bindTexture(gl.TEXTURE_2D, txtr[3]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 36);

// Draw face 4
gl.bindTexture(gl.TEXTURE_2D, txtr[4]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 48);

// Draw face 5
gl.bindTexture(gl.TEXTURE_2D, txtr[5]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 60);
*/

gl.activeTexture(gl.TEXTURE0);
//gl.bindTexture(gl.TEXTURE_2D, texturen[1]);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.vertexAttribPointer(shaderProgram.textureCoordA ttribute, cubeVertexTextureCoordBuffer1.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1);
gl.vertexAttribPointer(shaderProgram.vertexPositio nAttribute,cubeVertexPositionBuffer1.itemSize, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);


gl.uniform1i(shaderProgram.appleUniform, 0);
gl.uniform1i(shaderProgram.droidUniform, 0);
/* gl.uniform1i(shaderProgram.useLightingUniform, lighting);
if (lighting)
{
gl.uniform3f(
shaderProgram.ambientColorUniform,
parseFloat(document.getElementById("ambientR").value),
parseFloat(document.getElementById("ambientG").value),
parseFloat(document.getElementById("ambientB").value)
);

var lightingDirection = [
parseFloat(document.getElementById("lightDirectionX").value),
parseFloat(document.getElementById("lightDirectionY").value),
parseFloat(document.getElementById("lightDirectionZ").value)
];
var adjustedLD = vec3.create();
vec3.normalize(lightingDirection, adjustedLD);
vec3.scale(adjustedLD, -1);
gl.uniform3fv(shaderProgram.lightingDirectionUnifo rm, adjustedLD);

gl.uniform3f(
shaderProgram.directionalColorUniform,
parseFloat(document.getElementById("directionalR").value),
parseFloat(document.getElementById("directionalG").value),
parseFloat(document.getElementById("directionalB").value)
);
}*/

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

}


var lastTime = 0;

function animate()
{
var timeNow = new Date().getTime();
if (lastTime != 0)
{
var elapsed = timeNow - lastTime;

xRot += (xSpeed * elapsed) / 1000.0;
yRot += (ySpeed * elapsed) / 1000.0;
}
lastTime = timeNow;
}


function tick()
{
requestAnimFrame(tick);
//handleKeys();
drawScene();
animate();
}


function webGLStart()
{
var canvas = document.getElementById("HW4");
initGL(canvas);
initShaders();
initBuffers();
initTexture("apple.bmp",tex);
initTexture("droid.bmp",tex);
initTexture("apple.bmp",tex);
initTexture("droid.bmp",tex);
initTexture("apple.bmp",tex);
initTexture("droid.bmp",tex);

gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
//document.onkeydown = handleKeyDown;
// document.onkeyup = handleKeyUp;
tick();
}


</script>


</head>


<body onload="webGLStart();">

<canvas id="HW4" style="border: none;" width="500" height="500"></canvas>








<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-2240015-5");
pageTracker._trackPageview();
} catch(err) {
}
</script>

</body>

</html>