I am new to webgl and I've been trying to pass an attribute to the fragment shader using varying in order to change all the triangles to random colors just like this:
But right now, all the triangles are just in white color, and I'm not sure what did wrong. Also, how do I do to make the triangles fit into the canvas? PLease help, thank you.
// Application info.
var app = app || {};
var nbTriangles = 20;
function getContextGL(canvasElement) {
var can = document.getElementById(canvasElement);
if (can == null) {
return [null, null];
}
var gl = can.getContext("webgl");
return [can, gl];
}
function createShaderFromElement(gl, id) {
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt) {
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment") {
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (scriptElt.type == "x-shader/x-vertex") {
shaderObj = gl.createShader(gl.VERTEX_SHADER);
}
else {
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj, scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!ok) {
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl, vertexShader, fragmentShader) {
if (!vertexShader || !fragmentShader) {
return null;
}
var progObject = gl.createProgram();
if (!progObject) {
alert("Can't create program object.");
return;
}
gl.attachShader(progObject, vertexShader);
gl.attachShader(progObject, fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
if (!ok) {
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL() {
app.gl.viewport(0, 0, app.can.width, app.can.height);
app.gl.clearColor(0., 0., 0., 1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
app.gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],
orig[1] * scale + Trans[1],
];
var P1 = [
orig[2] * scale + Trans[0],
orig[3] * scale + Trans[1],
];
var P2 = [
orig[4] * scale + Trans[0],
orig[5] * scale + Trans[1],
];
positions.push(...P0, ...P1, ...P2);
}
var colors = [];
for (var i = 0; i < nbTriangles; ++i) {
var newColor = [Math.random() * 256, Math.random() * 256, Math.random() * 256, 1.0];
colors.push(...newColor);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
var colorBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject, "pos");
var colorLocation = gl.getAttribLocation(app.progObject, "color");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(colorLocation);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
}
function render() {
var gl = app.gl;
gl.clear(gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES, 0, 3 * nbTriangles);
}
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();
render();
}
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>Colored Quad</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="colored_quad.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
attribute vec4 color;
varying vec4 fcolor;
void main()
{
vec4 pt = vec4(pos, 0.0, 1.0);
gl_Position = pt;
fcolor=color;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fcolor;
void main()
{
vec4 color= fcolor;
gl_FragColor = color;
}
</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>
</div>
</body>
</html>
The the color attribute has a floating point type:
attribute vec4 color;
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
Hence the color values have to be specified in range [0.0, 1.0] rather than [0, 256]:
var newColor = [Math.random() * 256, Math.random() * 256, Math.random() * 256, 1.0];
var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
Furthermore, each triangle has 3 vertices (corners). Each vertex coordinate has to be associated to a separate color attribute. So each triangle has to have 3 color attributes, too:
var colors = [];
for (var i = 0; i < nbTriangles; ++i) {
var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
colors.push(...newColor);
colors.push(...newColor);
colors.push(...newColor);
}
// Application info.
var app = app || {};
var nbTriangles = 20;
function getContextGL(canvasElement) {
var can = document.getElementById(canvasElement);
if (can == null) {
return [null, null];
}
var gl = can.getContext("webgl");
return [can, gl];
}
function createShaderFromElement(gl, id) {
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt) {
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment") {
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (scriptElt.type == "x-shader/x-vertex") {
shaderObj = gl.createShader(gl.VERTEX_SHADER);
}
else {
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj, scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!ok) {
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl, vertexShader, fragmentShader) {
if (!vertexShader || !fragmentShader) {
return null;
}
var progObject = gl.createProgram();
if (!progObject) {
alert("Can't create program object.");
return;
}
gl.attachShader(progObject, vertexShader);
gl.attachShader(progObject, fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
if (!ok) {
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL() {
app.gl.viewport(0, 0, app.can.width, app.can.height);
app.gl.clearColor(0., 0., 0., 1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
app.gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],
orig[1] * scale + Trans[1],
];
var P1 = [
orig[2] * scale + Trans[0],
orig[3] * scale + Trans[1],
];
var P2 = [
orig[4] * scale + Trans[0],
orig[5] * scale + Trans[1],
];
positions.push(...P0, ...P1, ...P2);
}
var colors = [];
for (var i = 0; i < nbTriangles; ++i) {
var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
colors.push(...newColor);
colors.push(...newColor);
colors.push(...newColor);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
var colorBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject, "pos");
var colorLocation = gl.getAttribLocation(app.progObject, "color");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(colorLocation);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
}
function render() {
var gl = app.gl;
gl.clear(gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES, 0, 3 * nbTriangles);
}
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();
render();
}
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>Colored Quad</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="colored_quad.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
attribute vec4 color;
varying vec4 fcolor;
void main()
{
vec4 pt = vec4(pos, 0.0, 1.0);
gl_Position = pt;
fcolor=color;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fcolor;
void main()
{
vec4 color= fcolor;
gl_FragColor = color;
}
</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>
</div>
</body>
</html>
Related
I want to rotate and translate a 2d shape made with signed distance functions.
The docs say this is the method:
vec3 opTx( in vec3 p, in transform t, in sdf3d primitive )
{
return primitive( invert(t)*p );
}
It looks to me like primitive is some kind of function (or a struct) I can call, Is there a way to pass functions like that (or how does this make sense)?
Firstly I don't know what transform and sdf3d types are, and what is the invert function. Secondly how do I apply this to 2d?
const fShaderSource = `#version 300 es
precision mediump float;
uniform vec2 u_resolution;
out vec4 outColor;
float sdLine( in vec2 p, in vec2 a, in vec2 b )
{
vec2 pa = p-a, ba = b-a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h );
}
vec2 screenToWorld(vec2 screen) {
vec2 result = 2.0 * (screen/u_resolution.xy - 0.5);
result.x *= u_resolution.x/u_resolution.y;
return result;
}
void main() {
vec2 p = screenToWorld(gl_FragCoord.xy);
float sd = sdLine(p, vec2(0.0), vec2(0.0, 0.5));
vec3 col = vec3(0.0);
col += 1.0 - smoothstep(0.0, 0.04, abs(sd));
outColor = vec4(col, 1.0);
}
`;
const vShaderSource = `#version 300 es
precision mediump float;
in vec2 a_position;
uniform vec2 u_resolution;
void main() {
gl_Position = vec4(a_position, 0, 1);
}
`;
main(document.getElementById('app'));
function main(element) {
const canvas = document.createElement('canvas'),
gl = canvas.getContext('webgl2');
element.append(canvas);
const displayWidth = canvas.clientWidth,
displayHeight = canvas.clientHeight;
canvas.width = displayWidth;
canvas.height = displayHeight;
let graphics = new Graphics({width: displayWidth, height: displayHeight}, gl);
new Loop(() => {
graphics.render();
}).start();
}
function Graphics(state, gl) {
const { width, height } = state;
let vShader = createShader(gl, gl.VERTEX_SHADER, vShaderSource);
let fShader = createShader(gl, gl.FRAGMENT_SHADER, fShaderSource);
let program = createProgram(gl, vShader, fShader);
let posAttrLocation = gl.getAttribLocation(program, "a_position");
let posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
/*
(-1, 1).( 1, 1)
.
(-1,-1).( 1,-1)
*/
let positions = [
-1, 1,
-1, -1,
1, -1,
-1, 1,
1,-1,
1, 1
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
let vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.enableVertexAttribArray(posAttrLocation);
let size = 2,
type = gl.FLOAT,
normalize = false,
stride = 0,
offset = 0;
gl.vertexAttribPointer(posAttrLocation,
size,
type,
normalize,
stride,
offset);
let resUniformLocation = gl.getUniformLocation(program, "u_resolution");
gl.clearColor(0, 0, 0, 0);
this.render = () => {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.uniform2f(resUniformLocation, gl.canvas.width, gl.canvas.height);
gl.bindVertexArray(vao);
gl.drawArrays(gl.TRIANGLES, 0, 6);
};
}
function createShader(gl, type, source) {
let shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
};
function createProgram(gl, vShader, fShader) {
let program = gl.createProgram();
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
gl.linkProgram(program);
let success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.error(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
// Loop Library
function Loop(fn) {
const perf = window.performance !== undefined ? window.performance : Date;
const now = () => perf.now();
const raf = window.requestAnimationFrame;
let running = false,
lastUpdate = now(),
frame = 0;
this.start = () => {
if (running) {
return this;
}
running = true;
lastUpdate = now();
frame = raf(tick);
return this;
};
this.stop = () => {
running = false;
if (frame != 0) {
raf.cancel(frame);
}
frame = 0;
return this;
};
const tick = () => {
frame = raf(tick);
const time = now();
const dt = time - lastUpdate;
fn(dt);
lastUpdate = time;
};
}
#app canvas {
position: fixed;
top: 50%;
bottom: 0;
left: 50%;
right: 0;
width: 100vmin;
height: 70vmin;
transform: translate(-50%, -25%);
image-rendering: optimizeSpeed;
cursor: none;
margin: auto;
}
<div id="app">
</div>
GLSL does not allow you to pass functions as parameters. The snippet you linked is more of a macro, where you are supposed to manually inline the primitive.
Just above the code you copy-pasted, the definition of transform is stated:
This code bellow assumes that transform encodes only a rotation and a translation (as a 3x4 matrix for example, or as a quaternion and a vector), and that it does not contain any scaling factors in it.
To work in 2D, you use 3x3 matrices, where the upper 2x2 matrix encodes a rotation and the two first columns of the bottom row encode a translation.
Putting it all together: (replace the mainImage function of https://www.shadertoy.com/view/MldcD7 with this)
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
p *= 1.1;
// iFrame is a uniform that shadertoy provides: the current frame number
float angle = float(iFrame) / 60.0;
// Rotation part: rotate by `angle`, or once every 60 fps.
// Translation part: Move across the screen left to right, every 60 fps.
mat3 transform = mat3(
cos(angle), sin(angle), 0.0,
-sin(angle),cos(angle), 0.0,
(float(iFrame % 60)/60.0 - 0.5) * 2.0, 0.0, 1.0
);
vec2 tri = vec2(0.3,-1.1); // width, height
// Here, we first apply the inverse transform to our input, then pass the resulting point to our primitive, here sdTriangleIsosceles
float d = sdTriangleIsosceles( tri, (inverse(transform) * vec3(p, 1.0)).xy );
vec3 col = vec3(1.0) - sign(d)*vec3(0.1,0.4,0.7);
col *= 1.0 - exp(-2.0*abs(d));
col *= 0.8 + 0.2*cos(140.0*d);
col = mix( col, vec3(1.0), 1.0-smoothstep(0.0,0.02,abs(d)) );
fragColor = vec4(col*1.2,1.0);
}
Okay so I'm new to html and javascript right now. My task is to draw circles, I have looked at countless examples and my code doesn't draw anything. Here is what I have so far.
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPos;
void main()
{
gl_PointSize = 10.0;
gl_Position = vPos;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
<script type="text/javascript" src="webgl-utils.js"></script>
<script type="text/javascript" src="initshaders.js"></script>
<script type="text/javascript" src="lines.js"></script>
<script type="text/javascript">
var canvas;
var gl;
window.onload = init;
function init() {
canvas = document.getElementById("gl-canvas");
gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert("WebGL isn't available");
}
var program = initShaders(gl, "vertex-shader", "fragment-shader");
var vPos = gl.getAttribLocation(program, "vPos");
var colorUniformLocation = gl.getUniformLocation(program, "u_color");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.9, 0.9, 0.9, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.enableVertexAttribArray(vPos);
gl.vertexAttribPointer(vPos, 2, gl.FLOAT, false, 0, 0);
var red = 0.0;
var green = 0.0;
var blue = 1.0;
var vertices = circle(100,100,200);
for (var i=0; i<vertices.length; i++)
{
gl.uniform4f(colorUniformLocation, red, green, blue, 1.0);
gl.drawArrays(gl.POINTS, i, 1);
}
}
</script>
<body>
<canvas id="gl-canvas" width="1000" height="1000">
Oops... your browser doesn't support HTML5's Canvas elements!
</canvas>
</body>
</html>
The error seems to happen at var vertices = circle(100,100,200);
My circle function looks like this.
function getPoints(x,y)
{
var points = [];
points.push(x+x0,y+y0);
points.push(-x+x0,y+y0);
points.push(x+x0,-y+y0);
points.push(-x+x0,-y+y0);
points.push(y+y0,x+x0);
points.push(-y+y0,x+x0);
points.push(y+y0,-x+x0);
points.push(-y+y0,-x+x0);
return points;
}
function circle(x0, y0, radius)
{
var vertices = [];
var points = [];
var pk = 1- radius;
var xk = radius;
var yk = 0;
//var pk = ((xk +1)^2) + ((yk -.5)^2) - (radius^2);
points = getPoints(x0,y0);
for(var i = 0 ; i < points.length; i++)
{
vertices.push(points[i]);
}
while(xk>yk)
{
yk++;
if(pk <0)
{
points = getPoints(xk+1,yk);
pk = pk + (2* yk)+1;
}
else
{
points = getPoints(xk+1,yk-1);
xk--;
pk = pk + (2* yk) -(2* xk)+1;
}
for(var i = 0 ; i < points.length; i++)
{
vertices.push(points[i]);
}
}
return vertices;
}
From what I can tell the algorithm is correct, but for some reason the var vertices isn't returning correctly, because when I launch the file it draws the background but the circle is nowhere to be seen. Please help!
UPDATE
So I have fixed one problem, but my program is still not printing anything out. my circle function now looks like this.
function drawCircle(x0, y0, radius)
{
var vertices = [];
var pk = 1- radius;
var xk = 0;
var yk = radius;
//vertices.push(100,100); I am using these for error checking
//vertices.push(200,100); To see if vertices returns anything at all
//vertices.push(300,100); and from what i can tell it doesnt.
//vertices.push(400,100);
while(xk<yk)
{
xk++;
if(pk <0)
{
pk = pk + (2* xk)+1;
}
else
{
yk--;
pk = pk + (2* xk) -(2* yk)+1;
}
vertices.push(x+x0,y+y0); //This should be adding all symmetric
vertices.push(-x+x0,y+y0); //points from the first one around the
vertices.push(x+x0,-y+y0); //circle
vertices.push(-x+x0,-y+y0);
vertices.push(y+y0,x+x0);
vertices.push(-y+y0,x+x0);
vertices.push(y+y0,-x+x0);
vertices.push(-y+y0,-x+x0);
}
return vertices;
}
So besides the fact that there is actually an error, which I still need to figure out why, there is a difference in the error shown in the developer's tool console in Brackets editor and I'm not sure why.
The main.html file is the one that I made changes to based on the codes found here "view-source:http://learningwebgl.com/lessons/lesson01/index.html" (view-source needs to be included in the url), while the file main_copy.html is the actual codes that I copied and pasted from the link, and then backtracked through and added in my changes to see if I missed anything (thus the subtle differences in some warning strings).
Here are the two pictures showing the errors, the first one from running a Live Preview of main.html, and the second of main_copy.html:
HTML
main.html
<html>
<head>
<title>Rubik's Cube Interactive</title>
<meta charset="iso-8859-1">
<link rel="stylesheet" type="text/css" href="css/canvas.css">
<script type="text/javascript" src="js/gl-matrix-min.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {}
if (!gl) {
alert("Unable to initialize WebGL.");
}
}
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("Unable to initialize shaders.");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
var triangleVertexPositionBuffer;
function initBuffers() {
triangleVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;
}
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(pMatrix, 45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, mvMatrix, [-1.5, 0.0, -7.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
}
function webGLStart() {
var canvas = document.getElementById("project-canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initGL(canvas);
initShaders();
initBuffers();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
drawScene();
}
</script>
</head>
<body onload="webGLStart()">
<canvas id="project-canvas"></canvas>
</body>
</html>
main_copy.html
<html>
<head>
<title>Learning WebGL — lesson 1</title>
<meta charset="iso-8859-1">
<link rel="stylesheet" type="text/css" href="css/canvas.css">
<script type="text/javascript" src="js/gl-matrix-min.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("webgl") || 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.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
var triangleVertexPositionBuffer;
function initBuffers() {
triangleVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;
}
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(pMatrix, 45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, mvMatrix, [-1.5, 0.0, -7.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
}
function webGLStart() {
var canvas = document.getElementById("lesson01-canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initGL(canvas);
initShaders();
initBuffers();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
drawScene();
}
</script>
</head>
<body onload="webGLStart()">
<canvas id="lesson01-canvas"></canvas>
</body>
</html>
CSS
canvas.css
* { /* Remove top and left whitespace */
margin: 0;
padding: 0;
}
html, body { /* Set to full screen */
width: 100%;
height: 100%;
}
canvas { /* Remove scroll bars */
display: block;
}
JS
gl-matrix-min.js can be found here https://github.com/toji/gl-matrix/blob/master/dist/gl-matrix-min.js
I am following a book called professional WebGL, I am hand writing stuff making sure of my understanding, I have this code:
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>2-1 A first WebGL example</title>
<meta charset="utf-8">
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 1.0);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
<script type="text/javascript">
var gl;
var canvas;
var shaderProgram;
var vertexBuffer;
/*Function to create the webgl context*/
function createGLContext(canvas) {
var names = ["webgl", "experimental-webgl"];
var context = null;
for(var i = 0; i < names.length; i++) {
try {
context = canvas.getContext(names[i]);
} catch(e) {
if(context) {
break;
}
}
}
if(context) {
context.viewportWidth = canvas.width;
context.viewportHeight = canvas.height;
} else {
alert("Failed to create webgl context");
}
return context;
}
function loadShaderFromDOM(id) {
var shaderScript = document.getElementById(id);
//if we don't find an element with the specified id
//we do an early exit
if(!shaderScript) {
return null;
}
//loop through the children for the found DOM element and
//build up the shader source code as a string.
var shaderSource = "";
var currentChild = shaderScript.firstChild;
while(currentChild) {
if(currentChild.nodeType == 3) {
//3 corresponds to TEXT_NODE
shaderSource += currentChild.textContent;
}
currentChild = currentChild.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, shaderSource);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
/*Function to setup the shaders*/
function setupShaders() {
var vertexShader = loadShaderFromDOM("shader-vs");
var fragmentShader = loadShaderFromDOM("shader-fs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Failed toe setup shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
}
/*Function to setup the buffers*/
function setupBuffers() {
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
var triangleVertices = [
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
vertexBuffer.itemSize = 3;
vertexBuffer.numberOfItems = 3;
}
/*Function to draw the triangle*/
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.celar(gl.COLOR_BUFFER_BIT);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems);
}
/*Function to kick everything off*/
function startup() {
canvas = document.getElementById("myGLCanvas");
gl = createGLContext(canvas);
setupShaders();
setupBuffers();
gl.clearColor(0.0, 0.0, 0.0, 0.1);
draw();
}
</script>
</head>
<body onload="startup()">
<canvas id="myGLCnvas" width="500" height="300"></canvas>
</body>
</html>
for some reason, it says that it can't read property null for createShader here:
shader = gl.createShader(gl.VERTEX_SHADER);
But it doesn't complain at all for the same declaration but with the fragment shader.
Slightly changed version.
gl.celar was wrong and main loop for getting context.
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>2-1 A first WebGL example</title>
<meta charset="utf-8">
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 1.0);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
<script type="text/javascript">
var gl;
var canvas;
var shaderProgram;
var vertexBuffer;
/*Function to create the webgl context*/
function createGLContext(canvas) {
var names = ["webgl", "experimental-webgl"];
gl = null;
for(var i = 0; i < names.length; i++) {
gl = canvas.getContext(names[i]);
if(gl)
break;
}
if(gl) {
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} else {
console.log("Failed to create webgl context");
}
}
function loadShaderFromDOM(id) {
var shaderScript = document.getElementById(id);
//if we don't find an element with the specified id
//we do an early exit
if(!shaderScript) {
return null;
}
//loop through the children for the found DOM element and
//build up the shader source code as a string.
var shaderSource = "";
var currentChild = shaderScript.firstChild;
while(currentChild) {
if(currentChild.nodeType == 3) {
//3 corresponds to TEXT_NODE
shaderSource += currentChild.textContent;
}
currentChild = currentChild.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, shaderSource);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
/*Function to setup the shaders*/
function setupShaders() {
var vertexShader = loadShaderFromDOM("shader-vs");
var fragmentShader = loadShaderFromDOM("shader-fs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Failed toe setup shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
}
/*Function to setup the buffers*/
function setupBuffers() {
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
var triangleVertices = [
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
vertexBuffer.itemSize = 3;
vertexBuffer.numberOfItems = 3;
}
/*Function to draw the triangle*/
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems);
}
/*Function to kick everything off*/
function startup() {
canvas = document.getElementById("myGLCnvas");
createGLContext(canvas);
setupShaders();
setupBuffers();
gl.clearColor(0.0, 0.0, 0.0, 0.1);
draw();
}
</script>
</head>
<body onload="startup()">
<canvas id="myGLCnvas" width="500" height="300"></canvas>
</body>
</html>
I had the same problem, where I have one page that is an open scene that starts as a html that works and the other page is a death match with and the map and unitsize using and external main file and not hard coded and it doesn't work. Both pages are the same code
The difference was between three.js and three.min.js. The .min file worked.
I'm trying to figure out a good way to render mathematical functions using WebGL. Or just everything that I put in an array, like basic mathematical functions. So here I just put some 3D coordinate in an array, it does not seem to work.
This are my code lines:
arrays.js [UPDATED]
var myPosArray = [];
var myArrBuffer = null;
var x = 0, y = 0, z = 0;
/*Function that fills the array*/
function dotter() {
myArrBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, myArrBuffer);
for (var i = 0; i < 10; ++i) {
x = Math.cos(i * Math.PI / 3);
y = Math.sin(i * Math.PI / 4);
z = x + y;
myPosArray.push(x);
myPosArray.push(y);
myPosArray.push(z);
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(myPosArray), gl.STATIC_DRAW);
myArrBuffer.itemSize = 3;
myArrBuffer.numItems = myPosArray.lenght / 3;
}
/*This function is supposed to draw the points*/
function drawPoints(){
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);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*Draw triangle*/
mat4.translate(mvMatrix, [ -1.5, 0.0, -7.0 ]);
gl.bindBuffer(gl.ARRAY_BUFFER, myArrBuffer);
gl.vertexAttribArray(shaderProgram.vertexPositionAttribute, myArrBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, myArrBuffer.numItems);
}
shaders:
i set up the shaders here [UPDATED]:
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 mvMatrix;
uniform mat4 pMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = pMatrix * mvMatrix * vec4(aVertexPosition, 1.0);
}
</script>
schaders.js
/* Setting shaders up */
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
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 lightingShaders(){
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "pMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "mvMatrix");
}
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);
lightingShaders();
}
As you say, there were some small errors, but I think the real problem here is that you didn't set the matrix uniforms before you call gl.drawArrays. I assume you're following the tutorials on http://learningwebgl.com/, so the last 3 lines in drawPoints() should be:
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
myArrBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.POINTS, 0, myArrBuffer.numItems);
where setMatrixUniforms() is defined as:
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
Note that I also changed gl.vertexAttribArray to gl.vertexAttribPointer.
Using the translation matrix
mat4.translate(mvMatrix, [ 0.0, 0.0, -7.0 ]);
and setting the point size to 10 in the vertex shader for visibility
gl_PointSize = 10.0;
here's the output I got: