Need to create a smooth alpha transition from three color vertices without, breaking. what am i doing wrong.
https://jsfiddle.net/Lm208gjq/
var vertexShaderText =
[
'precision mediump float;',
'',
'attribute vec2 vertPosition;',
'attribute vec4 vertColor;',
'varying vec4 fragColor;',
'',
'void main()',
'{',
' fragColor = vertColor;',
' gl_Position = vec4(vertPosition, 0.0, 1.0);',
'}'
].join('\n');
var fragmentShaderText =
[
'precision mediump float;',
'',
'varying vec4 fragColor;',
'void main()',
'{',
' gl_FragColor = fragColor;',
'}'
].join('\n');
var InitDemo = function () {
console.log('This is working');
var canvas = document.getElementById('opengl_output');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('Your browser does not support WebGL');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//
// Create shaders
//
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShaderText);
gl.shaderSource(fragmentShader, fragmentShaderText);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error('ERROR compiling vertex shader!', gl.getShaderInfoLog(vertexShader));
return;
}
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.error('ERROR compiling fragment shader!', gl.getShaderInfoLog(fragmentShader));
return;
}
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('ERROR linking program!', gl.getProgramInfoLog(program));
return;
}
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
console.error('ERROR validating program!', gl.getProgramInfoLog(program));
return;
}
//
// Create buffer
//
var triangleVertices =
[ // X, Y, R, G, B, A
0.0, 0.5, 1.0, 0.0, 0.0, 1.0,
-0.5, -0.5, 0.0, 1.0, 0.0, 0.0001,
0.5, -0.5, 0.0, 0.0, 1.0, 1.0
];
var triangleVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
var positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');
var colorAttribLocation = gl.getAttribLocation(program, 'vertColor');
gl.vertexAttribPointer(
positionAttribLocation, // Attribute location
2, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
colorAttribLocation, // Attribute location
4, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
2 * Float32Array.BYTES_PER_ELEMENT // Offset from the beginning of a single vertex to this attribute
);
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ZERO);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
//
// Main render loop
//
gl.useProgram(program);
gl.drawArrays(gl.TRIANGLES, 0, 3);
};
InitDemo();
<canvas id="opengl_output" width="640" height="480"></canvas>
Why is this code producing another triangle?
Im new to this webgl programming, it could be something simple iv'e tried to change the attribute buffer with no success.
The default alpha compositing is premultiplied alpha.
Either you've to disable premultipliedAlpha,
var gl = canvas.getContext('webgl', { premultipliedAlpha: false });
Or you've to multiply the RGB color channels by the ALPHA channel in the fragment shader:
gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);
See WebGLFundamentals - WebGL and Alpha
var vertexShaderText =
[
'precision mediump float;',
'',
'attribute vec2 vertPosition;',
'attribute vec4 vertColor;',
'varying vec4 fragColor;',
'',
'void main()',
'{',
' fragColor = vertColor;',
' gl_Position = vec4(vertPosition, 0.0, 1.0);',
'}'
].join('\n');
var fragmentShaderText =
[
'precision mediump float;',
'',
'varying vec4 fragColor;',
'void main()',
'{',
' gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);',
'}'
].join('\n');
var InitDemo = function () {
console.log('This is working');
var canvas = document.getElementById('opengl_output');
var gl = canvas.getContext('webgl' /*, { premultipliedAlpha: false }*/);
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl' /*, { premultipliedAlpha: false }*/);
}
if (!gl) {
alert('Your browser does not support WebGL');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//
// Create shaders
//
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShaderText);
gl.shaderSource(fragmentShader, fragmentShaderText);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error('ERROR compiling vertex shader!', gl.getShaderInfoLog(vertexShader));
return;
}
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.error('ERROR compiling fragment shader!', gl.getShaderInfoLog(fragmentShader));
return;
}
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('ERROR linking program!', gl.getProgramInfoLog(program));
return;
}
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
console.error('ERROR validating program!', gl.getProgramInfoLog(program));
return;
}
//
// Create buffer
//
var triangleVertices =
[ // X, Y, R, G, B, A
0.0, 0.5, 1.0, 0.0, 0.0, 1.0,
-0.5, -0.5, 0.0, 1.0, 0.0, 0.0001,
0.5, -0.5, 0.0, 0.0, 1.0, 1.0
];
var triangleVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
var positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');
var colorAttribLocation = gl.getAttribLocation(program, 'vertColor');
gl.vertexAttribPointer(
positionAttribLocation, // Attribute location
2, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
colorAttribLocation, // Attribute location
4, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
2 * Float32Array.BYTES_PER_ELEMENT // Offset from the beginning of a single vertex to this attribute
);
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ZERO);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
//
// Main render loop
//
gl.useProgram(program);
gl.drawArrays(gl.TRIANGLES, 0, 3);
};
InitDemo();
<canvas id="opengl_output" width="640" height="480"></canvas>
Related
I have been trying to draw a triangle but it is not showing up on the canvas
here is my draw function code:
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight)gl.clear(gl.COLOR_BUFFER_BIT)
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute)
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
}
here is the whole work:
const vertexShaderText = [
'attribute vec3 vertexPos;',
'',
'void main() {',
' gl_Position = vec4(vertexPos, 1.0);',
'}'
].join('\n')
const fragmentShaderText = [
'precision mediump float;',
'',
'void main() {',
' gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);',
'}'
].join('\n')
let gl, shaderProgram, buffer
function startup() {
const canvas = document.getElementById('myCanvas')
gl = canvas.getContext('webgl')
initShader()
initBuffer()
gl.clearColor(0.0, 0.0, 0.0, 1.0)
draw()
}
function initShader() {
// VERTEX SHADER
let vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertexShaderText)
gl.compileShader(vertexShader)
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert('vertex', gl.getShaderInfoLog(vertexShader))
return
}
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, fragmentShaderText)
gl.compileShader(fragmentShader)
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert('fragment', gl.getShaderInfoLog(fragmentShader))
return
}
shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Failed to setup shaders')
}
gl.useProgram(shaderProgram)
shaderProgram.vertextPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
//gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)
}
function initBuffer() {
buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
const 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)
buffer.itemSize = 3
buffer.numberOfItems = 3
console.log(shaderProgram)
}
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute)
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
}
startup()
<canvas id="myCanvas" width="500" height="500"></canvas>
There are some issues:
The properties gl.viewportWidth and gl.viewportHeight are never set:
gl = canvas.getContext('webgl')
gl.viewportWidth = canvas.clientWidth;
gl.viewportHeight = canvas.clientHeight;
In the array of vertex coordinates is a , instead of a .
const triangleVertices = [
0.0, 0,5, 0.0, // <---- this line
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
And there is a typo , you wrote vertextPositionAttribute instead of vertexPositionAttribute, when you get the attribute index:
shaderProgram.vertextPositionAttribute = // <--- typo
gl.getAttribLocation(shaderProgram, 'vertexPos')
But in general your code works:
const vertexShaderText = [
'attribute vec3 vertexPos;',
'',
'void main() {',
' gl_Position = vec4(vertexPos, 1.0);',
'}'
].join('\n')
const fragmentShaderText = [
'precision mediump float;',
'',
'void main() {',
' gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);',
'}'
].join('\n')
let gl, shaderProgram, buffer
function startup() {
const canvas = document.getElementById('myCanvas')
gl = canvas.getContext('webgl')
gl.viewportWidth = canvas.clientWidth;
gl.viewportHeight = canvas.clientHeight;
initShader()
initBuffer()
gl.clearColor(0.0, 0.0, 0.0, 1.0)
draw()
}
function initShader() {
// VERTEX SHADER
let vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertexShaderText)
gl.compileShader(vertexShader)
if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert('vertex', gl.getShaderInfoLog(vertexShader))
return
}
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, fragmentShaderText)
gl.compileShader(fragmentShader)
if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert('fragment', gl.getShaderInfoLog(fragmentShader))
return
}
shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader )
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Failed to setup shaders')
}
gl.useProgram(shaderProgram)
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
//gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)
}
function initBuffer() {
buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
const 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)
buffer.itemSize = 3
buffer.numberOfItems = 3
console.log(shaderProgram)
}
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
requestAnimationFrame(draw);
}
startup()
<canvas id="myCanvas" width="500" height="500"></canvas>
Some issues
There is no such thing as gl.viewportWidth and gl.viewportHeight
Use gl.canvas.width and gl.canvas.height.
There's a site out there that teaches using gl.viewportWidth and gl.viewportHeight. It is arguably an anti-pattern. Those variables are not part of WebGL. They are user variables being added by the example onto the WebGL context. There is absolutely zero reason to do that as they will always have to be manually updated and the actual width and height are always available.
Typo in triangleVertices
The second comma below should be a period
bad
const triangleVertices = [
0.0, 0, 5, 0.0, -0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
good
const triangleVertices = [
0.0, 0.5, 0.0, -0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
With that it runs but here's another typo
vertextPositionAttribute should be vertexPositionAttribute
shaderProgram.vertextPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
//gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)
That said here's a bunch of suggestions.
Use multiline template literals for shaders
Instead of
const vertexShaderText = [
'attribute vec3 vertexPos;',
'',
'void main() {',
' gl_Position = vec4(vertexPos, 1.0);',
'}'
].join('\n')
do this
const vertexShaderText = `
attribute vec3 vertexPos;
void main() {
gl_Position = vec4(vertexPos, 1.0);
}
`;
So much easier! Use backticks instead of quotes for multi-line strings
Make initShader return a shader rather than assign a global
It's not common to have a single shader in WebGL so it's much more useful to have a function that creates shaders
Don't call gl.useProgram in initShader
Again it's not common to have a single shader. Calling gl.useProgram generally belongs in draw
Don't add attributes to browser objects, especially WebGL objects
bad
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos');
good (one of many ways)
const shaderProgramInfo = {}
shaderProgramInfo.program = initShader(...)
shaderProgramInfo.vertexPositionAttribute =
gl.getAttribLocation(shaderProgramInfo.program, 'vertexPos');
This is because if initShader fails (for example the context is lost) your gl.createProgram will be null and trying to assign a property to null will cause your page to fail. The same issue with buffer
bad
const buffer = gl.createBuffer();
...
buffer.itemSize = 3
buffer.numberOfItems = 3
good (one of many ways)
const bufferInfo = {
buffer: gl.createBuffer(),
}
...
bufferInfo.itemSize = 3
bufferInfo.numberOfItems = 3
Call gl.bindBuffer before calling gl.vertexAttribPointer
Your code works because there is only one buffer. If there are 2 buffers it would likely stop working because gl.vertexAttribPointer references the currently bound buffer
Consider Reading better tutorials.
I'd recommend https://webglfundamentals.org
const vertexShaderText = `
attribute vec3 vertexPos;
void main() {
gl_Position = vec4(vertexPos, 1.0);
}
`;
const fragmentShaderText = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
let gl, shaderProgramInfo, bufferInfo
function startup() {
const canvas = document.getElementById('myCanvas')
gl = canvas.getContext('webgl')
shaderProgramInfo = {
program: initShader(gl, vertexShaderText, fragmentShaderText),
};
shaderProgramInfo.vertexPositionAttribute = gl.getAttribLocation(shaderProgramInfo.program, 'vertexPos');
bufferInfo = initBuffer()
gl.clearColor(0.0, 0.0, 0.0, 1.0)
draw()
}
function initShader(gl, vertexShaderText, fragmentShaderText) {
// VERTEX SHADER
let vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertexShaderText)
gl.compileShader(vertexShader)
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert('vertex', gl.getShaderInfoLog(vertexShader))
return
}
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, fragmentShaderText)
gl.compileShader(fragmentShader)
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert('fragment', gl.getShaderInfoLog(fragmentShader))
return
}
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Failed to setup shaders')
}
return shaderProgram;
}
function initBuffer() {
buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
const 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)
return {
buffer,
itemSize: 3,
numberOfItems: 3,
};
}
function draw() {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT)
gl.useProgram(shaderProgramInfo.program)
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.buffer);
gl.vertexAttribPointer(shaderProgramInfo.vertexPositionAttribute,
bufferInfo.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgramInfo.vertexPositionAttribute)
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numberOfItems)
}
startup()
<canvas id="myCanvas" width="500" height="500"></canvas>
I'm busy transferring some code from OpenGL to WebGL2 (to do duel depth peeling) but I'm getting a warning in my console that I cannot make sense of and the output is just black.
I've gone through the process of drawing some of the buffers individually and discovered the warning only appears inside the loop for (var p = 1; p < numPasses; p++) when I do the geometry passes.
The shaders I based mine off also made extensive use of gl_NormalMatrix, gl_ModelViewMatrix, and gl_Vertex that I think could also be a result of the black output. I assume just replacing gl_ModelViewMatrix * gl_Vertex with uProjMatrix * uViewMatrix * uModelMatrix * vec4(inVertexPosition, 1.0); will yield the same result.
(function() {
var script = document.createElement("script");
script.onload = function() {
main();
};
script.src = "https://mdn.github.io/webgl-examples/tutorial/gl-matrix.js";
document.head.appendChild(script);
})();
var initShader, peelShader, blendShader, finalShader;
var accumTex0, accumTex1;
var backBlenderFBO, peelingSingleFBO;
var depthTex = [], frontBlenderTex = [], backTempTex = [], backBlenderTex = [];
var quadVAO;
var drawBuffers;
function main() {
const canvas = document.querySelector("#glcanvas");
const gl = canvas.getContext("webgl2", { alpha: false });
if (!gl) {
alert("Unable to initialize WebGL. Your browser or machine may not support it.");
return;
}
var ext = gl.getExtension("EXT_color_buffer_float");
if (!ext) { alert("Unable to initialize WebGL. Your browser or machine may not support it."); return; }
quadVAO = newMesh(gl);
drawBuffers = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3, gl.COLOR_ATTACHMENT4, gl.COLOR_ATTACHMENT5, gl.COLOR_ATTACHMENT6];
// Dual Peeling Render Targets
backBlenderTex = newTexture(gl, gl.TEXTURE_2D, gl.RGBA32F, 640, 480, gl.RGBA, gl.FLOAT, null);
backBlenderFBO = newFramebuffer(gl, [backBlenderTex]);
depthTex[0] = newTexture(gl, gl.TEXTURE_2D, gl.RG32F, 640, 480, gl.RG, gl.FLOAT, null);
frontBlenderTex[0] = newTexture(gl, gl.TEXTURE_2D, gl.RGBA32F, 640, 480, gl.RGBA, gl.FLOAT, null);
backTempTex[0] = newTexture(gl, gl.TEXTURE_2D, gl.RGBA32F, 640, 480, gl.RGBA, gl.FLOAT, null);
depthTex[1] = newTexture(gl, gl.TEXTURE_2D, gl.RG32F, 640, 480, gl.RG, gl.FLOAT, null);
frontBlenderTex[1] = newTexture(gl, gl.TEXTURE_2D, gl.RGBA32F, 640, 480, gl.RGBA, gl.FLOAT, null);
backTempTex[1] = newTexture(gl, gl.TEXTURE_2D, gl.RGBA32F, 640, 480, gl.RGBA, gl.FLOAT, null);
peelingSingleFBO = newFramebuffer(gl, [depthTex[0], frontBlenderTex[0], backTempTex[0], depthTex[1], frontBlenderTex[1], backTempTex[1], backBlenderTex]);
bindFramebuffer(gl, null);
initShader = newShader(gl, vsInitSource, fsInitSource);
peelShader = newShader(gl, vsPeelSource, fsPeelSource);
blendShader = newShader(gl, vsBlendSource, fsBlendSource);
finalShader = newShader(gl, vsFinalSource, fsFinalSource);
gl.disable(gl.CULL_FACE);
draw(gl);
}
// See below link to make sense of this function
// https://stackoverflow.com/questions/37381980/get-some-trounble-when-using-drawbuffers-in-webgl2
function getDrawBuffers(gl, ...idx) {
var buffers = [gl.NONE, gl.NONE, gl.NONE, gl.NONE, gl.NONE, gl.NONE, gl.NONE];
for (var i = 0; i < idx.length; i++) {
if (i == idx[i]) buffers[i] = drawBuffers[i];
}
return buffers;
}
function draw(gl) {
// setup MVP
const proj = mat4.create();
const cameraSize = 0.2;
mat4.ortho(proj, 0.0, 1.0, 0.0, 1.0, 0.0001, 10.0);
const view = mat4.create();
mat4.lookAt(view, [0, 0, 2], [0, 0, 0], [0, 1, 0]);
gl.disable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
bindFramebuffer(gl, peelingSingleFBO);
gl.drawBuffers(getDrawBuffers(gl, 1, 2));
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
const maxDepth = 1;
gl.drawBuffers(getDrawBuffers(gl, 0));
gl.clearColor(-maxDepth, -maxDepth, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.blendEquation(gl.MAX);
// init
// bindFramebuffer(gl, null); // to test with
// gl.drawBuffers([gl.BACK]); // to test with
gl.useProgram(initShader);
drawMesh(gl, initShader, proj, view, { x: 0.0, y: 0.0, z: 0.0 }, { r: 1.0, g: 0.0, b: 0.0, a: 1.0 });
gl.useProgram(null);
// return; // to test with
// peeling & blending
gl.drawBuffers(getDrawBuffers(gl, 6));
var backgroundColor = [1, 1, 1];
gl.clearColor(backgroundColor[0], backgroundColor[1], backgroundColor[2], 0);
gl.clear(gl.COLOR_BUFFER_BIT);
// return; // to test with
// for each pass
var numPasses = 4;
var currID = 0;
for (var p = 1; p < numPasses; p++) {
currID = p % 2;
var prevID = 1 - currID;
var bufID = currID * 3;
gl.drawBuffers(getDrawBuffers(gl, bufID + 1, bufID + 2));
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawBuffers(getDrawBuffers(gl, bufID));
gl.clearColor(-maxDepth, -maxDepth, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
// all three blending render targets
gl.drawBuffers(getDrawBuffers(gl, bufID, bufID + 1, bufID + 2));
gl.blendEquation(gl.MAX);
gl.useProgram(peelShader);
bindTexture(gl, gl.TEXTURE0, gl.TEXTURE_2D, depthTex[prevID]); // DepthBlenderTex
bindTexture(gl, gl.TEXTURE1, gl.TEXTURE_2D, frontBlenderTex[prevID]); // FrontBlenderTex
gl.uniform1f(gl.getUniformLocation(peelShader, "uAlpha"), 0.6);
drawMesh(gl, peelShader, proj, view, { x: 0.0, y: 0.0, z: 0.0 }, { r: 1.0, g: 0.0, b: 0.0, a: 1.0 });
gl.useProgram(null);
// alpha blend the back color
gl.drawBuffers(getDrawBuffers(gl, 6));
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.useProgram(blendShader);
bindTexture(gl, gl.TEXTURE0, gl.TEXTURE_2D, backTempTex[currID]); // TempTex
drawFullscreenQuad(gl);
gl.useProgram(null);
}
gl.disable(gl.BLEND);
// final pass
bindFramebuffer(gl, null);
gl.drawBuffers([gl.BACK]);
gl.useProgram(finalShader);
bindTexture(gl, gl.TEXTURE0, gl.TEXTURE_2D, depthTex[currID]); // DepthBlenderTex
bindTexture(gl, gl.TEXTURE1, gl.TEXTURE_2D, frontBlenderTex[currID]); // FrontBlenderTex
bindTexture(gl, gl.TEXTURE2, gl.TEXTURE_2D, backBlenderTex); // BackBlenderTex
drawFullscreenQuad(gl);
gl.useProgram(null);
}
function newShader(gl, vsSource, fsSource) {
const vertexShader = loadSource(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadSource(gl, gl.FRAGMENT_SHADER, fsSource);
const 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 the shader program: " + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
function loadSource(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function newMesh(gl) {
var vertices = [1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0];
var indicies = [0, 1, 3, 1, 2, 3];
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
const eb = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, eb);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indicies),
gl.STATIC_DRAW
);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 2 * 4, 0);
gl.enableVertexAttribArray(null);
gl.bindVertexArray(null);
return vao;
}
function drawFullscreenQuad(gl) {
gl.bindVertexArray(quadVAO);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
gl.bindVertexArray(null);
}
function drawMesh(gl, prog, proj, view, pos, col) {
gl.uniformMatrix4fv(gl.getUniformLocation(prog, "uProjMatrix"), false, proj);
gl.uniformMatrix4fv(gl.getUniformLocation(prog, "uViewMatrix"), false, view);
gl.bindVertexArray(quadVAO);
const model = mat4.create();
var trans = vec3.create();
vec3.set(trans, pos.x, pos.y, pos.z);
mat4.translate(model, model, trans);
gl.uniform4fv(gl.getUniformLocation(prog, "uColor"), [col.r, col.g, col.b, col.a]);
gl.uniformMatrix4fv(gl.getUniformLocation(prog, "uModelMatrix"), false, model);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
gl.bindVertexArray(null);
}
function newTexture(gl, target, internalFormat, height, width, format, type, pixels) {
var tid = gl.createTexture();
gl.bindTexture(target, tid);
gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(target, 0, internalFormat, width, height, 0, format, type, pixels);
return tid;
}
function bindTexture(gl, idx, target, id) {
gl.activeTexture(idx);
gl.bindTexture(target, id);
// wait should I be doing glUniforml1(id, ...) here?
}
function newFramebuffer(gl, colorAttachments) {
var fib = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fib);
for (var i = 0; i < colorAttachments.length; i++) {
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
drawBuffers[i],
gl.TEXTURE_2D,
colorAttachments[i],
0
);
}
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
alert(gl.checkFramebufferStatus(gl.FRAMEBUFFER).toString(16));
}
return fib;
}
function bindFramebuffer(gl, fib) {
gl.bindFramebuffer(gl.FRAMEBUFFER, fib);
}
const vsInitSource = `#version 300 es
layout(location=0) in vec3 inVertexPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;
void main(void) {
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(inVertexPosition, 1.0);
}`;
const fsInitSource = `#version 300 es
precision mediump float;
layout(location=0) out vec2 outColor;
void main(void) {
// This seems very important because it is based on the near/far values
// What is the correct value I can expect here?
outColor.xy = vec2(-gl_FragCoord.z, gl_FragCoord.z);
}`;
const vsPeelSource = `#version 300 es
layout(location=0) in vec3 inVertexPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;
// I believe this is what gives the model the green and white stripes
// Not required?
// vec3 ShadeVertex() {
// float diffuse = abs(normalize(gl_NormalMatrix * gl_Normal).z);
// return vec3(gl_Vertex.xy, diffuse);
// }
void main(void) {
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(inVertexPosition, 1.0);
//gl_TexCoord[0].xyz = ShadeVertex();
}`;
const fsPeelSource = `#version 300 es
precision mediump float;
uniform float uAlpha;
#define COLOR_FREQ 30.0
#define ALPHA_FREQ 30.0
vec4 ShadeFragment() {
vec4 color;
color.rgb = vec3(.4,.85,.0);
color.a = uAlpha;
return color;
}
uniform sampler2D DepthBlenderTex;
uniform sampler2D FrontBlenderTex;
#define MAX_DEPTH 1.0
layout(location=0) out vec4 outFragData0;
layout(location=1) out vec4 outFragData1;
layout(location=2) out vec4 outFragData2;
void main(void) {
// window-space depth interpolated linearly in screen space
float fragDepth = gl_FragCoord.z;
vec2 depthBlender = texture(DepthBlenderTex, gl_FragCoord.xy).xy;
vec4 forwardTemp = texture(FrontBlenderTex, gl_FragCoord.xy);
// Depths and 1.0-alphaMult always increase
// so we can use pass-through by default with MAX blending
outFragData0.xy = depthBlender;
// Front colors always increase (DST += SRC*ALPHA_MULT)
// so we can use pass-through by default with MAX blending
outFragData1 = forwardTemp;
// Because over blending makes color increase or decrease,
// we cannot pass-through by default.
// Each pass, only one fragment writes a color greater than 0
outFragData2 = vec4(0.0);
float nearestDepth = -depthBlender.x;
float farthestDepth = depthBlender.y;
float alphaMultiplier = 1.0 - forwardTemp.w;
if (fragDepth < nearestDepth || fragDepth > farthestDepth) {
// Skip this depth in the peeling algorithm
outFragData0.xy = vec2(-MAX_DEPTH);
return;
}
if (fragDepth > nearestDepth && fragDepth < farthestDepth) {
// This fragment needs to be peeled again
outFragData0.xy = vec2(-fragDepth, fragDepth);
return;
}
// If we made it here, this fragment is on the peeled layer from last pass
// therefore, we need to shade it, and make sure it is not peeled any farther
vec4 color = ShadeFragment();
outFragData0.xy = vec2(-MAX_DEPTH);
if (fragDepth == nearestDepth) {
outFragData1.xyz += color.rgb * color.a * alphaMultiplier;
outFragData1.w = 1.0 - alphaMultiplier * (1.0 - color.a);
} else {
outFragData2 += color;
}
}`;
const vsBlendSource = `#version 300 es
layout(location=0) in vec3 inVertexPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;
void main(void) {
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(inVertexPosition, 1.0);
}`;
const fsBlendSource = `#version 300 es
precision mediump float;
uniform sampler2D TempTex;
layout(location=0) out vec4 outColor;
void main(void) {
outColor = texture(TempTex, gl_FragCoord.xy);
// for occlusion query
if (outColor.a == 0.0) discard;
}`;
const vsFinalSource = `#version 300 es
layout(location=0) in vec3 inVertexPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;
void main(void) {
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(inVertexPosition, 1.0);
}`;
const fsFinalSource = `#version 300 es
precision mediump float;
uniform sampler2D DepthBlenderTex;
uniform sampler2D FrontBlenderTex;
uniform sampler2D BackBlenderTex;
layout(location=0) out vec4 outColor;
void main(void)
{
vec4 frontColor = texture(FrontBlenderTex, gl_FragCoord.xy);
vec3 backColor = texture(BackBlenderTex, gl_FragCoord.xy).rgb;
float alphaMultiplier = 1.0 - frontColor.w;
// front + back
outColor.rgb = frontColor.rgb + backColor * alphaMultiplier;
// front blender
// outColor.rgb = frontColor.rgb + vec3(alphaMultiplier);
// back blender
// outColor.rgb = backColor;
}`;
<canvas id="glcanvas" width="640" height="480"></canvas>
Using the same Texture for reading and writing in the Framebuffer is not alowed GLSL (see Point 6.27 at https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.26)
But you can create two FrameBuffers with seperate textures and swap then every Frame. So you can read from the last rendered and write to the second Texture and when done simply swap it.
I can't seem to figure out why my code isn't working. When I run it I get these errors:
Error: WebGL warning: vertexAttribPointer: Bad type: NONE
Error: WebGL warning: drawArrays: no VBO bound to enabled vertex attrib index 1u!
I followed this example: Link
EDIT: now the code works, it should show a colored triangle
MyCode:
var gl;
var shaderProgram;
var triangleVertices =
[ // X, Y, R, G, B
0.0, 0.5, 1.0, 1.0, 0.0,
-0.5, -0.5, 0.7, 0.0, 1.0,
0.5, -0.5, 0.1, 1.0, 0.6
];
var triangleVertexBufferObject;
var positionAttribLocation;
var colorAttribLocation;
var vertShaderCode = 'precision mediump float;'+
'attribute vec2 vertPosition;'+
'attribute vec3 vertColor;'+
'varying vec3 fragColor;'+
'void main()'+
'{'+
' fragColor = vertColor;'+
' gl_Position = vec4(vertPosition, 0.0, 1.0);'+
'}';
var fragShaderCode =
'precision mediump float;'+
'varying vec3 fragColor;'+
'void main()'+
'{'+
' gl_FragColor = vec4(fragColor, 1.0);'+
'}';
function initGL(canvas) {
try {
gl = canvas.getContext("webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}
function initShaders() {
var fragmentShader = getShader(fragShaderCode, gl.FRAGMENT_SHADER);
var vertexShader = getShader(vertShaderCode, gl.VERTEX_SHADER);
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");
}
}
function initBuffers() {
triangleVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
positionAttribLocation = gl.getAttribLocation(shaderProgram, "vertPosition");
colorAttribLocation = gl.getAttribLocation(shaderProgram, "vertColor");
gl.vertexAttribPointer(
positionAttribLocation, // attribute location
2, //number of elements per attribute
gl.FLOAT, // type of element
gl.FALSE,
5 * Float32Array.BYTES_PER_ELEMENT,//size of induvidual vertex
0//offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
colorAttribLocation,
3,
gl.FLOAT,
gl.FALSE,
5 * Float32Array.BYTES_PER_ELEMENT,
2 * Float32Array.BYTES_PER_ELEMENT
);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0/*verts to skip*/, 3/*verts to draw*/);
}
function getShader(code, type){
var shader = gl.createShader(type);
gl.shaderSource(shader, code);
gl.compileShader(shader);
return shader;
}
this.start = function(spritesCompiledDone, scriptsCompiledDone, roomsCompiledDone, customObjectsCompiledDone, soundsCompiledDone, currentIdGen){
document.body.style.cursor = "auto";
var canvas = document.createElement("canvas");
canvas.width = 640;
canvas.height = 480;
canvas.style.position = "fixed";
canvas.style.top = "0px";
canvas.style.left = "0px";
document.body.appendChild(canvas);
initGL(canvas);
initShaders();
initBuffers();
gl.useProgram(shaderProgram);
gl.clearColor(0.2, 0.1, 0.7, 1.0);
drawScene();
}
It looks like I have done all the steps to get the attribute locations and pointers but it doesn't work. I don't understand how no VBO can be bound as I use gl.bindBuffer which should still be active in the draw phase.
You should change the following things:
function initBuffers() {
triangleVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
positionAttribLocation = gl.getAttribLocation(shaderProgram, "vertPosition");
colorAttribLocation = gl.getAttribLocation(shaderProgram, "vertColor");
gl.vertexAttribPointer(
positionAttribLocation, // attribute location
2, //number of elements per attribute
gl.FLOAT, // type of element
gl.FALSE, // to => false,
5 * Float32Array.BYTES_PER_ELEMENT,//size of induvidual vertex
0//offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
colorAttribLocation,
3,
gl.Float, //to => gl.FLOAT,
gl.False, //to => false,
5 * Float32Array.BYTES_PER_ELEMENT,
5 * Float32Array.BYTES_PER_ELEMENT //to => 2 * Float32Array.BYTES_PER_ELEMENT
);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
}
Previously had a color vertex for rendering this small square, now i want to use an image. Im using an image sprite i had lying around that sits at 64x128 wide.
I'm not getting any errors, but nothing is showing up either. First the shaders:
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec2 vTextureCoord;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
For the buffers:
initBuffers: function () {
this.planePositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.planePositionBuffer);
var vertices = [
1.0, 1.0, 0.0,
-1.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);
this.planePositionBuffer.itemSize = 3;
this.planePositionBuffer.numItems = 4;
this.textureBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
var textureCoords = [
0.0, 1.0,
0.0, 0.0,
1.0, 1.0,
1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
this.textureBuffer.itemSize = 2;
this.textureBuffer.numItems = 4;
}
Initializing the shaders:
initShaders: function () {
this.shader = new Shader("shader");
var shaderProgram = this.shader.shaderProgram;
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
}
And the draw call.
draw: function () {
this.resize();
var delta = this.getDeltaTime();
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.identity(this.mvMatrix);
mat4.identity(this.pMatrix);
mat4.perspective(this.pMatrix, 45 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.1, 100.0);
mat4.translate(this.pMatrix, this.pMatrix, [0.0, 0.0, -50.0]);
var shaderProgram = this.shader.shaderProgram;
for (var i = 0; i < this.objects.length; i++) {
this.objects[i].update(delta, this.mvMatrix);
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.planePositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.planePositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, this.textureBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, me.loader.getImage('test'));
gl.uniform1i(shaderProgram.samplerUniform, 0);
this.setMatrixUniforms();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.planePositionBuffer.numItems);
requestAnimationFrame(this.draw.bind(this));
},
I based the texture coords off of an article i found on opengles drawing on android. The idea was the coords should be in order of bottom left -> top left -> bottom right -> top right.
Full source code for its broken state can be found here in addition to the snippets above: https://github.com/agmcleod/webgl-2dexperiment/tree/13f31f70037fdd4515c1336423337a1e82ab4e89
Looks as if the WebGL code was all correct. However, I was never invoking the function bindAllTextures to actually set up the texture with webgl for rendering.
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.