Webgl coloring the entire geometry? - webgl

I am using triangles(using vertices and face position) to draw the graphics.I am storing color information for each vertex and applying colors accordingly. But the problem is all the geometries in my scene are of single color(say cone=red, cylinder=blue). SO, storing color for each vertex is apparently of no use to me.
Is their any other approach by which coloring can be done in webgl apart from storing color information of each vertices in the scene. Maybe something like coloring the entire geometry(say a cone).

It's clear from your question you might not really understand WebGL yet? You might want to check out these tutorials.
WebGL uses shaders, those shaders use whatever inputs you define and output whatever you tell them to output. That means WebGL doesn't require vertex colors. Vertex colors are something you decide on when you write your shaders. If you don't want to use vertex colors, don't write a shader that references vertex colors.
That said there if you have a shader that happens to use vertex colors you can easily provide the shader with a constant color. Let's assume you have shaders like this that just use vertex colors.
vertex shader:
attribute vec4 a_position;
attribute vec4 a_color; // vertex colors
varying vec4 v_color; // so we can pass the colors to the fragment shader
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * a_position;
v_color = a_color;
}
fragment shader:
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
Now, all you have to do to use a constant color is turn off the attribute for a_color and set a constant value with gl.vertexAttrib4f like this
// at init time
var a_colorLocation = gl.getAttribLocation(program, "a_color";
// at draw time
gl.disableVertexAttribArray(a_colorLocation); // turn off the attribute
gl.vertexAttrib4f(a_colorLocation, r, g, b, a); // supply a constant color
Note that turning off attribute 0 will slow down WebGL on desktops because if differences between OpenGL and OpenGL ES. It's possible a_colorLocation is attribute 0. To avoid this problem bind your attribute locations BEFORE you link your program. Specifically since you'll always use a position (which is called "a_position" in the example above) just bind that to location 0 like this
..compile shaders..
..attach shaders to program..
// Must happen before you call linkProgram
gl.bindAttribLocation(program, 0, "a_position");
gl.linkProgram(program);
...check for errors, etc...
This will force the attribute for "a_position" to be attribute 0 so you'll always enable it.
Here's a sample
function main() {
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl");
if (!gl) {
alert("no WebGL");
return;
}
// NOTE:! This function binds attribute locations
// based on the indices of the second array
var program = twgl.createProgramFromScripts(
gl,
["vshader", "fshader"],
["a_position", "a_color"]); // a_position will get location 0
// a_color will get location 1
var a_positionLoc = 0;
var a_colorLoc = 1;
var u_matrixLoc = gl.getUniformLocation(program, "u_matrix");
gl.useProgram(program);
var verts = [
1, 1,
-1, 1,
-1, -1,
1, 1,
-1, -1,
1, -1,
];
var colors = [
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
255, 255, 0, 255,
0, 255, 255, 255,
255, 0, 255, 255,
];
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.enableVertexAttribArray(a_positionLoc);
gl.vertexAttribPointer(a_positionLoc, 2, gl.FLOAT, false, 0, 0);
var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(colors), gl.STATIC_DRAW);
gl.enableVertexAttribArray(a_colorLoc);
gl.vertexAttribPointer(a_colorLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);
// Draw in the bottom right corner
gl.uniformMatrix4fv(
u_matrixLoc,
false,
[0.5, 0, 0, 0,
0, 0.5, 0, 0,
0, 0, 1, 0,
-0.5, -0.5, 0, 1]);
gl.drawArrays(gl.TRIANGLES, 0, 6);
// Now turn off the a_color attribute and supply a solid color
gl.disableVertexAttribArray(a_colorLoc);
var r = 0.5;
var g = 1;
var b = 0.5;
var a = 1;
gl.vertexAttrib4f(a_colorLoc, r, g, b, a); // greenish
// Draw in the top left corner
gl.uniformMatrix4fv(
u_matrixLoc,
false,
[0.5, 0, 0, 0,
0, 0.5, 0, 0,
0, 0, 1, 0,
0.5, 0.5, 0, 1]);
gl.drawArrays(gl.TRIANGLES, 0, 6);
};
main();
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<script id="vshader" type="whatever">
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * a_position;
v_color = a_color;
}
</script>
<script id="fshader" type="whatever">
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
</script>
<canvas id="c" width="300" height="300"></canvas>

