如何为不同的属性使用单独的缓冲区

时间:2018-03-17 16:24:08

标签: javascript webgl

我正在学习WebGL并坚持理解如何将数据传递给属性。

  

drawArrays:没有缓冲区绑定到enabled属性   这是我得到的警告,但如果我禁用了一个vertexAttrib

gl.disableVertexAttribArray(positionAttributeLocation)

,此警告消失,但屏幕上仍然没有任何内容。

我做错了什么?

这是我的着色器。

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;
}
`;

接下来我的步骤: 1)获得gl上下文

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

2)创建着色器

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)创建一个程序并附加着色器,将它们链接

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)获取对属性的引用

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

5)创建缓冲区并绑定数据

  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)绘制场景

  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)

1 个答案:

答案 0 :(得分:1)

vertexAttribPointer的第一个参数必须是通用顶点属性的索引,而不是缓冲区对象。
注意,vertexAttribPointer指定通用顶点属性的数据,因此必须在某处指定索引。 如果命名缓冲区对象绑定到目标ARRAY_BUFFER,则此缓冲区中的数据是数据源。

请参阅OpenGL ES glVertexAttribPointerWebGL Specification; 5.13.10 Uniforms and attributes

这意味着您必须像这样更改代码:

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)