6lackrules
6lackrules

Reputation: 25

How to use separate buffers for different attributes

I'm learning WebGL and stuck in understanding how to pass data to attributes.

drawArrays: no buffer is bound to enabled attribute this is a warning that I get, but if I disable one vertexAttrib

gl.disableVertexAttribArray(positionAttributeLocation)

, this warning disappears, but I still don't have anything on a screen.

What am I doing wrong?

This is my shaders.

const vsSource = `
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;

void main() {
  gl_Position = a_position;
  v_color = a_color;
}
`;

const fsSource = `
precision mediump float;
varying vec4 v_color;

void main() {
  gl_FragColor = v_color;
}
`;

Next my steps: 1) get gl context

const canvas = document.querySelector('#glCanvas'); 
gl = canvas.getContext('webgl');

2) create shaders

function createShader(type, source) {
  var shader = gl.createShader(type);   // create shader
  gl.shaderSource(shader, source);      // set to shader his code
  gl.compileShader(shader);             // compile shader
  var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if (success) {
    return shader;
  }

  console.log(gl.getShaderInfoLog(shader));
  gl.deleteShader(shader);
}
  const vShader = createShader(gl.VERTEX_SHADER, vsSource)
  const fShader = createShader(gl.FRAGMENT_SHADER, fsSource)

3) Create a program and attach shaders, link them

var program = gl.createProgram();
  checkGlError()
  gl.attachShader(program, vShader); 
  gl.attachShader(program, fShader);
  gl.linkProgram(program); 

  if ( !gl.getProgramParameter(program, gl.LINK_STATUS) ) {
    var info = gl.getProgramInfoLog(program);
    throw 'Could not compile WebGL program. \n\n' + info;
  }

4) Get references to attributes

var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
  var colorAttributeLocation = gl.getAttribLocation(program, "a_color");

5) create buffers and bind data

  var positionBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
  setRectangle(gl)

  var colorBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
  setColors(gl)

function setRectangle(gl) {
  let x = randomFloat()
  let y = randomFloat()
  let width = randomFloat()
  let height = randomFloat()

  let x1 = x;
  let x2 = x + width;
  let y1 = y;
  let y2 = y + height;

  let positions = [
    x1, y1,
    x2, y1,
    x1, y2,
    x1, y2,
    x2, y1,
    x2, y2
  ]
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW)
}
function setColors(gl) {
  var r1 = Math.random();
  var b1 = Math.random();
  var g1 = Math.random();

  var r2 = Math.random();
  var b2 = Math.random();
  var g2 = Math.random();

  gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array(
        [ r1, b1, g1, 1,
          r1, b1, g1, 1,
          r1, b1, g1, 1,
          r2, b2, g2, 1,
          r2, b2, g2, 1,
          r2, b2, g2, 1]),
      gl.STATIC_DRAW);
}

6) Draw scene

  gl.viewport(0,0,gl.canvas.width,gl.canvas.height)

  gl.clearColor(78/255.0,159/255.0,255/255.0,1.0)
  gl.clear(gl.COLOR_BUFFER_BIT)

  gl.useProgram(program)

  gl.enableVertexAttribArray(positionAttributeLocation)

  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)

  var size = 2
  var type = gl.FLOAT
  var normalize = false
  var stride = 0
  var offset = 0

  gl.vertexAttribPointer(
    positionBuffer,
    size,
    type,
    normalize,
    stride,
    offset)

    gl.enableVertexAttribArray(colorAttributeLocation)
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)

    var size = 4
    var type = gl.FLOAT
    var normalize = false
    var stride = 0
    var offset = 0

    gl.vertexAttribPointer(
      colorBuffer,
      size,
      type,
      normalize,
      stride,
      offset)


    let verticiesCounter = 6;
    var drawingOffset = 0;

    gl.drawArrays(gl.TRIANGLES, drawingOffset , verticiesCounter)

Upvotes: 2

Views: 841

Answers (1)

Rabbid76
Rabbid76

Reputation: 210908

The first parameter of vertexAttribPointer has to be the index of the generic vertex attribute and not a buffer object.
Note, vertexAttribPointer specifies the data for a generic vertex attribute, so the index has to be specified somewhere. If a named buffer object is bound to the target ARRAY_BUFFER, then the data in this buffer are the data source.

See OpenGL ES glVertexAttribPointer and WebGL Specification; 5.13.10 Uniforms and attributes

This means you have to change your code like this:

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
gl.vertexAttribPointer(
    positionAttributeLocation, // instead of positionBuffer
    size,
    type,
    normalize,
    stride,
    offset)

.....

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
gl.vertexAttribPointer(
    colorAttributeLocation, // instead of colorBuffer
    size,
    type,
    normalize,
    stride,
    offset)

Upvotes: 2

Related Questions