If your geometry has color per object, that doesn't change across the geometry, then you should pass that color as the uniform variable.
So you en up with only one attribute - position of vertices, few matrix uniforms - say model, view, projection matrices, that for the vertex shader, and one vector uniform variable for the fragment shader for "shading" the object.

Related

WebGL shader z position not used in depth calculations

I've been trying out some WebGL but there's a bug I cannot seem to find out how to fix.
Currently I have the following setup:
I have around 100 triangles which all have a position and are being drawn by a single gl.drawArrays function. To have them drawn in the correct order I used gl.enable(gl.DEPTH_TEST); which gave the correct result.
The problem I have now is that if I update the gl_Position of the triangles in the vertex shader the updated Z value is not being used in the depth test. The result is that a triangle with a gl_Position.z of 1 can be drawn on top of a triangle with a gl_Position.z of 10, which is not exactly what I want..
What have I tried?
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.GEQUAL);
with
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.clearDepth(0);
gl.drawArrays(gl.TRIANGLES, 0, verticesCount);
in the render function.
The following code is used to create the buffer:
gl.bindBuffer(gl.ARRAY_BUFFER, dataBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positionBufferData, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, false, 0, 0);
The triangles with a higher z value are much bigger in size (due to the perspective) but small triangles still appear over it (due to the render order).
In the fragment shader I've used gl_fragCoord.z to see if that was correct and smaller triangles (further away) received a higher alpha than bigger ones (up close).
What could be the cause of the weird drawing behaviour?
Depth in clipspace goes from -1 to 1. Depth written to the depth buffer goes from 0 to 1. You're clearing to 1. There is no depth value > 1 so the only things you should see drawn are at gl_Position.z = 1. Anything less than 1 will fail the test gl.depthFunc(gl.GEQUAL);. Anything > 1 will be clipped. Only 1 is both in the depth range and Greater than or Equal to 1
The example below draws smaller to larger rectangles with different z values. The red is standard gl.depthFunc(gl.LESS) with depth cleared to 1. The green is gl.depthFunc(gl.GEQUAL) with depth cleared to 0. The blue is gl.depthFunc(gl.GEQUAL) with depth cleared to 1. Notice blue only draws the single rectangle at gl_Position.z = 1 because all other rectangles fail the test since they are at Z < 1.
const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl");
const vs = `
attribute vec4 position;
varying vec4 v_position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
v_position = abs(position);
}
`;
const fs = `
precision mediump float;
varying vec4 v_position;
uniform vec4 color;
void main() {
gl_FragColor = vec4(1. - v_position.xxx, 1) * color;
}
`;
// compiles shaders, links program, looks up attributes
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBindbuffer, gl.bufferData for each array
const z0To1BufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: [
...makeQuad( .2, 0.00),
...makeQuad( .4, .25),
...makeQuad( .6, .50),
...makeQuad( .8, .75),
...makeQuad(1.0, 1.00),
],
});
const z1To0BufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: [
...makeQuad(.2, 1.00),
...makeQuad(.4, .75),
...makeQuad(.6, .50),
...makeQuad(.8, .25),
...makeQuad(1., 0.00),
],
});
function makeQuad(xy, z) {
return [
-xy, -xy, z,
xy, -xy, z,
-xy, xy, z,
-xy, xy, z,
xy, -xy, z,
xy, xy, z,
];
}
gl.useProgram(programInfo.program);
gl.enable(gl.DEPTH_TEST);
gl.clearDepth(1);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.LESS);
drawRects(-0.66, z0To1BufferInfo, [1, 0, 0, 1]);
gl.clearDepth(0);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.GEQUAL);
drawRects(0, z1To0BufferInfo, [0, 1, 0, 1]);
gl.clearDepth(1);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.GEQUAL);
drawRects(0.66, z1To0BufferInfo, [0, 0, 1, 1]);
function drawRects(xoffset, bufferInfo, color) {
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
let mat = m4.translation([xoffset, 0, 0]);
mat = m4.scale(mat, [.3, .5, 1]);
// calls gl.uniformXXX
twgl.setUniforms(programInfo, {
color: color,
matrix: mat,
});
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
}
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<canvas></canvas>
<pre>
red : depthFunc: LESS, clearDepth: 1
green: depthFunc: GEQUAL, clearDepth: 0
blue : depthFunc: GEQUAL, clearDepth: 1
</pre>

