WebGL's zBuffer doesn't work - javascript

Does WebGL have a zBuffer or depth?
So here's my problem:
The cube is being cropped or not being rendered properly. Setting the 'z' coordinates beside 0 and 1 results to object / geometry being cropped / cut.
Additionaly I've already implemented this on C++ and it works properly just porting it webGL and OpenGL ES.
Here's my persepective view configuration:
mat4.perspective(45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0, pMatrix);
also tried setting the zFar to a much more larger value but the result are the same.
Here's the code that I used for vector translation:
mat4.translate(mvMatrix, mvMatrix, [0.0, 0.0, 2.0]);
and also tried this to check if there's a problem on the mat4.translate function this:
var x = 0.0, y = 0.0, z = 2.0;
var position = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1,
];
mat4.multiply(mvMatrix, mvMatrix, position);
Also check and tried setting the values directly in Vertex Shader:
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition.x, aVertexPosition.y, 2.0, 1.0);
Update:
Also set to enabled the DEPTH_TEST.
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);

Finally, I solved it, the cause of the problem is due to invalid argument parameters and outdated tutorials on the internet regarding usage of the gl-matrix.js library.
mat4.perspective(45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0, pMatrix);
whereas of the new gl-matrix parameters should be like this:
mat4.perspective(pMatrix, 45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0);
After checking the correct documentation of the JS library.

If you apply a projection, you normally look from the origin in the direction of the negative z-axis. So I think you need a translation by a negative value in z-direction to get your geometry in view, while you translate by [0.0, 0.0, 2.0].
You say you're trying to draw a cube, but your vertex shader hardwires all z-coordinates to 2.0. You can't really get any kind of 3-dimensional shape if you're using the same z-coordinate for all vertices. Well, you technically could, but I doubt that this is what you want.

Related

why rotation speed increases as i create new sphere using webgl at same position

