Range Slider for camera in WebGL - javascript

I'm trying to get a range slider to change the far plane and the angle of the camera in Webgl but I can't. How do I do in order for my code to read the value from the slider and then change the value in the perspective of the camera?
// Application info.
var app = app || {};
function initGL() {
var gl = app.gl;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.viewport(0, 0, app.can.width, app.can.height);
gl.clearColor(0., 0., 0., 1.0);
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [
// 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, -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,
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,
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, -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,
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, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0
];
app.nPoints = positions.length / 3;
var colors = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1
];
var loc, buffer;
// Create and copy position buffer.
loc = gl.getAttribLocation(app.progObject, "pos");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// Create and copy color buffer.
loc = gl.getAttribLocation(app.progObject, "color");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
// Look for uniforms.
app.pmLocation = gl.getUniformLocation(app.progObject, "projMatrix");
app.mmLocation = gl.getUniformLocation(app.progObject, "modelMatrix");
app.vmLocation = gl.getUniformLocation(app.progObject, "viewMatrix");
var mat4 = glMatrix.mat4;
app.projMatrix = mat4.create();
app.modelMatrix = mat4.create();
app.viewMatrix = mat4.create();
app.pcam = mat4.create();
app.mvpMatrix = mat4.create();
var near = 0.1;
mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/, 1, 0.1, farChanged());
mat4.lookAt(app.viewMatrix, [ 15, 0, -10], [-5, 0, 0], [0, 1, 0]);
}
function animate(time) {
var gl = app.gl;
var mat4 = glMatrix.mat4;
// converts to seconds.
var seconds = time * 1E-3;
var dtime = time - app.oldTime;
var mm1 = mat4.create();
mat4.translate(mm1, app.modelMatrix, [2, 0, 0]);
var angle = time * 0.001;
mat4.rotateY(mm1, mm1, angle);
app.oldTime = time;
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation, false, mm1);
gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix);
gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
// Pour dessiner autre cube, calculer autre model matrix
// et redessiner ... gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
var mm2 = mat4.create();
mat4.translate(mm2, app.modelMatrix, [-2, 0, 0]);
mat4.rotateY(mm2, mm2, angle)
gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation, false, mm2);
gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix);
gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
//for the camera
var moveInAndOut = 0.1 * Math.cos(angle);
var moveLeftAndRight = 0.1 * Math.sin(angle);
app.pcam = ([moveInAndOut, 0, moveLeftAndRight]);
// app.viewMatrix = lookAt(app.pcam, [0, 0, 0], [0, 1, 0]);
// mat4.lookAt(app.viewMatrix, app.pcam , [0, 0, 0], [0, 1, 0]);
mat4.translate(app.viewMatrix, app.viewMatrix, app.pcam);
mat4.rotateY(app.viewMatrix, app.viewMatrix, 0.05);
window.requestAnimationFrame(animate);
}
function fovChanged(id, value) {
console.log("FOV Angle: ", value);
var label = document.getElementById('output-fov');
label.innerHTML = value;
}
function farChanged(id, value) {
console.log("Far Plane: ", value);
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
}
function init() {
[app.can, app.gl] = getContextGL('can');
if (app.can == null || app.gl == null) {
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
app.oldTime = 0;
animate(0);
}
init();
// -----
function getContextGL(id) {
const can = document.getElementById(id);
const gl = can.getContext('webgl');
return [can, gl];
}
function createShaderFromElement(gl, id) {
const e = document.getElementById(id);
const s = gl.createShader(e.type.indexOf('vertex') >= 0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
gl.shaderSource(s, e.text);
gl.compileShader(s);
return s;
}
function buildProgram(gl, vs, fs) {
const p = gl.createProgram();
gl.attachShader(p, vs);
gl.attachShader(p, fs);
gl.linkProgram(p);
return p;
}
div
{
}
#main-div
{
display:inline-block;
}
#viewport, #manager
{
float: left;
margin: auto;
}
.color
{
width:100px;
height:50px;
}
.blue{
background:#0f0;
}
#viewport
{
width: 600px;
height:700px;
}
#can
{
width: 600px;
height: 500px;
border:1px solid orange;
}
#manager
{
width: 200px;
height:300px;
padding: 0 0 0 5px;
}
#obj-list
{
width: 200px;
}
<!DOCTYPE html>
<html>
<head>
<title>Cube Transform</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="transforms.js"></script>
<script src="utils.js"></script>
<script src="gl-matrix-min.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
attribute vec3 pos;
attribute vec3 color;
varying vec3 fColor;
void main()
{
fColor = color;
vec4 pt = vec4(pos, 1.0);
gl_Position = projMatrix * viewMatrix * modelMatrix * pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec3 fColor;
void main()
{
gl_FragColor = vec4(fColor,1);
}
</script>
</head>
<body onload="init();">
<div id="main-div">
<div id="viewport">
<canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
<div class="slider">
<span class="slider-label">FOV cam</span>
<input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id, this.value)" />
<span id="output-fov" class="slider-value">20</span>
</div>
<div class="slider">
<span class="slider-label">Far Plane</span>
<input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id, this.value)" />
<span id="output-far" class="slider-value">5</span>
</div>
</div>
</div>
</body>
</html>
My code contains multiple files so here's the link to the full code:
https://wetransfer.com/downloads/f05fa22faa0e0803a0b6fa13348d7d9520200920195230/52fc67
The js code is in transforms.js.
Thank you!

This line
mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/, 1, 0.1, farChanged());
makes no sense. farChanged does not return anything. It just sets the label's innerHTML
You need to update the project matrix when the event gets called
function farChanged(id, value) {
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
glMatrix.mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/ , 1, 0.1, parseFloat(value));
}
// Application info.
var app = app || {};
function initGL() {
var gl = app.gl;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.viewport(0, 0, app.can.width, app.can.height);
gl.clearColor(0., 0., 0., 1.0);
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [
// 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, -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,
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,
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, -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,
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, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0
];
app.nPoints = positions.length / 3;
var colors = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1
];
var loc, buffer;
// Create and copy position buffer.
loc = gl.getAttribLocation(app.progObject, "pos");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/ , 0 /*stride*/ , 0 /*offset*/ );
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// Create and copy color buffer.
loc = gl.getAttribLocation(app.progObject, "color");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/ , 0 /*stride*/ , 0 /*offset*/ );
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
// Look for uniforms.
app.pmLocation = gl.getUniformLocation(app.progObject, "projMatrix");
app.mmLocation = gl.getUniformLocation(app.progObject, "modelMatrix");
app.vmLocation = gl.getUniformLocation(app.progObject, "viewMatrix");
var mat4 = glMatrix.mat4;
app.projMatrix = mat4.create();
app.modelMatrix = mat4.create();
app.viewMatrix = mat4.create();
app.pcam = mat4.create();
app.mvpMatrix = mat4.create();
var near = 0.1;
mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/ , 1, 0.1, 10);
mat4.lookAt(app.viewMatrix, [15, 0, -10], [-5, 0, 0], [0, 1, 0]);
}
function animate(time) {
var gl = app.gl;
var mat4 = glMatrix.mat4;
// converts to seconds.
var seconds = time * 1E-3;
var dtime = time - app.oldTime;
var mm1 = mat4.create();
mat4.translate(mm1, app.modelMatrix, [2, 0, 0]);
var angle = time * 0.001;
mat4.rotateY(mm1, mm1, angle);
app.oldTime = time;
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation, false, mm1);
gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix);
gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
// Pour dessiner autre cube, calculer autre model matrix
// et redessiner ... gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
var mm2 = mat4.create();
mat4.translate(mm2, app.modelMatrix, [-2, 0, 0]);
mat4.rotateY(mm2, mm2, angle)
gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation, false, mm2);
gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix);
gl.drawArrays(gl.TRIANGLES, 0, app.nPoints);
//for the camera
var moveInAndOut = 0.1 * Math.cos(angle);
var moveLeftAndRight = 0.1 * Math.sin(angle);
app.pcam = ([moveInAndOut, 0, moveLeftAndRight]);
// app.viewMatrix = lookAt(app.pcam, [0, 0, 0], [0, 1, 0]);
// mat4.lookAt(app.viewMatrix, app.pcam , [0, 0, 0], [0, 1, 0]);
mat4.translate(app.viewMatrix, app.viewMatrix, app.pcam);
mat4.rotateY(app.viewMatrix, app.viewMatrix, 0.05);
window.requestAnimationFrame(animate);
}
function fovChanged(id, value) {
console.log("FOV Angle: ", value);
var label = document.getElementById('output-fov');
label.innerHTML = value;
}
function farChanged(id, value) {
//console.log("Far Plane: ", value);
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
glMatrix.mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/ , 1, 0.1, parseFloat(value));
}
function init() {
[app.can, app.gl] = getContextGL('can');
if (app.can == null || app.gl == null) {
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
app.oldTime = 0;
animate(0);
}
init();
// -----
function getContextGL(id) {
const can = document.getElementById(id);
const gl = can.getContext('webgl');
return [can, gl];
}
function createShaderFromElement(gl, id) {
const e = document.getElementById(id);
const s = gl.createShader(e.type.indexOf('vertex') >= 0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
gl.shaderSource(s, e.text);
gl.compileShader(s);
return s;
}
function buildProgram(gl, vs, fs) {
const p = gl.createProgram();
gl.attachShader(p, vs);
gl.attachShader(p, fs);
gl.linkProgram(p);
return p;
}
div {}
#main-div {
display: inline-block;
}
#viewport,
#manager {
float: left;
margin: auto;
}
.color {
width: 100px;
height: 50px;
}
.blue {
background: #0f0;
}
#viewport {
width: 600px;
height: 700px;
}
#can {
width: 600px;
height: 500px;
border: 1px solid orange;
}
#manager {
width: 200px;
height: 300px;
padding: 0 0 0 5px;
}
#obj-list {
width: 200px;
}
<div id="main-div">
<div id="viewport">
<canvas id="can">Your browser doesn't seem to support canvas!</canvas>
<div class="slider">
<span class="slider-label">FOV cam</span>
<input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id, this.value)" />
<span id="output-fov" class="slider-value">20</span>
</div>
<div class="slider">
<span class="slider-label">Far Plane</span>
<input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id, this.value)" />
<span id="output-far" class="slider-value">5</span>
</div>
</div>
</div>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
attribute vec3 pos;
attribute vec3 color;
varying vec3 fColor;
void main()
{
fColor = color;
vec4 pt = vec4(pos, 1.0);
gl_Position = projMatrix * viewMatrix * modelMatrix * pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec3 fColor;
void main()
{
gl_FragColor = vec4(fColor,1);
}
</script>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix#3.3.0/gl-matrix-min.js"></script>
Some other things.
Don't use body onload: https://stackoverflow.com/a/48256189/128511
Use addEventListener(eventName, function) instead of onClick="string"
Use the input event instead of the click event
don't set innerHTML, instead set textContent
Learn to use the snippets so they work (see the snippet above). In particular you didn't need <html>, <head>, links to <scripts> that don't exist and you needed to link to a cdn for glMatrix.

Related

I wanna make an octagon using multiple triangles in WebGL but it does not run

i am trying to run this code in a json script, its just the webgl code.
I am trying to make this work but it doesnt. I am trying to make an octagon using mulptiple triangles but when im trying to create them with the indexes it does not work.
I think the problem is at the indexes numItems value.
It is also supposed to show a black backround but this doesnt show either.
Any help? (this is not the whole code but i figure here is where the problem is)
octagonIndexBuffer = gl.createBuffer(); // **
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, octagonIndexBuffer); // We bind the IBO as an ELEMENT_ARRAY_BUFFER.
let indexes = [ // The indexes that will be loaded in the buffer
0, 2, 4,//A
4, 0, 6,//B
6, 0, 7,//C
7, 0, 5,//D
5, 0, 3,//E
5, 0, 8,//F
8, 0, 9,//G
9, 0, 2//H
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexes), gl.STATIC_DRAW);
octagonIndexBuffer.itemSize = 1; // item size = 1 because one index = one vertex.
octagonIndexBuffer.numItems = 24;
octagonVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, octagonVertexColorBuffer);
// We define our vertex colors.
let colors = [
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 0.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
octagonVertexColorBuffer.itemSize = 4; // item size = 4 because (R, G, B, A).
octagonVertexColorBuffer.numItems = 9;
octagonVertexPositionBuffer = gl.createBuffer(); // We tell our GPU to create a buffer and give us a pointer to it.
gl.bindBuffer(gl.ARRAY_BUFFER, octagonVertexPositionBuffer); // We need to bind the buffer (make it active) in order to use it.
// We define our vertex positions.
let vertices = [
0.0, 0.0, 0.0, //1
1.0, 1.0, 0.0,//2
-1.0, 1.0, 0.0, //3
1.0, -1.0, 0.0,//4
-1.0, -1.0, 0.0, //5
0.5, -1.5, 0.0, //6
-0.5, -1.5, 0.0 , //7
-0.5, 1.5, 0.0 , //8
0.5, 1.5, 0.0 , //9
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // We send the vertex positions to the buffer in our GPU.
octagonVertexColorBufferVertexPositionBuffer.itemSize = 3; // item size = 3 because (x, y, z).
octagonVertexPositionBuffer.numItems = 9; // numItems = 3 because we have three vertices.

I am trying to draw rotating square in WebGL but not getting it. plus I need to add a point light source

"use strict";
var canvas;
var gl;
var axis = 0;
var xAxis = 0;
var yAxis =1;
var zAxis = 2;
var theta = [0, 0, 0];
var thetaLoc;
var flag = true;
var numElements = 36;
var vertices = [
vec3(-0.5, -0.5, 0.5),
vec3(-0.5, 0.5, 0.5),
vec3(0.5, 0.5, 0.5),
vec3(0.5, -0.5, 0.5),
vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, -0.5),
vec3(0.5, 0.5, -0.5),
vec3(0.5, -0.5, -0.5)
];
var vertexColors = [
vec4(0.0, 0.0, 0.0, 1.0), // black
vec4(1.0, 0.0, 0.0, 1.0), // red
vec4(1.0, 1.0, 0.0, 1.0), // yellow
vec4(0.0, 1.0, 0.0, 1.0), // green
vec4(0.0, 0.0, 1.0, 1.0), // blue
vec4(1.0, 0.0, 1.0, 1.0), // magenta
vec4(1.0, 1.0, 1.0, 1.0), // white
vec4(0.0, 1.0, 1.0, 1.0) // cyan
];
// indices of the 12 triangles that compose the cube
var indices = [
1, 0, 3,
3, 2, 1,
2, 3, 7,
7, 6, 2,
3, 0, 4,
4, 7, 3,
6, 5, 1,
1, 2, 6,
4, 5, 6,
6, 7, 4,
5, 4, 0,
0, 1, 5
];
window.onload = function init()
{
// --------------- Cube --------------------------
canvas = document.getElementById("gl-canvas");
gl = canvas.getContext('webgl2');
if (!gl) alert("WebGL 2.0 isn't available");
gl.viewport(0, 0, canvas.width - 50, canvas.height - 50);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.enable(gl.DEPTH_TEST);
// Load shaders and initialize attribute buffers
// Create a buffer object, initialise it, and associate it
// with the associated attribute variable in our vertex shader
var programCube = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(programCube);
// array element buffer
var iBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);
// color array atrribute buffer
var cBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertexColors), gl.STATIC_DRAW);
var colorLoc = gl.getAttribLocation(programCube, "aColor");
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(colorLoc);
// vertex array attribute buffer
var vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW);
var positionLoc = gl.getAttribLocation( programCube, "aPosition");
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc );
thetaLoc = gl.getUniformLocation(programCube, "uTheta");
render();
//event listeners for buttons
document.getElementById( "xButton" ).onclick = function () {
axis = xAxis;
};
document.getElementById( "yButton" ).onclick = function () {
axis = yAxis;
};
document.getElementById( "zButton" ).onclick = function () {
axis = zAxis;
};
document.getElementById("ButtonT").onclick = function(){flag = !flag;};
}
function render()
{
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if(flag) theta[axis] += 2.0;
gl.uniform3fv(thetaLoc, theta);
gl.drawElements(gl.TRIANGLES, numElements, gl.UNSIGNED_BYTE, 0);
requestAnimationFrame(render);
}
still, need to add below
Need to set up the surface normals for the objects being shown on the scene.
Properly setting up different material properties for the objects being shown on the scene.
Properly showing two different light sources at fixed locations that areused to illustrate properly the objects on the scene, and can be turned on and off independently.
Properly setting up the lights above with an ambient light sourcecomponent that is used to illustrate properly the objects on the scene and can be turned from totally dark to intense brightness using a dialor a slider (from 0-total darkness to 100-total brightness, with a default somewhere in between.

WebGLRenderingContext GL ERROR : GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2

I'm learning how to use canvas in Webgl but im having some problems with textures. I want to draw a cube, an sphere, the axis and a grid. Everything is perfect if i only add the sphere, axis and grid but when i add the cube to the scene the grid disappears and shows me this error:
WebGL error INVALID_OPERATION in drawElements(TRIANGLES, 357, UNSIGNED_SHORT, 0)
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2.
this is my render class:
define([
'text!shaders/vertex-shader.glsl',
'text!shaders/fragment-shader.glsl',
'./Ejes',
'./Mesh',
'glMatrix',
'CuonUtils'], function(vsSource, fsSource,Ejes,Mesh,glMatrix, CuonUtils) {
var canvas = document.getElementById('canvas');
var gl = CuonUtils.getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!CuonUtils.initShaders(gl, vsSource, fsSource)) {
console.log('Failed to intialize shaders.');
return;
}
var program = gl.program;
// Cache attribute/uniform location
var aPostion = gl.getAttribLocation(program, 'aPostion');
var aNormal = gl.getAttribLocation(program, 'aNormal');
var aTexCoord = gl.getAttribLocation(program, 'aTexCoord');
var uModelMatrix = gl.getUniformLocation(program, 'uModelMatrix');
var uViewMatrix = gl.getUniformLocation(program, 'uViewMatrix');
var uProjectionMatrix = gl.getUniformLocation(program, 'uProjectionMatrix');
var uNormalMatrix = gl.getUniformLocation(program, 'uNormalMatrix');
var uLightColor = gl.getUniformLocation(program, 'uLightColor');
var uLightPosition = gl.getUniformLocation(program, 'uLightPosition');
var uAmbientLight = gl.getUniformLocation(program, 'uAmbientLight');
var uColor = gl.getUniformLocation(program, 'uColor');
var uSampler = gl.getUniformLocation(program, 'uSampler');
var uUseLighting = gl.getUniformLocation(program, 'uUseLighting');
var uUseTexture = gl.getUniformLocation(program, 'uUseTexture');
function initBuffers(gl, mesh){
if(mesh._webgl){
return;
}
mesh._webgl = {};
// Create Vertex Buffer Object
var VBOData = new Float32Array(
mesh.geometry.vertices);
var VBO = mesh._webgl.vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, VBO);
gl.bufferData(gl.ARRAY_BUFFER, VBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// Create Index Buffer Object
var IBOData = new Uint16Array(
mesh.geometry.faces);
var IBO = mesh._webgl.ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IBO);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, IBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
mesh._webgl.ibo.dataSize = IBOData.length;
// Create Normal Buffer Object
var NBOData = new Float32Array(
mesh.geometry.normals);
var NBO = mesh._webgl.nbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, NBO);
gl.bufferData(gl.ARRAY_BUFFER, NBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
if(mesh.useTexture){
// Create st Buffer Object
var STBOData = new Float32Array(
mesh.geometry.st);
var STBO = mesh._webgl.stbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, STBO);
gl.bufferData(gl.ARRAY_BUFFER, STBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
var TBO = mesh._webgl.tbo = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, TBO);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([255, 255, 255, 255])
);
loadTexture(gl, mesh.imgSrc, mesh._webgl.tbo, function() {
bindTextureToSampler(gl, mesh._webgl.tbo);
});
}
}
function render(scene, camera) {
// Specify the color for clearing <canvas>
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);
// seteo las luces
gl.uniform3fv(uLightColor, scene.pointLight.getLightColor());
gl.uniform3fv(uLightPosition, scene.pointLight.getLightPosition());
gl.uniform3fv(uAmbientLight, scene.ambientLight.getLightColor());
for( var i = 0; i < scene.meshes.length; i++){
var mesh = scene.meshes[i];
initBuffers(gl, mesh);
gl.uniform1i(uUseLighting, mesh.useLight);
gl.uniform1i(uUseTexture, mesh.useTexture);
gl.enableVertexAttribArray(aPostion);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.vbo);
gl.vertexAttribPointer(
aPostion, 3, gl.FLOAT, false, 0, 0
);
gl.enableVertexAttribArray(aNormal);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.nbo);
gl.vertexAttribPointer(
aNormal, 3, gl.FLOAT, false, 0, 0
);
// Clean up
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.uniformMatrix4fv(uModelMatrix, false, mesh.getModelMatrix());
gl.uniformMatrix4fv(uViewMatrix, false, camera.getViewMatrix());
gl.uniformMatrix4fv(uProjectionMatrix, false, camera.getProjectionMatrix());
gl.uniformMatrix4fv(uNormalMatrix, false, mesh.getNormalMatrix());
gl.uniform4fv(uColor, mesh.material.getColor());
if(mesh.useTexture){
gl.enableVertexAttribArray(aTexCoord);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.stbo);
gl.vertexAttribPointer(
aTexCoord, 2, gl.FLOAT, false, 0, 0
);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, mesh._webgl.tbo);
gl.uniform1i(uSampler, 0);
}
draw(gl,mesh);
}
}
function loadTexture(gl, imageSrc, textureBO, callback) {
var image = new Image();
image.src = imageSrc;
image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, textureBO);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
setupTexture(image.width, image.height);
gl.bindTexture(gl.TEXTURE_2D, null);
callback();
};
}
function bindTextureToSampler(gl, textureBO) {
gl.bindTexture(gl.TEXTURE_2D, textureBO);
gl.uniform1i(uSampler, 0);
}
function setupTexture(width, height) {
if (isPowerOf2(width) && isPowerOf2(height) ){
// the dimensions are power of 2 so generate mips and turn on
// tri-linear filtering.
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else {
// at least one of the dimensions is not a power of 2 so set the filtering
// so WebGL will render it.
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);
}
}
function isPowerOf2(value) {
return (value & (value - 1)) === 0;
}
function draw(gl, mesh) {
// gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._webgl.ibo);
gl.drawElements(mesh.tipe, mesh._webgl.ibo.dataSize, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, null);
}
return {
render: render
};
});
and this is my main class:
define([
'./WebGLRenderer',
'./Scene',
'./Mesh',
'./Geometry',
'./Material',
'./RegularConvexPolygonGeometry',
'./Cubo',
'./Sphere',
'./Cylinder',
'./PerspectiveCamera',
'./OrthographicCamera',
'./Light',
'./PointLight',
'./Ejes',
'dat',
'./cuadrado',
'CuonUtils'
], function(WebGLRenderer, Scene, Mesh, Geometry, Material,
RegularConvexPolygonGeometry, Cubo, Sphere, Cylinder,
PerspectiveCamera, OrthographicCamera, Light, PointLight,
Ejes, dat, Cuadrado, CuonUtils) {
var canvas = document.getElementById('canvas');
var gl = CuonUtils.getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
////////////
// ESCENA //
////////////
var clearColor = [0.0,0.0,0.0];
//Ambient Light
var light = Object.create(Light);
light.init();
light.hex = Math.floor( 0xaaaaaa );
//Point Light
var pointLight = Object.create(PointLight);
pointLight.init();
var scene = Object.create(Scene);
scene.init(clearColor, light, pointLight);
//////////
// EJES //
//////////
//GRID
var GrillaGeometry = Object.create(Ejes);
GrillaGeometry.getGrillaGeometry();
var grillaMaterial = Object.create(Material);
grillaMaterial.init();
grillaMaterial.hex = Math.floor( 0x0f0f0f );
var GrillaMesh = Object.create(Mesh);
GrillaMesh.init(GrillaGeometry,grillaMaterial);
GrillaMesh.tipe = gl.LINES;
GrillaMesh.useLight = false;
GrillaMesh.useTexture = false;
//X
var EjeXGeometry = Object.create(Ejes);
EjeXGeometry.getXGeometry();
var EjeXMaterial = Object.create(Material);
EjeXMaterial.init();
EjeXMaterial.hex = Math.floor( 0xff0000 );
var EjeXMesh = Object.create(Mesh);
EjeXMesh.init(EjeXGeometry,EjeXMaterial);
EjeXMesh.tipe = gl.LINES;
EjeXMesh.useLight = false;
EjeXMesh.useTexture = false;
//Y
var EjeYGeometry = Object.create(Ejes);
EjeYGeometry.getYGeometry();
var EjeYMaterial = Object.create(Material);
EjeYMaterial.init();
EjeYMaterial.hex = Math.floor( 0x00ff00 );
var EjeYMesh = Object.create(Mesh);
EjeYMesh.init(EjeYGeometry,EjeYMaterial);
EjeYMesh.tipe = gl.LINES;
EjeYMesh.useLight = false;
EjeYMesh.useTexture = false;
//Z
var EjeZGeometry = Object.create(Ejes);
EjeZGeometry.getZGeometry();
var EjeZMaterial = Object.create(Material);
EjeZMaterial.init();
EjeZMaterial.hex = Math.floor( 0x0000ff );
var EjeZMesh = Object.create(Mesh);
EjeZMesh.init(EjeZGeometry,EjeZMaterial);
EjeZMesh.tipe = gl.LINES;
EjeZMesh.useLight = false;
EjeZMesh.useTexture = false;
scene.addMesh(GrillaMesh);
scene.addMesh(EjeXMesh);
scene.addMesh(EjeYMesh);
scene.addMesh(EjeZMesh);
////////////////
// ESFERA //
////////////////
var sphereGeometry = Object.create(Sphere);
sphereGeometry.init();
var sphereMaterial = Object.create(Material);
sphereMaterial.init();
sphereMaterial.hex = Math.floor( 0xffffff );
var sphereMesh = Object.create(Mesh);
sphereMesh.init(sphereGeometry,sphereMaterial);
sphereMesh.tipe = gl.TRIANGLES;
sphereMesh.tx = 5.0;
sphereMesh.useLight = true;
sphereMesh.useTexture = true;
sphereMesh.imgSrc = 'scripts/texture/earthmap.jpg';
scene.addMesh(sphereMesh);
////////////////
// CUBO //
////////////////
var cubeGeometry = Object.create(Cubo);
cubeGeometry.init();
var cubeMaterial = Object.create(Material);
cubeMaterial.init();
cubeMaterial.hex = Math.floor( 0xffffff );
var cubeMesh = Object.create(Mesh);
cubeMesh.init(cubeGeometry,cubeMaterial);
cubeMesh.tipe = gl.TRIANGLES;
cubeMesh.tz = 5.0;
cubeMesh.useLight = true;
cubeMesh.useTexture = true;
cubeMesh.imgSrc = 'scripts/texture/firefox-icon3.png';
scene.addMesh(cubeMesh);
//////////////////////////////
/// PERSPECTIVE PROJECTION ///
//////////////////////////////
// var camera = Object.create(PerspectiveCamera);
// PerspectiveCamera.init(Math.PI / 4,1,0.1,200);
///////////////////////////////
/// ORTHOGRAPHIC PROJECTION ///
///////////////////////////////
var camera = Object.create(OrthographicCamera);
OrthographicCamera.init(-8,8,-8,8,0.1,1000);
function tick(){
WebGLRenderer.render(scene, camera);
requestAnimationFrame(tick);
}
tick();
});
I'm almost sure that the problem is my render class but just in case i'll post the other classes too.
cube:
define(['glMatrix','./Geometry'], function(glMatrix, Geometry) {
var Cubo = Object.create(Geometry);
Cubo.init = function(){
var vertices = new Float32Array([
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0,-1.0, 1.0, // v0-v1-v2-v3 front
1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0, // v0-v3-v4-v5 right
1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0,-1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
-1.0, 1.0, 1.0, -1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0,-1.0, 1.0, // v1-v6-v7-v2 left
-1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0, 1.0, -1.0,-1.0, 1.0, // v7-v4-v3-v2 down
1.0,-1.0,-1.0, -1.0,-1.0,-1.0, -1.0, 1.0,-1.0, 1.0, 1.0,-1.0 // v4-v7-v6-v5 back
]);
//Creo las caras
var indexVertices = new Uint16Array([
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // right
8, 9,10, 8,10,11, // up
12,13,14, 12,14,15, // left
16,17,18, 16,18,19, // down
20,21,22, 20,22,23 // back
]);
//Normales
var normales = new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, // v7-v4-v3-v2 down
0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0 // v4-v7-v6-v5 back
]);
var st = new Float32Array([
// Front
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Back
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Top
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Bottom
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Right
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Left
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
]);
Geometry.init.call(this, vertices, indexVertices, normales, st);
};
return Cubo;
});
sphere:
define(['./Geometry'], function(Geometry) {
var Sphere = Object.create(Geometry);
Sphere.init = function(){
var SPHERE_DIV = 13;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var vertices = [];
var indexVertices = [];
var st = [];
//Creo los vertices
for (j = 0; j <= SPHERE_DIV; j++) {
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++) {
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
vertices.push(si * sj); // X
vertices.push(cj); // Y
vertices.push(ci * sj); // Z
st.push(1 - (i / SPHERE_DIV) );
st.push(1 - (j / SPHERE_DIV) );
}
}
//Creo los indices
for (j = 0; j < SPHERE_DIV; j++) {
for (i = 0; i < SPHERE_DIV; i++) {
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indexVertices.push(p1);
indexVertices.push(p2);
indexVertices.push(p1 + 1);
indexVertices.push(p1 + 1);
indexVertices.push(p2);
indexVertices.push(p2 + 1);
}
}
Geometry.init.call(this, vertices, indexVertices, vertices, st);
};
return Sphere;
});
grid:
define(['./Geometry'], function(Geometry) {
var Ejes = Object.create(Geometry);
Ejes.getXGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(10.0,0.0,0.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices, vertices, st);
};
Ejes.getYGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(0.0,10.0,0.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices, vertices, st);
};
Ejes.getZGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(0.0,0.0,10.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices,vertices, st);
};
Ejes.getGrillaGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
for(var i=-10; i<0; i+=1)
{
// verticales
vertices.push(i,0,-10);
vertices.push(i,0,10);
// horizontales
vertices.push(-10,0,i);
vertices.push(10,0,i);
}
vertices.push(0,0,-10);
vertices.push(0,0,0);
vertices.push(-10,0,0);
vertices.push(0,0,0);
for(i=1; i<=10; i+=1)
{
// verticales
vertices.push(i,0,-10);
vertices.push(i,0,10);
// horizontales
vertices.push(-10,0,i);
vertices.push(10,0,i);
}
for(i=0; i<84;i+=1)
{
indexVertices.push(i);
}
Geometry.init.call(this,vertices,indexVertices,vertices, vertices);
};
return Ejes;
});
I'd really appreciate any help you could give me.