why is WebGL slower than Canvas 2D in my game?

I am adding WebGL support in my game, but I have a strange problem : it runs even slower than in Canvas 2D rendering mode, and I do not understand why.
I checked on both Firefox PC, Chrome PC, and Chrome Android, they run WebGL demos on the web with hundreds of sprites smoothly though, so I definitly made an error in my code.
Firefox's profiler says the whole game uses only 7% of the ressources, the rendering part takes only 1.2%. It is just the title screen of the game and there are only five sprites to draw. It is slow though...
update : Chrome's profiler says idle is only 4%, program is a huge 93%, and render 2.6%.
When using Canvas 2D things are very different, 76% idle, 16% program, 2.3% for the drawing function.
There definitly is a problem in my WebGL rendering code.
update : Android Chrome's profiler (on JXD S5110) always says program is ~39%, drawArrays is ~ 8%, bufferData ~5%, and bindTexture is 3%. Everything else is quite negligible.
If a function of mines was wasting all the ressources I would know what to do, but here the bottlenecks seem to be "program" (the browser itself ?) and webgl methods, two things I can't edit.
Please someone have a look at my code and tell me what I did wrong.
Here are my shaders
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec2 a_texCoord;
uniform vec2 u_resolution;
uniform vec2 u_translation;
uniform vec2 u_rotation;
varying vec2 v_texCoord;
void main()
{
// Rotate the position
vec2 rotatedPosition = vec2(
a_position.x * u_rotation.y + a_position.y * u_rotation.x,
a_position.y * u_rotation.y - a_position.x * u_rotation.x);
// Add in the translation.
vec2 position = rotatedPosition + u_translation;
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
// pass the texCoord to the fragment shader
// The GPU will interpolate this value between points
v_texCoord = a_texCoord;
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
// our texture
uniform sampler2D u_image;
// the texCoords passed in from the vertex shader.
varying vec2 v_texCoord;
void main()
{
// Look up a color from the texture.
gl_FragColor = texture2D(u_image, vec2(v_texCoord.s, v_texCoord.t));
}
</script>
Here is the creation code of my canvas and their contexts when in WebGL mode.
(I use to use several layered canvas in order to avoid drawing the backgrounds and foregrounds at every frame while they never change, that is why canvas and contexts are in arrays.)
// Get A WebGL context
liste_canvas[c] = document.createElement("canvas") ;
document.getElementById('game_div').appendChild(liste_canvas[c]);
liste_ctx[c] = liste_canvas[c].getContext('webgl',{premultipliedAlpha:false}) || liste_canvas[c].getContext('experimental-webgl',{premultipliedAlpha:false});
var gl = liste_ctx[c] ;
gl.viewport(0, 0, game.res_w, game.res_h);
// setup a GLSL program
gl.vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
gl.fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
gl.program = createProgram(gl, [gl.vertexShader, gl.fragmentShader]);
gl.useProgram(gl.program);
// look up where the vertex data needs to go.
positionLocation = gl.getAttribLocation(gl.program, "a_position");
texCoordLocation = gl.getAttribLocation(gl.program, "a_texCoord");
// provide texture coordinates for the rectangle.
texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable( gl.BLEND ) ;
gl.posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, gl.posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
In the .onload function of my images, I add
var gl = liste_ctx[c] ;
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
And here is the WebGL part of my draw_sprite() function :
var gl = liste_ctx[c] ;
gl.bindTexture(gl.TEXTURE_2D, sprites[d_sprite].texture);
var resolutionLocation = gl.getUniformLocation(gl.program, "u_resolution");
gl.uniform2f(resolutionLocation, liste_canvas[c].width, liste_canvas[c].height);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
topleft_x , topleft_y ,
topright_x , topright_y ,
bottomleft_x , bottomleft_y ,
bottomleft_x , bottomleft_y ,
topright_x , topright_y ,
bottomright_x , bottomright_y ]), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, 6);
What did I do wrong ?
This may help: What do the "Not optimized" warnings in the Chrome Profiler mean?
Relevant links:
https://groups.google.com/forum/#!topic/v8-users/_oZ4fUSitRY
https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
For "optimized too many times", that means the function parameters / behavior change too much, so Chrome keeps having to re-optimize it.
What was making it so slow was using several webgl canvas, I use only one now and it works way better. But it is still a bit slower than Canvas 2D though, and the profiler says 65% is idle while it lags as hell so I really don't understand...
edit : I think I got it. Since my computer is running WinXP, hardware acceleration for WebGL can't be enabled, so the browsers use software rendering, and that explains why 'program' is huge in Chrome's profiler. However, hardware acceleration seems to work for 2d context, that is why it is faster.

