从野外看一些不同的示例,似乎将数据上传到缓冲区(用作统一缓冲区)的过程如下:
第3步的目的是什么?
答案 0 :(得分:0)
您不需要按此顺序进行。
最简单的例子:
'use strict';
const vs = `#version 300 es
void main() {
gl_PointSize = 128.0;
gl_Position = vec4(0, 0, 0, 1);
}
`;
const fs = `#version 300 es
precision mediump float;
uniform Color {
vec4 u_color;
};
out vec4 outColor;
void main() {
outColor = u_color;
}
`;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need webgl2');
const program = twgl.createProgram(gl, [vs, fs]);
const color = new Float32Array([1, 0.5, 0.7, 1]);
const buffer = gl.createBuffer();
// there's only 1 so I believe it's safe to guess index 0
const uniformBlockIndex = 0;
const uniformBlockBinding = 0;
gl.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
// at render time
gl.useProgram(program);
// for each block
{
const uniformBlockBufferOffset = 0;
const uniformBlockBufferOffsetByteLength = 16; // 4 floats
gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding, buffer, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);
// set the data
gl.bufferData(gl.UNIFORM_BUFFER, color, gl.DYNAMIC_DRAW);
}
gl.drawArrays(gl.POINTS, 0, 1);
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
如果您想查看一个复杂的示例,可以深入研究this example。创建程序时,它将查询有关统一缓冲区的所有数据。有多少人,他们的名字是什么,他们使用哪些制服,这些制服的类型是什么。当您致电look inside并看到createUniformBlockSpecFromProgram
中的信息已创建时,便会发生这种情况
然后,您可以使用块规范,通过调用twgl.createUniformBlockInfo
twgl.createProgramInfo
您可以直接使用视图通过视图在typedarray中设置统一值
const ubi = twgl.createUniformBlockInfo(...)
但这会很脆弱,因为在调试时可能会优化块,因此您可以使用不那么脆弱的
ubi.uniforms.nameOfUniform.set(newValue)
当您实际上希望将typedarray中的数据上传到您调用的GPU时
twgl.setBlockUniforms(ubi, {nameOfUniform: newValue});
既将统一块绑定到其分配的绑定,又将数据上传到GPU。
如果您只想绑定现有块(无需上传新数据),则
twgl.setUniformBlock(...);
虽然模式如您在示例中所见
bindBufferRange已经绑定了缓冲区,因此我们可以使用该绑定来上传数据。
测试(非twgl)
twgl.bindUniformBlock(gl, programInfo, ubi);
'use strict';
const vs = `#version 300 es
void main() {
gl_PointSize = 128.0;
gl_Position = vec4(0, 0, 0, 1);
}
`;
const fs = `#version 300 es
precision mediump float;
uniform Color1 {
vec4 u_color1;
};
uniform Color2 {
vec4 u_color2;
};
out vec4 outColor;
void main() {
outColor = u_color1 + u_color2;
}
`;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need webgl2');
const program = twgl.createProgram(gl, [vs, fs]);
const color1 = new Float32Array([1, 0, 0, 1]);
const buffer1 = gl.createBuffer();
const color2 = new Float32Array([0, 0, 1, 1]);
const buffer2 = gl.createBuffer();
// there's only 2 and they are the same format so we don't really
// care which is which to see the results.
const uniformBlockIndex = 0;
const uniformBlockBinding = 0;
gl.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
gl.uniformBlockBinding(program, uniformBlockIndex + 1, uniformBlockBinding + 1);
// at render time
gl.useProgram(program);
{
const uniformBlockBufferOffset = 0;
const uniformBlockBufferOffsetByteLength = 16; // 4 floats
gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding, buffer1, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);
// set the data
gl.bufferData(gl.UNIFORM_BUFFER, color1, gl.DYNAMIC_DRAW);
gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding + 1, buffer2, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);
// set the data
gl.bufferData(gl.UNIFORM_BUFFER, color2, gl.DYNAMIC_DRAW);
}
gl.drawArrays(gl.POINTS, 0, 1);
上面的示例显示<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
做2件事。
bindBufferRange
绑定点我们知道它有用,因为结果是紫色。如果不起作用,它将是红色或蓝色
根据OpenGL ES 3.0规范第2.10.1.1节中关于UNIFORM_BUFFER
每个目标也代表缓冲对象绑定点的索引数组, 作为单个通用绑定点,可被其他缓冲区对象操作功能使用