WebGL Element Array Buffers not working - opengl-es

I'm learning WebGL with haxe and I'm stuck on the part describing element arrays. What is suppose to be a square isn't showing up and I dont know why?
var verticesArray = [
0.5, 0.5,
0.5,-0.5,
-0.5,-0.5,
-0.5, 0.5
];
var indicesArray = [0, 1, 3, 1, 2, 3];
var VBO = GL.createBuffer();
GL.bindBuffer(GL.ARRAY_BUFFER, VBO);
GL.bufferData(GL.ARRAY_BUFFER,new Float32Array(verticesArray), GL.STATIC_DRAW);
var EBO = GL.createBuffer();
GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, EBO);
GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new UInt16Array(indicesArray), GL.STATIC_DRAW);
GL.vertexAttribPointer(0, 2, GL.FLOAT, false, 0, 0);
GL.enableVertexAttribArray(0);
GL.useProgram(shaderProgram);
GL.drawElements(GL.TRIANGLES, 6, GL.UNSIGNED_INT, 0);
GL.bindBuffer(GL.ARRAY_BUFFER, null);
GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);
Here's all the code that's suppose to draw the square I have got the shader programing working for sure

Make sure the type in your call to drawElements matches the provided index array type, which is
gl.UNSIGNED_BYTE for Uint8Array
gl.UNSIGNED_SHORT for Uint16Array
gl.UNSIGNED_INT for Uint32Array (needs OES_element_index_uint extension)
Also VertexAttribPointer and enableVertexAttribArray calls always operate on the buffer currently bound to the ARRAY_BUFFER target, which in this case isn't a problem, but very well become one the way you wrote it if you add additional VBOs. So either set them after creating and binding the buffer or make otherwise sure the correct buffer is bound.

Related

threejs applyMatrix4 appears to do nothing

