I am trying to get a square drawn on to a html canvas using GLSL and I am actually having a hard time understanding the errors. Here is my code for defining vertex and fragment shaders.Also Don't forget to leave a comment about the question
<script type="x-shader/x-vertex" id="VertexShader">
attribute vec3 aSquareVertexPosition;
void(main){
gl_Position = vec4(aSquareVertexPosition, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="FragmentShader">
void(main){
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
And here is my code for loading and compiling above glsl code.
var gSimpleShader = null;
var gShaderVertexPositionAttribute = null;
function loadAndCompile(id, shaderType) {
var shaderText, shaderSource, compiledShader;
shaderText = document.getElementById(id);
shaderSource = shaderText.firstChild.textContent;
compiledShader = gGL.createShader(shaderType);
gGL.shaderSource(compiledShader, shaderSource);
gGL.compileShader(compiledShader);
var errorOrNot = gGL.getShaderParameter(compiledShader, gGL.COMPILE_STATUS);
if (!errorOrNot){
console.error(gGL.getShaderInfoLog(compiledShader));
}
return compiledShader;
}
function initSimpleShader(vertexShaderID, fragmentShaderID) {
var vertexShader = loadAndCompile(vertexShaderID, gGL.VERTEX_SHADER);
var fragmentShader = loadAndCompile(fragmentShaderID, gGL.FRAGMENT_SHADER);
gSimpleShader = gGL.createProgram();
gGL.attachShader(gSimpleShader, vertexShader);
gGL.attachShader(gSimpleShader, fragmentShader);
gGL.linkProgram(gSimpleShader);
var errorOrNot = gGL.getProgramParameter(gSimpleShader, gGL.LINK_STATUS);
if (!errorOrNot){
console.error(gGL.getProgramInfoLog(gSimpleShader));
}
gShaderVertexPositionAttribute = gGL.getAttribLocation(gSimpleShader, "aSquareVertexPosition");
gGL.bindBuffer(gGL.ARRAY_BUFFER, gSquareVertexBuffer);
gGL.vertexAttribPointer(gShaderVertexPositionAttribute, 3, gGL.FLOAT, false, 0, 0);
}
this is where the gSquareVertexBuffer variable from above code is defined.
"use strict";
var gSquareVertexBuffer = null;
function initSquareBuffer() {
var verticesOfSquare =
[
0.5, 0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0,
];
gSquareVertexBuffer = gGL.createBuffer();
gGL.bindBuffer(gGL.ARRAY_BUFFER, gSquareVertexBuffer);
gGL.bufferData(gGL.ARRAY_BUFFER, new Float32Array(verticesOfSquare), gGL.STATIC_DRAW);
}
And I call these functions in another file as below.
"use strict";
var gGL = null;
function initializeGL()
{
var canvas = document.getElementById("GLCanvas");
gGL = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
if (gGL != null){
gGL.clearColor(0.0, 0.0, 1.0, 1.0);
initSquareBuffer();
initSimpleShader("VertexShader", "FragmentShader");
}else{
document.write("<br><b>WebGL is not supported</b>");
}
}
function drawSquare()
{
gGL.clear(gGL.COLOR_BUFFER_BIT);
gGL.useProgram(gSimpleShader);
gGL.enableVertexAttribArray(gShaderVertexPositionAttribute);
gGL.drawArrays(gGL.TRANGLE_STRIP, 0, 4);
}
function doGLDraw()
{
initializeGL();
drawSquare();
}
After I open the index.html file in the browser I can only see the canvas and I get the following errors in the console.
Must have a compiled vertex shader attached: SHADER_INFO_LOG: ERROR: 0:3: '(' : syntax error
And also these WebGL warnings
WebGL warning: linkProgram: Must have a compiled vertex shader attached: SHADER_INFO_LOG: ERROR: 0:3: '(' : syntax error
WebGL warning: vertexAttribI?Pointer: index (4294967295) must be < MAX_VERTEX_ATTRIBS.
WebGL warning: useProgram: Program must be linked successfully.
WebGL warning: enableVertexAttribArray: -1 is not a valid index. This value probably comes from a getAttribLocation() call, where this return value -1 means that the passed name didn't correspond to an active attribute in the specified program.
WebGL warning: drawArraysInstanced: The current program is not linked.
I am new to WebGL and javaScript so don't forget to leave a comment.
There is a syntax error in the vertex shader and in the fragment shader. void is the return type. The name of the main function is main:
void(main){
void main(){
// [...]
}
Furthermore, it is TRIANGLE_STRIP not TRANGLE_STRIP
gGL.drawArrays(gGL.TRANGLE_STRIP, 0, 4);
gGL.drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
var gSimpleShader = null;
var gShaderVertexPositionAttribute = null;
function loadAndCompile(id, shaderType) {
var shaderText, shaderSource, compiledShader;
shaderText = document.getElementById(id);
shaderSource = shaderText.firstChild.textContent;
compiledShader = gGL.createShader(shaderType);
gGL.shaderSource(compiledShader, shaderSource);
gGL.compileShader(compiledShader);
var errorOrNot = gGL.getShaderParameter(compiledShader, gGL.COMPILE_STATUS);
if (!errorOrNot){
console.error(gGL.getShaderInfoLog(compiledShader));
}
return compiledShader;
}
function initSimpleShader(vertexShaderID, fragmentShaderID) {
var vertexShader = loadAndCompile(vertexShaderID, gGL.VERTEX_SHADER);
var fragmentShader = loadAndCompile(fragmentShaderID, gGL.FRAGMENT_SHADER);
gSimpleShader = gGL.createProgram();
gGL.attachShader(gSimpleShader, vertexShader);
gGL.attachShader(gSimpleShader, fragmentShader);
gGL.linkProgram(gSimpleShader);
var errorOrNot = gGL.getProgramParameter(gSimpleShader, gGL.LINK_STATUS);
if (!errorOrNot){
console.error(gGL.getProgramInfoLog(gSimpleShader));
}
gShaderVertexPositionAttribute = gGL.getAttribLocation(gSimpleShader, "aSquareVertexPosition");
gGL.bindBuffer(gGL.ARRAY_BUFFER, gSquareVertexBuffer);
gGL.vertexAttribPointer(gShaderVertexPositionAttribute, 3, gGL.FLOAT, false, 0, 0);
}
var gSquareVertexBuffer = null;
function initSquareBuffer() {
var verticesOfSquare =
[
0.5, 0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0,
];
gSquareVertexBuffer = gGL.createBuffer();
gGL.bindBuffer(gGL.ARRAY_BUFFER, gSquareVertexBuffer);
gGL.bufferData(gGL.ARRAY_BUFFER, new Float32Array(verticesOfSquare), gGL.STATIC_DRAW);
}
var gGL = null;
function initializeGL()
{
var canvas = document.getElementById("GLCanvas");
gGL = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
if (gGL != null){
gGL.clearColor(0.0, 0.0, 1.0, 1.0);
initSquareBuffer();
initSimpleShader("VertexShader", "FragmentShader");
}else{
document.write("<br><b>WebGL is not supported</b>");
}
}
function drawSquare()
{
gGL.clear(gGL.COLOR_BUFFER_BIT);
gGL.useProgram(gSimpleShader);
gGL.enableVertexAttribArray(gShaderVertexPositionAttribute);
gGL.drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(drawSquare);
}
function doGLDraw()
{
initializeGL();
drawSquare();
}
doGLDraw()
<script type="x-shader/x-vertex" id="VertexShader">
attribute vec3 aSquareVertexPosition;
void main(){
gl_Position = vec4(aSquareVertexPosition, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="FragmentShader">
void main(){
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
<canvas id="GLCanvas"></canvas>
Related
I am trying to write a function to draw a triangle (it's in main() now). everything works - everything is cool, but I added the execution of two functions for drawing point ( drawPoint()) and the point that is drawn after the triangle is displayed in the wrong place, why?
index.html :
<!DOCTYPE html>
<html>
<head>
<title>
the rgb
</title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400">
PLZ USE BROWSER SUPPORTING CANVAS
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script src="thergb.js"></script>
</body>
</html>
thergb.js:
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
function main()
{
clearCanvas('green');
drawPoint(0.3,0.0,50.0,'blue'); //draw point before triangle
//draw triangle
var VSHADER_SOURCE=
'attribute vec4 a_Position;\n'+
'void main() {\n' +
' gl_Position = a_Position;\n'+
'}\n';
var FSHADER_SOURCE=
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n'+
'}\n';
if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
return;
}
var n = initVertexBuffers(gl);
gl.drawArrays(gl.TRIANGLES, 0, n);
drawPoint(0.4,0.0,50.0,'red'); //draw point after triangle
}
function initVertexBuffers(gl) {
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3; // The number of vertices
// Create a buffer object
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// Write date into the buffer object
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
// Assign the buffer object to a_Position variable
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
// Enable the assignment to a_Position variable
gl.enableVertexAttribArray(a_Position);
return n;
}
function drawPoint(x,y,size,color)
{
var VSHADER_SOURCE=
'attribute vec4 a_Position;\n'+
'attribute float a_PointSize;\n'+
'void main() {\n' +
' gl_Position = a_Position;\n'+
' gl_PointSize = a_PointSize;\n'+
'}\n';
if (color == 'red')
{
var FSHADER_SOURCE=
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n'+
'}\n';
}
if (color == 'green')
{
var FSHADER_SOURCE=
'void main() {\n' +
' gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n'+
'}\n';
}
if (color == 'blue')
{
var FSHADER_SOURCE=
'void main() {\n' +
' gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n'+
'}\n';
}
if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
return;
}
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
gl.vertexAttrib3f(a_Position,x,y,0.0);
gl.vertexAttrib1f(a_PointSize, size);
gl.drawArrays(gl.POINTS, 0,1);
}
function clearCanvas(color)
{
if (color == 'red')
{
gl.clearColor( 1.0, 0.0, 0.0, 1.0);
}
if (color == 'green')
{
gl.clearColor( 0.0, 1.0, 0.0, 1.0);
}
if (color == 'blue')
{
gl.clearColor( 0.0, 0.0, 1.0, 1.0);
}
gl.clear(gl.COLOR_BUFFER_BIT);
}
additional libraries are on my github: https://github.com/bazylevnik0/thergb
The reason the point after the triangle shows up in the wrong place is that when the triangle is drawn it enables the attributes with gl.enableVertexAttribArray
An enabled attribute gets its values from a buffer assigned when calling gl.vertexAttribPointer
A disabled attribute gets its value from a constant set by gl.vertexAttrib???
In drawPoint, the gl.vertexAttrib3f functions, they set the constant for that attribute, but when it comes time to draw the second point the attributes are enabled which means it's looking in the buffers assigned when the triangle was drawn not the constant.
If you add
gl.disableVertexAttribArray(a_Position);
gl.disableVertexAttribArray(a_PointSize);
in drawPoint before drawing it should work.
You might find this state diagram helpful in understanding what is being set by the various functions
I keep getting the following error when I run my code: "INVALID_VALUE: getAttribLocation: no object or object deleted"
I am brand new to webGL and any help will be greatly appreciated! Sorry if this question is too broad.
HTML
<html>
<head>
<script type="text/javascript" src = "prog1.js"></script>
<script type="text/javascript" src = "webgl-utils.js"></script>
<script type="text/javascript" src = "webgl-debug.js"></script>
<script type="text/javascript" src = "cuon-utils.js"></script>
<script type="text/javascript" src = "cuon-matrix.js"></script>
</head>
<body onload="init()">
<script id ="vertexShader" type="x-shader/x-vertex">
precision mediump float;
attribute vec4 vertexPosition;
void main(){
gl_position = vertexPosition;
}
</script>
<script id ="fragmentShader" type ="x-shader/x-fragment">
void main(){
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
</script>
<canvas id = "webgl" width = "300" height = "300"></canvas>
</body>
</html>
JAVASCRIPT
function flatten(a) {
return a.reduce(function(b, v) {
b.push.apply(b, v);
return b
}, [])
}
function init() {
var positions = [
[-0.25, 0.5, 0],
[-0.5, 0.0, 0],
[0.0, 0.0, 0.0]
];
var triangles = [
[0, 1, 2]
];
// initialize the GL context
canvas = document.getElementById("webgl");
gl = getWebGLContext(canvas, false);
// initialize the program object
var vertexSource = document.getElementById("vertexShader").text;
var fragmentSource = document.getElementById("fragmentShader").text;
program = createProgram(gl, vertexSource, fragmentSource);
gl.useProgram(program);
// initialize the buffer objects
positionBuffer = gl.createBuffer();
triangleBuffer = gl.createBuffer();
// copy vertex data to the gpu
positionArray = new Float32Array(flatten(positions));
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positionArray, gl.STATIC_DRAW);
// copy triangle data to the gpu
triangleArray = new Uint16Array(flatten(triangles));
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, triangleArray, gl.STATIC_DRAW);
requestAnimationFrame(draw);
}
function draw() {
var vertexSource = document.getElementById("vertexShader").text;
var fragmentSource = document.getElementById("fragmentShader").text;
gl.clearColor(0.0, 0.8, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
var vertexPositionLocation = gl.getAttribLocation(program, "vertexPosition");
gl.vertexAttribPointer(vertexPositionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vertexPositionLocation);
gl.drawElements(gl.TRIANGLES, triangleArray.length, gl.UNSIGNED_SHORT, 0);
}
Your shader program probably didn't compile/link and your createProgram function returned null. The error explains it directly
INVALID_VALUE: getAttribLocation: no object or object deleted"
Since getAttribLocation takes only 2 values. The first is a WebGLProgram and get second a string. Since your string is a constant then there must be something wrong with your program argument. "no object" probably means "is null" or "undefined"
When I run your code with my substitution for createProgram I get
*** Error compiling shader: ERROR: 0:4: 'gl_position' : undeclared identifier
ERROR: 0:4: 'assign' : cannot convert from 'attribute mediump 4-component vector of float' to 'float'
function flatten(a) {
return a.reduce(function(b, v) {
b.push.apply(b, v);
return b
}, [])
}
function init() {
var positions = [
[-0.25, 0.5, 0],
[-0.5, 0.0, 0],
[0.0, 0.0, 0.0]
];
var triangles = [
[0, 1, 2]
];
// initialize the GL context
canvas = document.getElementById("webgl");
gl = canvas.getContext("webgl");
// initialize the program object
var vertexSource = document.getElementById("vertexShader").text;
var fragmentSource = document.getElementById("fragmentShader").text;
program = createProgram(gl, vertexSource, fragmentSource);
gl.useProgram(program);
// initialize the buffer objects
positionBuffer = gl.createBuffer();
triangleBuffer = gl.createBuffer();
// copy vertex data to the gpu
positionArray = new Float32Array(flatten(positions));
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positionArray, gl.STATIC_DRAW);
// copy triangle data to the gpu
triangleArray = new Uint16Array(flatten(triangles));
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, triangleArray, gl.STATIC_DRAW);
requestAnimationFrame(draw);
}
function draw() {
var vertexSource = document.getElementById("vertexShader").text;
var fragmentSource = document.getElementById("fragmentShader").text;
gl.clearColor(0.0, 0.8, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
var vertexPositionLocation = gl.getAttribLocation(program, "vertexPosition");
gl.vertexAttribPointer(vertexPositionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vertexPositionLocation);
gl.drawElements(gl.TRIANGLES, triangleArray.length, gl.UNSIGNED_SHORT, 0);
}
function createProgram(gl, vs, fs) {
return twgl.createProgramFromSources(gl, [vs, fs]);
}
init();
<script id ="vertexShader" type="x-shader/x-vertex">
precision mediump float;
attribute vec4 vertexPosition;
void main(){
gl_position = vertexPosition;
}
</script>
<script id ="fragmentShader" type ="x-shader/x-fragment">
void main(){
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
</script>
<canvas id = "webgl" width = "300" height = "300"></canvas>
<script src="https://twgljs.org/dist/twgl.min.js"></script>
The bug is it's gl_Position not gl_position. It's case sensitive.
You should probably print your shader compilation and linking errors using standard boilerplate WebGL code and make sure to check the JavaScript console for error messages or use an alert or throw an exception if they fail to compile.
PS: please use running snippets when you can. It's less work for the rest of us.
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 have a simple WebGL application.
It has canvas and a pair of simple shaders:
<canvas id="render" width="320" height="240">
<div id="vertexShader" class="shader">
attribute vec4 position;
void main()
{
gl_Position = position;
}
</div>
<div id="fragmentShader" class="shader">
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
</div>
The application code looks like this:
function getContext() {
var canvas = document.getElementById("render");
return canvas.getContext("webgl");
}
function initContext(context) {
context.clearColor(0.0, 0.0, 0.0, 1.0);
context.clear(context.COLOR_BUFFER_BIT);
}
function getShader(shaderId, type, context) {
var shaderSource = document.getElementById(shaderId).innerHTML;
var shader = context.createShader(type);
context.shaderSource(shader, shaderSource);
context.compileShader(shader);
if (!context.getShaderParameter(shader, context.COMPILE_STATUS)) {
console.log(context.getShaderInfoLog(shader));
return null;
}
return shader;
}
function initShaders(context) {
var program = context.createProgram();
context.attachShader(program, getShader("vertexShader", context.VERTEX_SHADER, context));
context.attachShader(program, getShader("fragmentShader", context.FRAGMENT_SHADER, context));
context.linkProgram(program);
if (!context.getProgramParameter(program, context.LINK_STATUS)) {
console.log("Could not initialise shaders");
}
return program;
}
function renderTile(context, program) {
var tileBuffer = context.createBuffer();
var tile = [
1.0, 1.0, 0, 1.0,
-1.0, 0, 0, 1.0,
1.0, -1.0, 0, 1.0
];
context.bindBuffer(context.ARRAY_BUFFER, tileBuffer);
context.bufferData(context.ARRAY_BUFFER, new Float32Array(tile), context.STATIC_DRAW);
positionLocation = context.getAttribLocation(program, "position");
context.enableVertexAttribArray(positionLocation);
context.vertexAttribPointer(positionLocation, 4, context.FLOAT, false, 0, 0);
context.drawArrays(context.TRIANGLES, 0, 3);
}
var context = getContext();
initContext(context);
var program = initShaders(context);
context.useProgram(program);
setTimeout(function() {
renderTile(context, program);
}, 100);
It renders a simple triangle on a canvas.
The problem is that it sometimes renders a triangle on a white background although clear color is set to non-transparent black. (in latest Google Chrome, Firefox is ok)
While debugging I found that white background is rendered when drawArrays method is called.
But I can't understand why it is not black.
Here is a jsFiddle for your convenience.
In your example you just have to clear your color buffer every "frame". Your background is black at first, then gets "overwritten" by your triangle (that vertices buffer), like you mentioned.
You actually just do one clear in your init function at startup.
function initContext(context) {
context.clearColor(0.0, 0.0, 0.0, 1.0);
context.clear(context.COLOR_BUFFER_BIT);
}
Just add context.clear(context.COLOR_BUFFER_BIT); to your update function, for example:
setInterval(function() {
context.clear(context.COLOR_BUFFER_BIT);
renderTile(context, program);
}, 100);
See this updated jsFiddle.
I have this segment of code:
function setupWebGL() {
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,400,300);
mat4.perspective(45, 400 / 300, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0, 0, -2.0]);
}
And everything in the code runs except the very last line
mat4.translate(mvMatrix, [0, 0, -2.0]);
I know this because I put alert functions after every line until they failed to run (I need a better way of debugging in chrome, any suggestions?)
I'm using the gl-Matrix library found here https://github.com/toji/gl-matrix/blob/master/dist/gl-matrix-min.js
Any ideas on why that line is stopping the code execution?
Here is the full code:
<!doctype html>
<html>
<head>
<title>WebGL - Chapter One - Lol</title>
<style>
body{ background-color: grey; }
canvas{ background-color: white; }
</style>
<script src = "gl-matrix-min.js"></script>
<script src = "raf_polyfill.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying highp vec4 vColor;
void main(void){
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = vec4(aVertexColor, 1.0);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
varying highp vec4 vColor;
void main(void){
gl_FragColor = vColor;
}
</script>
<script>
var gl = null,
canvas = null,
glProgram = null,
fragmentShader = null,
vertexShader = null;
var vertexPositionAttribute = null,
trianglesVerticeBuffer = null,
vertexColorAttribute = null,
trianglesColorBuffer = null;
var angle = 0.0;
var mvMatrix = mat4.create(),
pMatrix = mat4.create();
function initWebGL(){
var canvas = document.getElementById("my-canvas");
try{
gl = canvas.getContext("experimental-webgl");
}catch(e){}
if(gl){
initShaders();
setupBuffers();
getMatrixUniforms();
animLoop();
}else{
alert("Error: Your browser does not appear to support WebGL.");
}
}
function animLoop(){
setupWebGL();
setupDynamicBuffers();
setMatrixUniforms();
drawScene();
requestAnimationFrame(animLoop,canvas);
}
function setupWebGL() {
//sets the clear color to red lol
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,400,300);
mat4.perspective(45, 400 / 300, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0, 0, -2.0]);
}
function initShaders(){
var fs_source = document.getElementById("shader-fs").innerHTML;
var vs_source = document.getElementById("shader-vs").innerHTML;
//compile shaders
vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);
//create program
glProgram = gl.createProgram();
//attach and link shaders to the program
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
}
//use program
gl.useProgram(glProgram);
}
function makeShader(src, type) {
//compile the vertex shader
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
}
return shader;
}
function getMatrixUniforms(){
glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix");
glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix");
}
function setMatrixUniforms(){
gl.unifromMatrix4fv(glProgram.pMatrixUniform, false, pMatrix);
gl.unifromMatrix4fv(glProgram.mvMatrixUniform, false, mvMatrix);
}
function setupBuffers() {
var triangleVerticeColors = [
1.0, 0.0, 0.0,
1.0, 1.0, 1.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
0.0, 0.0, 1.0
];
trianglesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW);
}
function setupDynamicBuffers(){
var xTran = Math.sin(angle)/2.0;
var triangleVertices = [
-0.5 + xTran, 0.5, -0.5,
0.0 + xTran, 0.0, -0.5,
-0.5 + xTran, -0.5, -0.5,
0.5 + xTran, 0.5, -0.5,
0.0 + xTran, 0.0, -0.5,
0.5 + xTran, -0.5, -0.5
];
angle += 0.05;
trianglesVerticeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.DYNAMIC_DRAW);
}
function drawScene() {
vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
</script>
</head>
<body onload="initWebGL()">
<canvas id="my-canvas" width="400" height="300">
Your browser does not support the HTML5 canvas element.
</canvas>
</body>
</html>
Use the new API:
Old API
mat4.translate(mvMatrix, [0, 0, -2.0]);
New API
var translation = vec3.create();
vec3.set (translation, 0, 0, -2.0);
mat4.translate (mvMatrix, mvMatrix, translation);
You have a typo:
unifromMatrix4fv should be uniformMatrix4fv in function setMatrixUniforms.
I'm not sure if this fixes your problem or not, or why you thought your problem was with mat4.translate. You can always open the JavaScript console (F12 if you're running Chrome in Windows) and it'll tell you what the error is.