How do I draw gradients of discrete integer values from 0-255 in WebGL without making a buffer for each color

Hello I am using Dartlang and WebGl to write a neural net visualization and I the neurons output ranges from 0-1. I want to display the neurons outputs as a function of color using a sampling depth of 255 values in the red spectrum. I have learned basic WegGL and I know that I need to bind a color to an array and then read it using a GPU program. My program draws red triangle for a neuron with output close to 1 and white for a neuron who's output is close to 0. My question is how do I draw with colors of values in between white and red without creating a gl buffer for each of the 255 values. I assume I will do something in the GPU program itself and just bind the value of the neuron output to the Array and then have the GPU program convert it into a vec4 color.
A link to my current FULL code is here: https://github.com/SlightlyCyborg/dart-neuralnet/blob/master/web/part1.dart
Also here is segment of my code:
program = new GlProgram('''
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
''','''
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;
}
''', ['aVertexPosition', 'aVertexColor'], ['uMVMatrix', 'uPMatrix']);
gl.useProgram(program.program);
Here is where I bind the buffer for the on_neuron_color
gl.bindBuffer(ARRAY_BUFFER, on_color_buff);
gl.bufferDataTyped(ARRAY_BUFFER, new Float32List.fromList([
1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
]), STATIC_DRAW);
And here is where I draw using that color:
gl.bindBuffer(ARRAY_BUFFER,tri_buff);
gl.vertexAttribPointer(program.attributes['aVertexPosition'], 3, FLOAT, false, 0, 0);
gl.bindBuffer(ARRAY_BUFFER, on_color_buff);
gl.vertexAttribPointer(program.attributes['aVertexColor'], 4, FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(TRIANGLE_STRIP, 0, 3);
I don't understand what you're really trying to do but....
If you change your fragment shader to
precision mediump float;
uniform vec4 uColor;
void main(void) {
gl_FragColor = uColor;
}
Then you can set the color that WebGL will draw with with
gl.uniform4f(program.uniforms['uColor'], r, g, b, a);
or
gl.uniform4fv(program.uniforms['uColor'], arrayOf4Floats);
You don't need any color buffers and you can remove all references to color from your vertex shader.

GLSL: Changing more than two vertex dimensions crashes shader

For testing purposes I am trying to set the position of every vertex to zero. But If I try to change more than two dimensions (and it doesn't matter which), the shader crashes silently. Can anybody clue me into what is going on here? My code:
static const float vertices[12] = {
-0.5,-0.5, 0.0,
0.5,-0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, 0.5, 0.0,
};
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)vertices);
glEnableVertexAttribArray(vertexHandle);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, (const GLfloat*)&modelViewProjection.data[0]);
glDrawArrays(GL_POINTS, 0, 4);
And my shader:
attribute vec4 vertexPosition;
uniform mat4 modelViewProjectionMatrix;
void main()
{
vec4 temp = vertexPosition;
temp.x = 0.0;
temp.y = 0.0;
temp.z = 0.0; // Can set any 2 dimensions (e.g. x and y or y and z)
// to zero, but not all three or the shader crashes.
gl_Position = modelViewProjectionMatrix * vec4(temp.xyz, 1.0);
}
Maybe it's because you declare vertexPosition as a vec4, but you are only passing 3 floats per vertex in your C code? I think the part about your temp vector is a red herring.