The method applyMatrix4 seems like it does nothing...
Why can I not apply this transformation matrix to my vector?
const vec = new THREE.Vector3(1,1,1)
const geometry = new THREE.BoxGeometry(1,1,1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
mesh.rotateX(Math.PI)
const rotatedVec = vec.applyMatrix4(mesh.matrix)
console.log(rotatedVec)
Expectation (taking the cross product):
{x: 1, y: -1, z: -1}
Reality (the vector is unchanged)
{x: 1, y: 1, z: 1}
My mesh's matrix has changed - it is not the identity matrix.
[
[1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1],
]
Object3D.rotateX() only affects the object's quaternion property. It does not update its local matrix. If you say your matrix has changed, I assume you have checked it at a later point when other engine logic triggers a recalculation.
You can solve this issue by adding mesh.updateMatrix(); after you have called Object3D.rotateX().
Or even better use Vector3.applyQuaternion(). In this way, you don't have to recompute the matrix because you don't need it anyway.
const rotatedVec = vec.applyQuaternion(mesh.quaternion)

three.js set objects in local coordinate system of another object

I was wondering if it is possible to place 3d objects within a local coordinate system of another object in three.js. so the placed objects should be relative to the "origin" object.
for example: i scan an image with the device camera (with expo AR) and want to place objects which got a fixed distance to the image. I think these positions are relative to the camera, isn't it?
this.scene.add(chair)
chair.position.set( 1, 0, -5);
this.scene.add(chair2)
chair2.position.set( 1, 0 , -3);
I think what you're looking for is the THREE.Group object. It lets you nest elements in a group, so if you change the coordinates of the group, its children move with it. For instance:
// Create parent, set its pos to 0, 5, 0
var parent = new THREE.Group();
scene.add(parent);
parent.position.set(0, 5, 0);
// create child, and add to parent
var chair1 = new THREE.Mesh(geom, mat);
parent.add(chair1);
chair1.position.set(1, 0, 0);
// create child, and add to parent
var chair2 = new THREE.Mesh(geom, mat);
parent.add(chair2);
chair2.position.set(0, 1, 0);
chair1 will be at [1, 5, 0] in global coordinates, but [1, 0, 0] in local space.
chair2 will be at [0, 6, 0] in global coordinates, but [0, 1, 0] in local space.

Orbiting a cube in WebGL with glMatrix

https://jsfiddle.net/sepoto/Ln7qvv7w/2/
I have a base set up to display a cube with different colored faces. What I am trying to do is set up a camera and apply a combined X axis and Y axis rotation so that the cube spins around both axis concurrently. There seems to be some problems with the matrices I set up as I can see the blue face doesn't look quite right. There are some examples of how this is done using older versions of glMatrix however the code in the examples no longer works because of some changes in vec4 of the glMatrix library. Does anyone know how this can be done using the latest version of glMatrix as I have attached a CDN to the fiddle?
Thank you!
function drawScene() {
gl.viewport(0,0,gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.ortho( mOrtho, -5, 5, 5, -5, 2, -200);
mat4.identity(mMove);
var rotMatrix = mat4.create();
mat4.identity(rotMatrix);
rotMatrix = mat4.fromYRotation(rotMatrix, yRot,rotMatrix);
rotMatrix = mat4.fromXRotation(rotMatrix, xRot,rotMatrix);
mat4.multiply(mMove, rotMatrix, mMove);
setMatrixUniforms();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
yRot += 0.01;
xRot += 0.01;
}
As the name says, fromYRotation() initializes a matrix to a given rotation. Hence, you need two temporary matrices for the partial rotations, which you can then combine:
var rotMatrix = mat4.create();
var rotMatrixX = mat4.create();
var rotMatrixY = mat4.create();
mat4.fromYRotation(rotMatrixY, yRot);
mat4.fromXRotation(rotMatrixX, xRot);
mat4.multiply(rotMatrix, rotMatrixY, rotMatrixX);
And the reason why your blue face was behaving strangely, was the missing depth test. Enable it in your initialization method:
gl.enable(gl.DEPTH_TEST);
You dont need to use three matrices:
// you should do allocations outside of the renderloop
var rotMat = mat4.create();
// no need to set the matrix to identity as
// fromYRotation resets rotMats contents anyway
mat4.fromYRotation(rotMat, yRot);
mat4.rotateX(rotMat,xRot);

WebGL error when attempting to get color data from vec4

I'm having an issue while rendering a square in WebGL. When I run the program in Chrome, I'm getting the error:
GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 0
I've assumed this is because, at some point, the buffers are looking at the wrong arrays when trying to get data. I've pinpointed the issue to the
gl.vertexAttribPointer(pColorIndex, 4, gl.FLOAT, false, 0, 0);
line in the code below. i.e. if I change the 4 to a 2, the code will run, but not properly (as I'm looking at a vec4 for color data here). Is there an issue with the way my arrays are bound?
bindColorDisplayShaders();
// clear the framebuffer
gl.clear(gl.COLOR_BUFFER_BIT);
// bind the shader
gl.useProgram(shader);
// set the value of the uniform variable in the shader
var shift_loc = gl.getUniformLocation(shader, "shift");
gl.uniform1f(shift_loc, .5);
// bind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, vertexbuffer);
// get the index for the a_Position attribute defined in the vertex shader
var positionIndex = gl.getAttribLocation(shader, 'a_Position');
if (positionIndex < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
// "enable" the a_position attribute
gl.enableVertexAttribArray(positionIndex);
// associate the data in the currently bound buffer with the a_position attribute
// (The '2' specifies there are 2 floats per vertex in the buffer. Don't worry about
// the last three args just yet.)
gl.vertexAttribPointer(positionIndex, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// bind the buffer with the color data
gl.bindBuffer(gl.ARRAY_BUFFER, chosencolorbuffer);
var pColorIndex = gl.getUniformLocation(shader, 'a_ChosenColor');
if(pColorIndex < 0){
console.log('Failed to get the storage location of a_ChosenColor');
}
gl.enableVertexAttribArray(pColorIndex);
gl.vertexAttribPointer(pColorIndex, 4, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// draw, specifying the type of primitive to assemble from the vertices
gl.drawArrays(gl.TRIANGLES, 0, numPoints);
You can only use either a uniform or a vertex attribute,
this are two different things.
When using a vertex attribute you have to match the amount of vertices in your position buffer, and get the location using gl.getAttribLocation.
When using a uniform you're not supplying its data via array buffers but using the gl.uniform* methods to set their value.
In your example gl.uniform4fv(pColorIndex, yourColorVector).

WebGL Jagged Edges (Anti-Aliasing)

So I'm currently rendering my terrain using vertices and color data only (no indices, no textures), and maybe when I add textures in later the problem will fix itself. Both at a distance and close up, I seem to be getting jagged edges where the edge of the terrain meets the background.
It seems like this problem could be fixed by using antialiasing/multisampling, but I was under the impression that by setting up a WebGL context with default parameters, it will use antialiasing by default so this shouldn't be a problem.
Here's what the problem looks like:
Here's my context init code:
gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
return;
}
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
By passing no additional options to setupWebGL, I'm assuming it'll use the default of using antialiasing...
Here's the applicable init code:
this.buffers['Position'] = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers[attrib]);
gl.bufferData(gl.ARRAY_BUFFER, this.getData(attrib), gl.STATIC_DRAW);
this.buffers['Color'] = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers[attrib]);
gl.bufferData(gl.ARRAY_BUFFER, this.getData(attrib), gl.STATIC_DRAW);
Here's the applicable draw code:
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers['Position']);
gl.vertexAttribPointer(
this.shader.getAttribute('Position'),
this.getItemSize('Position'),
gl.FLOAT,
false,
0,
0
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers['Color']);
gl.vertexAttribPointer(
this.shader.getAttribute('Color'),
this.getItemSize('Color'),
gl.FLOAT,
false,
0,
0
);
gl.drawArrays(gl.TRIANGLES, 0, this.getNumItems());
Anti-aliasing seems to be force-disabled in WebGL on the hardware I was using (MacBook Air, Intel HD 4000).

Resources