I am working on WebGL and I have made some classes to make rendering easier. The problem is, that only the first class can be rendered and all other classes aren't rendered. I looked for every array buffer and bind and unbind them when needed but it still doesn't work. This is my class for a triangleElementCluster:
function TriangleElementCluster(vertices, uvs, normals, indices, indicesLenght, shader, gl) {
shader.use();
var verticesBuffer = new ArrayBufferFloat(vertices, gl);
var verticesAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "vertex", 3, 3, 0, gl);
var uvsBuffer = new ArrayBufferFloat(uvs, gl);
var uvsAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "uv", 2, 2, 0, gl);
var normalsBuffer = new ArrayBufferFloat(normals, gl);
var normalsAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "normal", 3, 3, 0, gl);
var indicesBuffer = new ElementArrayBuffer16(indices, gl);
verticesBuffer.unbind();
verticesAttribLocation.unbind();
uvsBuffer.unbind();
uvsAttribLocation.unbind();
normalsBuffer.unbind();
normalsAttribLocation.unbind();
indicesBuffer.unbind();
this.setTexture = function(texture) {
this.texture = texture;
}
this.render = function() {
verticesBuffer.bind();
verticesAttribLocation.bind();
uvsBuffer.bind();
uvsAttribLocation.bind();
normalsBuffer.bind();
normalsAttribLocation.bind();
indicesBuffer.bind();
this.texture.activate(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, indicesLenght, gl.UNSIGNED_SHORT, 0);
verticesBuffer.unbind();
verticesAttribLocation.unbind();
uvsBuffer.unbind();
uvsAttribLocation.unbind();
normalsBuffer.unbind();
normalsAttribLocation.unbind();
indicesBuffer.unbind();
}
}
These are the classes for ArrayBuffers and VertexAttribPoints:
function ArrayBufferFloat(array, gl) {
this.arrayBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.arrayBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
this.unbind = function() {
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
this.bind = function() {
gl.bindBuffer(gl.ARRAY_BUFFER, this.arrayBuffer);
}
}
function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);
gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
gl.enableVertexAttribArray(attribLocation);
console.log(attribLocation);
this.bind = function() {
gl.enableVertexAttribArray(attribLocation);
}
this.unbind = function() {
gl.disableVertexAttribArray(attribLocation);
}
}
You might have noticed that I print the ID of the VertexAttribPointer and I get: 2 0 1 2 0 1 I have two classes and both of them are using the same pointers, this shouldn't happen, what could lead to this?
From my understanding of OpenGL every buffer etc. is deactivated after the triangles have been drawn. Where is the error that leads to only drawing the first class?
This
function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);
gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
gl.enableVertexAttribArray(attribLocation);
console.log(attribLocation);
this.bind = function() {
gl.enableVertexAttribArray(attribLocation);
}
this.unbind = function() {
gl.disableVertexAttribArray(attribLocation);
}
}
Needs to be this
function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);
this.bind = function() {
gl.enableVertexAttribArray(attribLocation);
gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
}
this.unbind = function() {
gl.disableVertexAttribArray(attribLocation);
}
}
And your program usage need to be moved to render
function TriangleElementCluster(vertices, uvs, normals, indices, indicesLenght, shader, gl) {
this.render = function() {
shader.use();
...
}
}
You don't actually need any of the unbinds what-so-ever BTW
You can think of bind as similar to just setting global variables.
const state = {
temp1: 0,
temp2: 0,
temp3: 0,
result: 0,
};
function add() { state.result = state.temp1 + state.temp2; }
function sub() { state.result = state.temp1 - state.temp2; }
function sum() { state.result = state.temp1 + state.temp2 + state.temp3; }
function bind(id, value) { state[id] = value; }
function get(id) { return state[id]; }
bind('temp1', 1);
bind('temp2', 2);
bind('temp3', 3);
sum();
console.log('sum:', get('result'));
bind('temp1', 4);
bind('temp2', 5);
add();
console.log('add:', get('result'));
Notice I don't unbind anything. I just bind the things I need for the next function to run. It's the same in WebGL though the state is more complicated
Related
I'm creating a pinball game using three.js and ammo.js and am having issues rotating the flippers using enableAngularMotor when using bufferGeometry cloned from a loaded GLTF file, when the same code using a BoxBufferGeometry works ok.
The original test build I had a threejs BoxBufferGeometry block wired up to the hinge, and got that working. I have shifted the code to the loaded callback on the gltf loader in three.js and the geometry from the new nicer model clones ok, and can be read, but the same hinge wiring code doesn't seem to rotate the flipper.
var loader = new THREE.GLTFLoader();
let mass = ms;
loader.load(whichFile,function ( gltf ) {
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Scene
gltf.scenes; // Array<THREE.Scene>
gltf.cameras; // Array<THREE.Camera>
gltf.asset; // Object
gltf.scene.scale.set(Size[0],Size[1],Size[2]);
gltf.scene.position.set(Pos[0],Pos[1],Pos[2]);
gltf.asset.castShadow = true;
gltf.asset.receiveShadow = true;
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
let geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
let qCircX = new THREE.Mesh(geometry, child.material);
//scene.add(qCircX);
qCircX.scale.set(Size[0],Size[1],Size[2]);
qCircX.position.set(Pos[0],Pos[1],Pos[2]);
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
child.geometry = new THREE.BufferGeometry().fromGeometry( geometry );
let qCirc = new THREE.Mesh(child.geometry, child.material);
qCirc.scale.set(Size[0],Size[1],Size[2]);
qCirc.position.set(Pos[0],Pos[1],Pos[2]);
qCirc.castShadow = true;
qCirc.receiveShadow = true;
scene.add(qCirc);
let transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin( new Ammo.btVector3( Pos[0],Pos[1],Pos[2] ) );
let motionState = new Ammo.btDefaultMotionState( transform );
let vertices, face, triangles = [];
vertices = geometry.vertices;
vertices = generateVertexMesh(geometry, vertices, triangles);
let i, triangle, triangle_mesh = new Ammo.btTriangleMesh;
let _vec3_1 = new Ammo.btVector3(0,0,0);
let _vec3_2 = new Ammo.btVector3(0,0,0);
let _vec3_3 = new Ammo.btVector3(0,0,0);
for ( i = 0; i < triangles.length; i++ ) {
triangle = triangles[i];
_vec3_1.setX(triangle[0].x);
_vec3_1.setY(triangle[0].y);
_vec3_1.setZ(triangle[0].z);
_vec3_2.setX(triangle[1].x);
_vec3_2.setY(triangle[1].y);
_vec3_2.setZ(triangle[1].z);
_vec3_3.setX(triangle[2].x);
_vec3_3.setY(triangle[2].y);
_vec3_3.setZ(triangle[2].z);
triangle_mesh.addTriangle(
_vec3_1,
_vec3_2,
_vec3_3,
true
);
}
let colSurround = new Ammo.btBvhTriangleMeshShape( triangle_mesh, true, true );
let localInertia = new Ammo.btVector3( 0, 0, 0 );
colSurround.calculateLocalInertia( mass, localInertia );
let rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, colSurround, localInertia );
let body = new Ammo.btRigidBody( rbInfo );
body.setRestitution(rest);
qCirc.userData.physicsBody = body;
qCirc.name = objName;
collidableMeshList.push(qCirc);
if(addToScoreColliders){
scoreList.push(objName);
}
//console.log(ballArray);
if ( mass > 0 ) {
rigidBodies.push( qCirc );
//console.log(rigidBodies);
body.setActivationState( 4 );
}
physicsWorld.addRigidBody( body );
if(objName == "flipperL"){
let pos = {x:-16,y:0,z:27}, posBumper = {x:0,y:0,z:0}, scaleHinge = {x:1,y:1,z:1}, scaleBumper = {x:1,y:1,z:1}, quat = {x:0,y:0,z:0,w:1}, quatBumper = {x:0,y:0,z:0,w:1}, mass = 0, massBumper = 9;
// create the hinge and bumper objects
leftHinge = createPhysicsGeometry(0xff0000,pos,scaleHinge,quat,mass,"leftHinge",0,[0,0], true);
// Hinge constraint to move the bumper
let pivotA = new Ammo.btVector3( 0, 0.5, 0 ),pivotB = new Ammo.btVector3( -1.5, -3, 0 ),axis = new Ammo.btVector3( 0, 1, 0 );
leftHingeConstraint = new Ammo.btHingeConstraint( leftHinge.userData.physicsBody, qCirc.userData.physicsBody, pivotA, pivotB, axis, axis, true );
leftHingeConstraint.setLimit(0, Math.PI/2 * 0.5, 0.9, 0.3, 1);
physicsWorld.addConstraint( leftHingeConstraint, true );
leftHingeActive = true;
bumperGeoms[0] = qCirc;
}
if(objName == "flipperR"){
let pos = {x:16,y:0,z:27}, posBumper = {x:0,y:0,z:0}, scaleHinge = {x:1,y:1,z:1}, scaleBumper = {x:1,y:1,z:1}, quat = {x:0, y:0, z:0, w: 1},quatBumper = {x:0,y:0,z:0,w:1}, mass = 0, massBumper = 9;
// create the hinge and bumper objects
rightHinge = createPhysicsGeometry(0xff0000,pos,scaleHinge,quat,mass,"rightHinge",0,[0,0], true);
// Hinge constraint to move the bumper
let pivotA = new Ammo.btVector3( 0, 0.5, 0 ),pivotB = new Ammo.btVector3( 1.5, -3, 0 ),axis = new Ammo.btVector3( 0, 1, 0 );
//console.log(bumperArray);
rightHingeConstraint = new Ammo.btHingeConstraint( rightHinge.userData.physicsBody, qCirc.userData.physicsBody, pivotA, pivotB, axis, axis, true );
rightHingeConstraint.setLimit(-Math.PI/2 * 0.5, 0, 0.9, 0.3, 1);
physicsWorld.addConstraint( rightHingeConstraint, true );
rightHingeActive = true;
bumperGeoms[1] = qCirc;
}
}
});
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened : ' + error );
});
}```
When an area of the screen is pressed, the angular motor is enabled with a multiplier to turn the flipper, whereas now the flipper doesn't rotate. I don't get any errors logging to the console, and logging geometry to check it's loaded ok is fine.
Ok, so I took an alternate approach and make the gltf scene a child of the existing simple cuboid flipper.
function Luminary(radius, orbitRadius, speed, children) {
this.radius = radius;
this.orbitRadius = orbitRadius;
this.speed = speed;
this.children = children;
}
function initSolarSystem() {
var moon = new Luminary(0.02, 0.2, 0.0015, []);
var earth = new Luminary(0.1, 0.7, 0.001, [moon]);
var sun = new Luminary(0.3, 0.0, 0.0, [earth]);
return sun;
}
var solarSystem = initSolarSystem();
I have the code above in JS. How can I access for example the radius of earth using the solarSystem object? The following returns Undefined
alert(solarSystem.children.radius);
How should I call children in a recursive function as follows:
function draw(obj) {
// draw Current Object
if (obj.children != undefined) {
draw(obj.children);
}
}
draw(solarSystem);
Can Someone please help me?
I have the code above in JS. How can I access for example the radius
of earth using the solarSystem object? The following returns Undefined
alert(solarSystem.children.radius);
solarSystem.children is an array, so use solarSystem.children[0].radius
How should I call children in a recursive function as follows.
function draw(obj)
{
// draw Current Object
if (obj.children != undefined)
{
obj.children.forEach( s => draw(s) ); //invoke draw in a loop
//draw(obj.children[0]); //use
}
}
draw(solarSystem);
First of all your .children is an array. so call .children[i].radius.
Second:
if (obj.children != undefined) {
draw(obj.children);
}
You call here once the draw function for the full children array. So you need to implement a for loop.
For this there are a lot options this is my approach:
function Luminary(name, radius, orbitRadius, speed, children = []) {
this.name = name;
this.radius = radius;
this.orbitRadius = orbitRadius;
this.speed = speed;
this.children = children;
}
function initSolarSystem() {
var moon = new Luminary("moon", 0.02, 0.2, 0.0015);
var earth = new Luminary("earth", 0.1, 0.7, 0.001, [moon]);
var sun = new Luminary("sun", 0.3, 0.0, 0.0, [earth]);
return sun;
}
var solarSystem = initSolarSystem();
function draw(obj) {
// Draw current object.
for (let key in obj.children)
if (obj.children.hasOwnProperty(key)) {
//if (typeof(obj.children) == "array") {
console.log(obj.children[key].radius);
draw(obj.children[key]);
}
}
draw(solarSystem);
I am trying to render a model under multiple light sources using multiple drawElement calls with different light sources. The gist of the code is as follows.
this.setUniform("u_matrix", "Matrix4fv", false, matrix);
this.setUniform("u_nMatrix", "Matrix3fv", false, nMatrix);
this.setUniform("u_kSpecular", "3fv", material.specular);
this.setUniform("u_kDiffuse", "3fv", material.diffuse);
this.setUniform("u_kAmbient", "3fv", material.ambient);
this.setUniform("u_shininess", "1f", material.shininess);
this.setVertexAttribArray("a_position", new Float32Array(mesh.vertices), 3);
this.setVertexAttribArray("a_normal", new Float32Array(mesh.vertexNormals), 3);
this.setElementArray(new Uint16Array(mesh.indices));
for(var i = 0;i < lights.length;i++) {
if(i == 1) {
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE);
gl.blendEquation(gl.FUNC_ADD);
}
var light = lights[i];
console.dir(light);
this.setUniform("u_lightType", "1i", light.type);
this.setUniform("u_lightVector", "3fv", light.vector);
this.setUniform("u_lightColor", "3fv", light.color);
gl.drawElements(gl.TRIANGLES, mesh.indices.length, gl.UNSIGNED_SHORT, 0);
}
gl.disable(gl.BLEND);
The issue here is that only the first lighting is rendered. Subsequent drawElements do not render anything. I do not think the issue is with my shader code, because the issue persists even if I strip the shader down to just set fragment color equal to the light type or some such parameter.
setUniform setVertexAttribArray and setElementArray are some helpers that i have written. They basically look like this:
setElementArray: function(array) {
var gl = this.gl;
var buffer = this._arrBuffers.__indexBuffer;
if(_.isUndefined(buffer)) {
buffer = gl.createBuffer();
this._arrBuffers.__indexBuffer = buffer;
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, array, gl.STATIC_DRAW);
}
setVertexAttribArray: function(name, array, size, type, normalized, stride, offset) {
var gl = this.gl;
size = size || 2;
type = type || gl.FLOAT;
normalized = normalized || false;
stride = stride || 0;
offset = offset || 0;
var buffer = this._arrBuffers[name];
if(_.isUndefined(buffer)) {
buffer = gl.createBuffer();
this._arrBuffers[name] = buffer;
}
var location = this.getLocation(name, true);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, size, type, normalized, stride, offset);
}
I have found the solution. I had set gl.depthFunc(gl.LESS), so subsequent renderings failed the depth test. Setting gl.depthFunc(gl.LEQUAL) solved the problem.
I created a mesh in Blender and called it "Walking.babylon". I set it up in my code just how it states in the babylon tutorial:
///<reference path="/ref script/babylon.1.14-debug.js"/>
"use strict"
var canvas;
var engine;
var scene;
document.addEventListener("DOMContentLoaded", startBabylonJS, false);
function startBabylonJS() {
if (BABYLON.Engine.isSupported()) {
canvas = document.getElementById("renderCanvas");
engine = new BABYLON.Engine(canvas, true);
scene = new BABYLON.Scene(engine);
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
light.position = new BABYLON.Vector3(20, 150, 70);
//create the camera that will view our scene
var cam = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
cam.setTarget(new BABYLON.Vector3.Zero());
cam.attachControl(canvas, false);
scene.ambientColor = new BABYLON.Color3(0.3, 0.3, 0.3);
// Ground
var ground = BABYLON.Mesh.CreateGround("ground", 1000, 1000, 1, scene, false);
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.2, 0.2);
groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
ground.material = groundMaterial;
ground.receiveShadows = true;
// Shadows
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// Dude
BABYLON.SceneLoader.ImportMesh("man", "Scenes/Models/Animation/", "Walking.babylon", scene, function (newMeshes, particleSystems, skeletons) {
var dude = newMeshes[0];
for (var index = 0; index < newMeshes.length; index++) {
shadowGenerator.getShadowMap().renderList.push(newMeshes[index]);
}
dude.rotation.y = Math.PI;
dude.position = new BABYLON.Vector3(0, 0, -80);
scene.beginAnimation(skeletons[0], 0, 100, true, 1.0);
});
//Once the scene is loaded, just register a render loop to render it
engine.runRenderLoop(function () {
scene.render();
});
//Resize
window.addEventListener("resize", function () {
engine.resize();
});
}
}
But When I load my scene and hit F12 I get this message in the console: Failed to load resource: the server responded with a status of 404 (Not Found) and right next to it is this link: http://localhost:50207/Scenes/Models/Animation/Walking.babylon.manifest?1419869394361
So my question is: what am I doing wrong that is causing my animated mesh not to show?
Open notepad and put this:
{
"version" : 1,
"enableSceneOffline" : true,
"enableTexturesOffline" : true
}
Then rename it: Walking.babylon.manifest
And put it where "Walking.babylon" is.
I'm trying to render a few objects to a canvas and I'm having a bit of trouble understanding what's not working.
I'm building two objects at the moment that represent the two meshes that I want to render. If I create one mesh the code works fine so the problem, I think, is that the data gets screwed up when I'm building two or more.
Here's an example of the mesh data:
"name":"cone",
"buffers":{
"vertexPosition":{}, // Buffer
"vertexIndex":{} // Buffer
},
"mesh":{
"vertices":[], // emptied it to fit on page
"faces":[] // emptied it to fit on page
},
"mvMatrix": Float32Array[16],
"itemSize":3,
"numItems":12,
"program":{
"vertexPosAttrib":0,
"mvMatrixUniform":{},
"pMatrixUniform":{}
}
This is build from this function:
buildMeshData: function(){
this.mvMatrix = mat4.create();
this.buffers.vertexPosition = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.vertexPosition);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.mesh.vertices), gl.STATIC_DRAW);
this.buffers.vertexIndex = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.buffers.vertexIndex);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.mesh.faces), gl.STATIC_DRAW);
this.itemSize = 3;
this.numItems = this.mesh.faces.length;
var vertexProps = {
attributes: ['vec3', 'VertexPosition'],
uniforms: ['mat4', 'MVMatrix', 'mat4', 'PMatrix'],
varyings: ['vec3', 'TexCoord']
}
var vertexShaderFunction = 'vTexCoord = aVertexPosition + 0.5; gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1);';
var vshaderInput = utils.buildVertexShader(vertexProps, vertexShaderFunction);
var fragmentProps = {
attributes: [],
uniforms: [],
varyings: ['vec3', 'TexCoord']
}
var fragmentShaderFunction = 'gl_FragColor = vec4(vTexCoord, 1);';
var fshaderInput = utils.buildFragmentShader(fragmentProps, fragmentShaderFunction);
this.program = gl.createProgram();
var vshader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vshader, vshaderInput);
gl.compileShader(vshader);
var fshader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fshader, fshaderInput);
gl.compileShader(fshader);
gl.attachShader(this.program, vshader);
gl.attachShader(this.program, fshader);
gl.linkProgram(this.program);
gl.useProgram(this.program);
this.program.vertexPosAttrib = gl.getAttribLocation(this.program, 'aVertexPosition');
gl.vertexAttribPointer(this.program.vertexPosAttrib, this.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.program.vertexPosAttrib);
this.program.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");
this.program.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
scene.add(this);
}
and the render function goes like this:
function render(){
currentTime = new Date().getTime();
deltaTime = (currentTime - initialTime) / 1000; // in seconds
gl.viewport(0, 0, stage.width, stage.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
for(var i in scene.meshes){
(function(mesh){
mat4.translate(mesh.mvMatrix, mesh.mvMatrix, [0, 2 * i, -10 - (10 * i)]);
gl.useProgram(mesh.program);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.vertexIndex);
gl.vertexAttribPointer(mesh.program.vertexPosAttrib, mesh.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(mesh.program.vertexPosAttrib);
gl.uniformMatrix4fv(mesh.program.mvMatrixUniform, false, mesh.mvMatrix);
gl.uniformMatrix4fv(mesh.program.pMatrixUniform, false, scene.pMatrix);
gl.drawElements(gl.TRIANGLES, mesh.numItems, gl.UNSIGNED_SHORT, 0);
gl.disableVertexAttribArray(mesh.program.vertexPosAttrib);
})(scene.meshes[i])
}
// requestAnimationFrame(render);
}
The result of this is the second object is drawn correctly but the first causes the error:
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0
...and is therefore not drawn.
Any ideas where the problem lies. Hopefully thats enough information from the code, I didn't want to put up too much, but if you need to see anything else I'll update.
This code
gl.vertexAttribPointer(this.program.vertexPosAttrib, this.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.program.vertexPosAttrib);
Need to be called when drawing each mesh and not where it's called now. Additionally before calling gl.vertexAttribPointer for this.program.vertexPosAttrib you need to call
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertexPosition);
Because gl.vertexAttribPointer binds the buffer currently bound to gl.ARRAY_BUFFER to the specified attribute.
In other words
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertexPosition);
gl.vertexAttribPointer(mesh.program.vertexPosAttrib, mesh.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(mesh.program.vertexPosAttrib);