There is something strange going on, i am drawing a sphere dynamically using lesson11 of github.com on link http://learningwebgl.com/blog/?p=1253 ,
By dynamically mean i am taking latitudeBands and longitudeBands from the user at run time and he may change them run time to form a new sphere. (User has a choice to select at run time the latitudeBands and longitudeBands values from the given UI item option in html)
I am creating sphere using those latitudeBands and longitudeBands using the same concepts as on this link and it works fine and which i auto rotate by doing like this:
//rotation is at the end of the loop method 'tick'
function tick() {
requestAnimFrame(tick);
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);
gl.uniform1i(shaderProgram.useLightingUniform, false);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0, 0, -6]);
mat4.multiply(mvMatrix, RotationMatrix);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, imageTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, VertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, VertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, VertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, VertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, VertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, VertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, VertexIndexBuffer);
setMatrixUniforms();
/*Rotation code is below*/
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(5 / 10), [0, 1, 0]);
mat4.multiply(newRotationMatrix, RotationMatrix, RotationMatrix);
gl.drawElements(gl.TRIANGLES, VertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
Where is the problem ?
The problem is for the first time when i select the value dynamically it works fine. But when i select another(on second time or more) value for latitudeBands and longitudeBands at runtime from UI then the rotation speed becomes faster then previous rotation of sphere
and speed of rotation keeps on increasing as i select again and again dynamic latitudeBands and longitudeBands values.
Why this strange behavior, why it increases the speed of rotation for newly formed sphere by selected latitudeBands and longitudeBands, The rotation speed is supposed to be same as i re-draw a new sphere with new latitudeBands and longitudeBands values at same position?
How to avoid it ?
EDIT1:
var RotationMatrix = mat4.create();
mat4.identity(RotationMatrix);
and setMatrixUniforms() is
function setMatrixUniforms()
{
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
var normalMatrix = mat3.create();
mat4.toInverseMat3(mvMatrix, normalMatrix);
mat4.transpose(normalMatrix);
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
}
Could it be the reason that some matrice is not refreshed, or the rotation keeps on increasing with previous value?
I think mat4.multiply(newRotationMatrix, RotationMatrix, RotationMatrix); should be mat4.multiply(newRotationMatrix, RotationMatrix, newRotationMatrix); ?

How to encode and send float data to GLSL from Javascript/THREE.js and decode results

I would like to encode object positions (x,y,z) and send to a GLSL shader, decode the data, perform some calculations and send the results back to the CPU. I have researched this issue and have found partial answers like decode rgb value to single float without bit-shift in glsl, but I have not been successful in encoding and decoding the results.
Here is a part of my code.`...
function init() {
...
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
]),
gl.STATIC_DRAW
);
texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
vec1 = new THREE.Vector3(2.6, 3.3, 100.80); //example position vector
data = new Uint8Array([float2Color(vec1.x).r, float2Color(vec1.x).g, float2Color(vec1.x).b, 255, //x
float2Color(vec1.y).r, float2Color(vec1.y).g, float2Color(vec1.y).b, 255, //y
float2Color(vec1.z).r, float2Color(vec1.z).g, float2Color(vec1.z).b, 255 //z
]);
// This encodes to give me int8Array [ 2, 0, 0, 255, 3, 0, 0, 255, 100, 0, 2 more… ]
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
}
//render function
function render() {
...
gl.drawArrays(gl.POINTS, 0, 2);
var pixels = new Uint8Array(WIDTH * HEIGHT * 4);
gl.readPixels(0, 0, WIDTH, HEIGHT, gl.RGBA, gl.FLOAT, pixels);
pixels = new Uint8Array(pixels.buffer);
//After getting the results from GLSL, pixels now look like this
//Uint8Array [ 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, … ]
var color = {
r: pixels[0],
g: pixels[1],
b: pixels[2]
};
float1 = decodeVec3ToFloat(color); // I would like to decode and use the data after the position is updated in GLSL
}
function float2Color( f ) {
b = Math.floor(f / 255.0 / 255.0);
g = Math.floor((f - (b * 255.0 * 255.0) ) / 255.0);
// r = Math.floor(f - (b * 255.0 * 255.0) - (g * 255.0) );
r = Math.floor(f % 255);
return {r:r, g:g, b:b};
}
function decodeVec3ToFloat(color) {
var result;
result = color.r * 255.0;
result += color.g * 255.0 * 255.0;
result += color.b * 255.0 * 255.0 * 255.0;
return result;
}
I've been working with this sort of thing myself. You can use DataTextures to achieve this, and pass them in and out as buffers manipulated by a simulation shader. The best example I've found so far uses a dated version of Three.js (v58) but can be easily updated. I found it helpful to get the scripts updated and then toy around with it until I understood it well enough for my use case. Note that in the example there are even fixed values passed through in the simulation shader, as well as the changing x,y,z values that are rendered in and out on the buffers. Good luck!
UPDATE:
I have since discoverer that the old THREE.FBOUtils script I was using above has been updated and reworked and is now called THREE.GPUComputationRenderer -- works great! (v80)

Two Viewports for stereoscopic 3D without three.js

Is it possible to create a stereoscopic 3D vision of my scene, easilly, without resorting to three.js?
I thought about 2 canvas or two viewports, but I don't know if it's possible to do so, so I've started by trying to create a new viewport, but it just stays black and only shows the second.
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth/2, gl.viewportHeight);
mat4.frustum(-24.0, 24.0, -11.0, 25.0, -100.0, 100.0, pMatrix);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
if(perspective){
mat4.perspective(38.5, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
}
if(perspectiveTP){
mat4.perspective(53.13, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
}
if(orthogonal){
mat4.ortho(-24.0, 24.0, -11.0, 25.0, -100.0, 100.0, pMatrix);
}
mat4.identity(mvMatrix);
if(perspectiveTP){
mat4.lookAt([camX+frogH,camY,camZ+frogV],[frogH,1,frogV],[0,1,0], mvMatrix);
}
if(perspective){
mat4.lookAt([-12,50,17],[-12,0,17],[0,0,1], mvMatrix);
}
if(orthogonal){
mat4.lookAt([-12,52.5,10],[-12,0,10],[0,0,1], mvMatrix);
}
mat4.identity(pMatrix);
gl.viewport(gl.viewportWidth/2, 0, gl.viewportWidth/2, gl.viewportHeight);
mat4.frustum(-24.0, 24.0, -11.0, 25.0, -100.0, 100.0, pMatrix);
if(perspective){
mat4.perspective(38.5, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
}
if(perspectiveTP){
mat4.perspective(53.13, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
}
if(orthogonal){
mat4.ortho(-24.0, 24.0, -11.0, 25.0, -100.0, 100.0, pMatrix);
}
mat4.identity(mvMatrix);
if(perspectiveTP){
mat4.lookAt([camX+frogH,camY,camZ+frogV],[frogH,1,frogV],[0,1,0], mvMatrix);
}
if(perspective){
mat4.lookAt([-12,50,17],[-12,0,17],[0,0,1], mvMatrix);
}
if(orthogonal){
mat4.lookAt([-12,52.5,10],[-12,0,10],[0,0,1], mvMatrix);
}
(...)
EDIT: I've simply created a drawSceneLeft and a drawSceneRight, but not sure if it's the right way to achieve what I'm trying to do, any help is still welcome!
What is your draw function doing? If it's clearing the canvas then you're basically drawing one half, erasing the entire canvas, then drawing the other half.
gl.viewport only sets vertex math related functions. It doesn't stop things from drawing outside the viewport. Specifically it tells WebGL how to convert from clipspace back into pixels and it clips vertex calculations. So for example if you were to draw POINTS and you set gl_PointSize to 100 those points could bleed out of your viewport. A point whose center is outside the viewport won't get drawn at all (it's clipped) but a point whose center is on the edge inside of the viewport will be drawn. Only vertex calculation is clipped and the point is inside so it's not clipped. Once it's passed that test the primitive is still rendered, in this case a 100x100 pixel POINT of which ~50 pixels are outside the viewport.
On the other hand. gl.scissor does clip during rasterization. So, enable the scissor test gl.enable(gl.SCISSOR_TEST) and set the scissor gl.scissor(x, y, width, height) and now that same POINT above would be clipped. gl.clear will also be clipped.
TD;LR you need to set both the gl.viewport and enable and set the scissor to render multiple viewports.

WebGL code produces same matrices as pre-made library but does not display the same

I am working on a 3D function library (for fun) and am unable to find the error in my code. From what I can see, the matrices produced by my code and a pre-made library are exactly the same. I am using the same vertex positions but nothing is showing and it's driving me crazy.
My Version:
http://robjte.de/webgl/notworking.html
http://jsfiddle.net/uh9574z0/
The pre-made working version (target output):
http://robjte.de/webgl/working.html
http://jsfiddle.net/5daae976/
I have console logged the matrices on each version.
Main segment (my version):
var translate = [0.5, 0, 0];
var modelMatrix = identity(4);
modelMatrix.setXY(3, 0, translate[0]);
modelMatrix.setXY(3, 1, translate[1]);
modelMatrix.setXY(3, 2, translate[2]);
var eye = createVector([0, 0, 2.25]);
var focus = createVector([0, 0, 0]);
var up = createVector([0, 1, 0]);
modelMatrix = modelMatrix;
var viewMatrix = lookAt(eye, focus, up);
var projectionMatrix = perspective(canvas, 50 * Math.PI / 180, 1, 10);
Main segment (working version):
// local coords -> world space
var modelMatrix = mat4.create();
mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(0.5, 0.0, 0.0));
// world space -> camera space
var eye = vec3.fromValues(0, 0, 2.25);
var lookAt = vec3.fromValues(0, 0, 0);
var up = vec3.fromValues(0, 1, 0);
var viewMatrix = mat4.create();
mat4.lookAt(viewMatrix, eye, lookAt, up);
var projMatrix = mat4.create();
mat4.perspective(projMatrix, 50 * Math.PI / 180, canvas.clientWidth / canvas.clientHeight, 1, 10);
I don't think your math lib is actually generating the same results. I used the WebGL Inspector to look at the state of the program in each of your links. There's a few very significant differences.
I figured it out. My arrays were in row major order instead of column major order as required by GLSL. This helped a lot: Correct OpenGL matrix format?

glmatrix.js anomaly - changing order of transforms does not change outcome

In creating a webgl "hello world" for demonstration to a high school class, I am experiencing an anomalous result.
Using gl-matrix.js version 2.2.0, reversing the order of two transforms does not produce a difference in output.
This code produces the desired result:
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = mat4.create();
var modelview_matrix = mat4.create();
var mvp = mat4.create();
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
mat4.perspective(projection_matrix, D2R(50.0), gl.size[0] / gl.size[1], 1.0, 10.0);
mat4.translate(modelview_matrix, modelview_matrix, [0.0, 0.0, -3.5]);
mat4.rotate(modelview_matrix, modelview_matrix, D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0]);
mat4.multiply(mvp, projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
namely a triangle that spins in place about its Y axis.
Reversing the order of the translate and rotate should spin the triangle around the camera (part of my intended lesson), but instead continues to spin the triangle in place. I sanity checked this in an equivalent legacy OpenGL "hello world" producing exactly the expected results.
The vertex shader simply multiples the vertex position attribute with the mvp uniform. Is there a problem in gl-matrix.js or in this code?
For completeness, here is the render function.
Triangle.prototype.Render = function (gl, shader_index, color, mvp) {
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertex_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].VP, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].VP);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.element_buffer_object);
shaders[shader_index].Use(gl);
gl.uniformMatrix4fv(shaders[shader_index].MVP, false, mvp);
if (shader_index == 0)
gl.uniform4fv(shaders[shader_index].COLOR, color);
else {
gl.bindBuffer(gl.ARRAY_BUFFER, this.color_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].COLOR, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].COLOR);
}
gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
shaders[shader_index].StopUsing(gl);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
Thank you.
I believe there is an error in my use of gl-matrix or gl-matrix itself. Replacing gl-matrix with mjs.js works as expacted.
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = M4x4.I;
var modelview_matrix = M4x4.I;
var mvp = M4x4.I;
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
projection_matrix = M4x4.makePerspective(50.0, gl.size[0] / gl.size[1], 1.0, 10.0);
modelview_matrix = M4x4.rotate(D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0], modelview_matrix);
modelview_matrix = M4x4.translate([0.0, 0.0, -5.5], modelview_matrix);
mvp = M4x4.mul(projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
Does indeed rotate about the camera. Reversing to translate then rotate spins about the Y axis of the triangle.
I would be very pleased to have my code for gl-matrix corrected. If it cannot, gl-matrix is very broken.

Categories

Resources