为什么 WebGL 实例扩展只绘制一个三角形而不是两个? [英] Why is the WebGL instancing extension only drawing one triangle instead of two?

查看:28
本文介绍了为什么 WebGL 实例扩展只绘制一个三角形而不是两个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用基于 本指南的 WebGL 实例化

I'm trying to use instancing with WebGL based on this guide. I've tried to create a simple example that draws a red triangle on the left and a blue triangle on the right. When I run it, it draws a blue triangle on the left and I don't understand why.

我已经尝试将参数更改为 drawArraysInstancedANGLE 但这无济于事.我尝试更改绑定缓冲区的行顺序和设置属性指针等.我做错了什么?谢谢

I've tried changing the arguments to drawArraysInstancedANGLE but that doesn't help. I've tried changing the order of lines for binding buffers and setting attribute pointers, etc. What am I doing wrong? Thanks

const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
const ext = gl.getExtension("ANGLE_instanced_arrays");
const vert = gl.createShader(gl.VERTEX_SHADER);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
const program = gl.createProgram();

gl.shaderSource(vert, `
  attribute vec4 a_position;
  attribute vec4 a_color;
  varying vec4 v_color;

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

gl.shaderSource(frag, `
  precision mediump float;
  varying vec4 v_color;

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

gl.compileShader(vert);
gl.compileShader(frag);
gl.attachShader(program, vert);
gl.attachShader(program, frag);
gl.linkProgram(program);

const a_position = gl.getAttribLocation(program, "a_position");
const buffer1 = gl.createBuffer();
const positions = [-0.5, 0, -0.5, 0.2, -0.3, 0, 0.5, 0, 0.5, 0.2, 0.3, 0];
gl.bindBuffer(gl.ARRAY_BUFFER, buffer1);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

const a_color = gl.getAttribLocation(program, "a_color");
const buffer2 = gl.createBuffer();
const colors = [1, 0, 0, 1, 0, 0, 1, 1];
gl.bindBuffer(gl.ARRAY_BUFFER, buffer2);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

gl.viewport(0, 0, 300, 300);
gl.useProgram(program);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer1);
gl.enableVertexAttribArray(a_position);
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer2);
gl.enableVertexAttribArray(a_color);
gl.vertexAttribPointer(a_color, 4, gl.FLOAT, false, 0, 0);
ext.vertexAttribDivisorANGLE(a_color, 1);

ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 3, 2);

<canvas id="canvas" width="300" height="300"></canvas>

推荐答案

所以我看到你大部分已经在评论中得到了答案.

So I see you mostly already got an answer in the comments.

代码绘制了第一个三角形两次,一次是红色,一次是蓝色.

The code is drawing the first triangle twice, once in red, then once in blue.

但是,...你提到索引一个统一的数组.那将是不寻常的

But, ... you mentioned indexing a uniform array. That would be unusual

通常,您会将每个实例的数据放入缓冲区.链接站点上的示例使用了一个矩阵只是为了通用,因为矩阵可以让你做任何数学运算(平移、旋转、缩放、3d 投影等),但作为一个例子,你可以传入单个 x 偏移量.

Normally you'd put per instance data in a buffer. The example on the site linked used a matrix just to be generic since a matrix well will let you do just about any math (translation, rotation, scale, 3d projection, ...) but just as an example, you could just pass in single x offset.

const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
const ext = gl.getExtension("ANGLE_instanced_arrays");
const vert = gl.createShader(gl.VERTEX_SHADER);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
const program = gl.createProgram();

gl.shaderSource(vert, `
  attribute vec4 a_position;
  attribute float a_xoffset;
  attribute vec4 a_color;
  varying vec4 v_color;

  void main() {
    gl_Position = a_position;
    gl_Position.x += a_xoffset;
    v_color = a_color;
  }
`);

gl.shaderSource(frag, `
  precision mediump float;
  varying vec4 v_color;

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

gl.compileShader(vert);
gl.compileShader(frag);
gl.attachShader(program, vert);
gl.attachShader(program, frag);
gl.linkProgram(program);

const a_position = gl.getAttribLocation(program, "a_position");
const buffer1 = gl.createBuffer();
const positions = [-0.5, 0, -0.5, 0.2, -0.3, 0];
gl.bindBuffer(gl.ARRAY_BUFFER, buffer1);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

const a_color = gl.getAttribLocation(program, "a_color");
const buffer2 = gl.createBuffer();
const colors = [1, 0, 0, 1, 0, 0, 1, 1];
gl.bindBuffer(gl.ARRAY_BUFFER, buffer2);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

const a_xoffset = gl.getAttribLocation(program, "a_xoffset");
const buffer3 = gl.createBuffer();
const xoffsets = [0, 1];
gl.bindBuffer(gl.ARRAY_BUFFER, buffer3);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(xoffsets), gl.STATIC_DRAW);

gl.viewport(0, 0, 300, 300);
gl.useProgram(program);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer1);
gl.enableVertexAttribArray(a_position);
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer2);
gl.enableVertexAttribArray(a_color);
gl.vertexAttribPointer(a_color, 4, gl.FLOAT, false, 0, 0);
ext.vertexAttribDivisorANGLE(a_color, 1);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer3);
gl.enableVertexAttribArray(a_xoffset);
gl.vertexAttribPointer(a_xoffset, 1, gl.FLOAT, false, 0, 0);
ext.vertexAttribDivisorANGLE(a_xoffset, 1);

ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 3, 2);

<canvas id="canvas" width="300" height="300"></canvas>

我只是指出这一点,因为缓冲区中有数百万个值,但制服的限制要大得多,因此索引制服以进行实例化并不常见.

I'm just pointing that out because you have millions of values in a buffer but uniforms are far more limited so indexing a uniform for instancing is not common.

如果您确实希望每个实例有不同的数据,那么是的,您必须做其他事情.

If you actually wanted different data per instance then yes you'd have to do something else.

一个例子是这里

这篇关于为什么 WebGL 实例扩展只绘制一个三角形而不是两个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