How to use multiple textures in WebGL?

I wanted to use 6 different textures on a cube, one per side, but can't find the mistake. Here's my current code:
var texturen = new Array();
function initTexture(sFilename,texturen)
{
var anz = texturen.length;
texturen[anz] = gl.createTexture();
texturen[anz].image = new Image();
texturen[anz].image.onload = function()
{
gl.bindTexture(gl.TEXTURE_2D, texturen[anz]);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D
(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texturen[anz].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);
}
texturen[anz].image.src = sFilename;
}
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);
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
var cubeVertexPositionBuffer;
var cubeVertexTextureCoordBuffer;
var cubeVertexIndexBuffer;
var cubeVertexPositionBuffer1;
var cubeVertexTextureCoordBuffer1;
var cubeVertexIndexBuffer1;
function initBuffers() {
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 = 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 = 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 = 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 = 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 = 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 xRot = 0;
var yRot = 0;
var zRot = 0;
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, -5.0]);
mat4.rotate(mvMatrix, degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, degToRad(yRot), [0, 1, 0]);
mat4.rotate(mvMatrix, degToRad(zRot), [0, 0, 0]);
setMatrixUniforms();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texturen[0]);
gl.vertexAttribPointer
(textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer
(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, texturen[1]);
gl.vertexAttribPointer
(textureCoordAttribute, cubeVertexTextureCoordBuffer1.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1);
gl.vertexAttribPointer
(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer1.itemSize,
gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer1);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer1.numItems, gl.UNSIGNED_SHORT, 0);
}
i just divided it into two parts, trying to make a test with 2 different pics. And what are the cubeVertexIndexBuffers for exactly?
First off, the short answer: Replace the last 10 lines of your code with the following and I think it should work.
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texturen[1]);
gl.vertexAttribPointer(textureCoordAttribute, cubeVertexTextureCoordBuffer1.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer1.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
The key changes are:
activeTexture is still TEXTURE0 (you're only using one texture at a time here)
Using cubeVertexIndexBuffer instead of cubeVertexIndexBuffer1, which contained out-of-range indicies
For a better explanation of what the indices are actually used for I'll refer you to this SO question as I'd rather not repeat all that here.
Now, on to the more general answer.
There are two basic ways to handle the issue of using different textures on different faces. The first and simpler method is to do exactly what you are doing here: Render the object in pieces, binding a different texture for each piece. Though not strictly the most efficient way to accomplish the effect it is nevertheless the most common way to handle it in high-performance applications such as games simply because it offers a lot of flexibility, especially when your materials are more complex than a simple diffuse texture.
There is a simple way that you can improve the performance of code like yours for a case like this, though. The vertices/indices don't have to be broken into separate buffers per-texture. You could instead combine them all into a single buffer and render them with different offsets like so:
// On Init
var vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
var vertices = [
// Vertex values for all 6 faces
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
var indices = [
// Index values for all 6 faces
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// On Draw
// Setup the shader and uniforms and all that jazz
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.vertexAttribPointer(// Blah blah blah...);
// Draw face 0
gl.bindTexture(gl.TEXTURE_2D, texture[0]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
// Draw face 1
gl.bindTexture(gl.TEXTURE_2D, texture[1]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 12);
// Draw face 2
gl.bindTexture(gl.TEXTURE_2D, texture[2]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 24);
// .. And so on to face 5
// Draw face 2
gl.bindTexture(gl.TEXTURE_2D, texture[5]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 60);
What's going on here is that each call to drawElements only draws 2 triangles (6 vertices, the second parameter of the call), but each call is offset into the index buffer so that it starts on a different face. (fourth parameter of the call, which indicates a byte offset. Each index is a Uint16, so 2 bytes per index. 12 == "start on index[6]") This way all of the binding and setup only happens once, and each draw call only has to change the state that is actually necessary (the texture).
The other way to handle this, which is faster but harder to generalize, is to bind an array of textures to a shader uniform and use another vertex attribute to index into the array within the shader. I'm not going to detail the code for this approach but it should be relatively easy to set up once you're comfortable with WebGL shader use. If you have further questions about this specific approach it would be best to ask in a different SO question so as not to overload this one.

Multiple Programs in WebGL doesn't work

I'm trying to use multiple shader programs in webgl but continue to get issues.
It seems that if i have a different number of vertex shader attributes in programs then i get nothing rendered with no errors. Is there some constraint that means that programs have to have the same number of attributes? Do i need to disable/enable attribute locations when changing programs?
It seems that just creating multiple programs causes the issue ( i dont even have to use the second shader, just the fact that it is created causes the issue).
To create the attributes i'm using the following snippet (works fine when number of attributes in all programs is the same):
for ( var i=0 ; i<vertexAttributes.length ; i++ )
{
shaderProgram[vertexAttributes[i].name] = gl.getAttribLocation(shaderProgram,vertexAttributes[i].name);
gl.enableVertexAttribArray(shaderProgram[vertexAttributes[i].name]);
}
Sorry for posting such a large chunk of code, but this best illustrates the issue. this is code from one of the learningwebgl.com tutorials, all that i have done is add a second pair of shaders ("shader2-fs" and "shader2-vs") and a new function called initShaders2. if initShaders2 is called in webGLStart() (as it is in the code) then nothing is drawn??? i'm baffled!
<script type="text/javascript" src="two_files/glMatrix-0.js"></script>
<script type="text/javascript" src="two_files/webgl-utils.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<script id="shader2-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
uniform sampler2D uSampler;
void main(void) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
}
</script>
<script id="shader2-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;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
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.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
var shaderProgram2;
function initShaders2() {
var fragmentShader = getShader(gl, "shader2-fs");
var vertexShader = getShader(gl, "shader2-vs");
shaderProgram2 = gl.createProgram();
gl.attachShader(shaderProgram2, vertexShader);
gl.attachShader(shaderProgram2, fragmentShader);
gl.linkProgram(shaderProgram2);
if (!gl.getProgramParameter(shaderProgram2, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram2);
shaderProgram2.vertexPositionAttribute = gl.getAttribLocation(shaderProgram2, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram2.vertexPositionAttribute);
shaderProgram2.vertexNormalAttribute = gl.getAttribLocation(shaderProgram2, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram2.vertexNormalAttribute);
shaderProgram2.textureCoordAttribute = gl.getAttribLocation(shaderProgram2, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram2.textureCoordAttribute);
shaderProgram2.pMatrixUniform = gl.getUniformLocation(shaderProgram2, "uPMatrix");
shaderProgram2.mvMatrixUniform = gl.getUniformLocation(shaderProgram2, "uMVMatrix");
shaderProgram2.nMatrixUniform = gl.getUniformLocation(shaderProgram2, "uNMatrix");
shaderProgram2.samplerUniform = gl.getUniformLocation(shaderProgram2, "uSampler");
shaderProgram2.useLightingUniform = gl.getUniformLocation(shaderProgram2, "uUseLighting");
shaderProgram2.ambientColorUniform = gl.getUniformLocation(shaderProgram2, "uAmbientColor");
shaderProgram2.lightingDirectionUniform = gl.getUniformLocation(shaderProgram2, "uLightingDirection");
shaderProgram2.directionalColorUniform = gl.getUniformLocation(shaderProgram2, "uDirectionalColor");
}
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);
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
var pyramidVertexPositionBuffer;
var pyramidVertexColorBuffer;
var cubeVertexPositionBuffer;
var cubeVertexColorBuffer;
var cubeVertexIndexBuffer;
function initBuffers() {
pyramidVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
var vertices = [
// Front face
0.0, 1.0, 0.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
// Right face
0.0, 1.0, 0.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
// Back face
0.0, 1.0, 0.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
// Left face
0.0, 1.0, 0.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
pyramidVertexPositionBuffer.itemSize = 3;
pyramidVertexPositionBuffer.numItems = 12;
pyramidVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
var colors = [
// Front face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
// Right face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0,
// Back face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
// Left face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
pyramidVertexColorBuffer.itemSize = 4;
pyramidVertexColorBuffer.numItems = 12;
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,
// 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);
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numItems = 24;
cubeVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
colors = [
[1.0, 0.0, 0.0, 1.0], // Front face
[1.0, 1.0, 0.0, 1.0], // Back face
[0.0, 1.0, 0.0, 1.0], // Top face
[1.0, 0.5, 0.5, 1.0], // Bottom face
[1.0, 0.0, 1.0, 1.0], // Right face
[0.0, 0.0, 1.0, 1.0] // Left face
];
var unpackedColors = [];
for (var i in colors) {
var color = colors[i];
for (var j=0; j < 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
cubeVertexColorBuffer.itemSize = 4;
cubeVertexColorBuffer.numItems = 24;
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
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);
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numItems = 36;
}
var rPyramid = 0;
var rCube = 0;
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, [-1.5, 0.0, -8.0]);
mvPushMatrix();
mat4.rotate(mvMatrix, degToRad(rPyramid), [0, 1, 0]);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, pyramidVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, pyramidVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);
mvPopMatrix();
mat4.translate(mvMatrix, [3.0, 0.0, 0.0]);
mvPushMatrix();
mat4.rotate(mvMatrix, degToRad(rCube), [1, 1, 1]);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, cubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
mvPopMatrix();
}
var lastTime = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
rPyramid += (90 * elapsed) / 1000.0;
rCube -= (75 * elapsed) / 1000.0;
}
lastTime = timeNow;
}
function tick() {
requestAnimFrame(tick);
drawScene();
animate();
}
function webGLStart() {
var canvas = document.getElementById("lesson04-canvas");
initGL(canvas);
initShaders2(); // !!!!!!!!!!!!!!!!!!!!!!!!!
initShaders();
initBuffers();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
tick();
}
</script>
</head>
<body onload="webGLStart();">
<< Back to Lesson 4<br>
<canvas id="lesson04-canvas" style="border: none;" width="500" height="500"></canvas>
<br>
<< Back to Lesson 4<br>
</body></html>
You'll probably need to give us a little bit more information, but to get you started here's a quick checklist. Any time you change programs, you'll want to:
Enable the appropriate vertex attribute arrays
Bind the vertex attribute pointers, even if they were already bound to the right buffers
Bind any uniforms needed, like texture samplers.
Basically, you want to treat every time you change programs as if it's the first time you're setting up a draw call.

Categories