webgl adding projection doesnt display object

I am having a look at web gl, and trying to render a cube, but I am having a problem when I try to add projection into the vertex shader. I have added an attribute, but when I use it to multiple the modelview and position, it stops displaying the cube. Im not sure why and was wondering if anyone could help? Ive tried looking at a few examples but just cant get this to work
vertex shader
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
//gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0);
}
fragment shader
#ifdef GL_ES
precision highp float; // Not sure why this is required, need to google it
#endif
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
function init() {
// Get a reference to our drawing surface
canvas = document.getElementById("webglSurface");
gl = canvas.getContext("experimental-webgl");
/** Create our simple program **/
// Get our shaders
var v = document.getElementById("vertexShader").firstChild.nodeValue;
var f = document.getElementById("fragmentShader").firstChild.nodeValue;
// Compile vertex shader
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, v);
gl.compileShader(vs);
// Compile fragment shader
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, f);
gl.compileShader(fs);
// Create program and attach shaders
program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
// Some debug code to check for shader compile errors and log them to console
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
console.log(gl.getShaderInfoLog(vs));
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
console.log(gl.getShaderInfoLog(fs));
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
console.log(gl.getProgramInfoLog(program));
/* Create some simple VBOs*/
// Vertices for a cube
var vertices = new Float32Array([
-0.5, 0.5, 0.5, // 0
-0.5, -0.5, 0.5, // 1
0.5, 0.5, 0.5, // 2
0.5, -0.5, 0.5, // 3
-0.5, 0.5, -0.5, // 4
-0.5, -0.5, -0.5, // 5
-0.5, 0.5, -0.5, // 6
-0.5,-0.5, -0.5 // 7
]);
// Indices of the cube
var indicies = new Int16Array([
0, 1, 2, 1, 2, 3, // front
5, 4, 6, 5, 6, 7, // back
0, 1, 5, 0, 5, 4, // left
2, 3, 6, 6, 3, 7, // right
0, 4, 2, 4, 2, 6, // top
5, 3, 1, 5, 3, 7 // bottom
]);
// create vertices object on the GPU
vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// Create indicies object on th GPU
ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicies, gl.STATIC_DRAW);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
// Render scene every 33 milliseconds
setInterval(render, 33);
}
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
function render() {
// Set our viewport and clear it before we render
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(program);
// Bind appropriate VBOs
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
// Set the color for the fragment shader
program.uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(program.uColor, [0.3, 0.3, 0.3, 1.0]);
//
// code.google.com/p/glmatrix/wiki/Usage
program.uPMatrix = gl.getUniformLocation(program, "uPMatrix");
program.uMVMatrix = gl.getUniformLocation(program, "uMVMatrix");
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 1.0, 10.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0.0, -0.25, -1.0]);
gl.uniformMatrix4fv(program.uPMatrix, false, pMatrix);
gl.uniformMatrix4fv(program.uMVMatrix, false, mvMatrix);
// Set the position for the vertex shader
program.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(program.aVertexPosition);
gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 3*4, 0); // position
// Render the Object
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
}
Thanks in advance for any help
Problem is here:
..., gl.viewportWidth / gl.viewportHeight, ...
Both gl.viewportWidth and gl.viewportHeight are undefined values.
I think you missed this two lines:
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
You will see a lot of people doing this:
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
But please note that WebGL context also have this two attributes:
gl.drawingBufferWidth
gl.drawingBufferHeight
So your cube shows up without the perspective matrix, correct?
At first glance I would think that you may be clipping away your geometry with the near plane. You provide a near an far plane to the perpective function as 1.0 and 10.0 respectively. This means that for any fragments to be visible they must fall in the z range of [1, 10]. You cube is 1 unit per side, centered on (0, 0, 0), and you are moving it "back" from the camera 1 unit. This means that the nearest face to the camera will actually be at 0.5 Z, which is outside the clipping range and therefore discarded. About half of your cube WILL be at z > 1, but you'll be looking at the inside of the cube at that point. If you have backface culling turned on you won't see anything.
Long story short - Your cube is probably too close to the camera. Try this instead:
mat4.translate(mvMatrix, [0.0, -0.25, -3.0]);

Resources