Glsl 绑定多个统一缓冲区对象
使用WebGL 2,我们现在可以使用统一缓冲区对象 它们看起来是一个不错的主意,不必为每个程序都附加通用的制服(比如投影矩阵和视图矩阵,它们对渲染的每个对象都是通用的) 我创建了一个助手类,每当我想绑定一个统一的缓冲区对象时,我都会调用它Glsl 绑定多个统一缓冲区对象,glsl,webgl2,Glsl,Webgl2,使用WebGL 2,我们现在可以使用统一缓冲区对象 它们看起来是一个不错的主意,不必为每个程序都附加通用的制服(比如投影矩阵和视图矩阵,它们对渲染的每个对象都是通用的) 我创建了一个助手类,每当我想绑定一个统一的缓冲区对象时,我都会调用它 class UniformBuffer { constructor(gl, data, boundLocation = 0) { this.boundLocation = boundLocation; this.dat
class UniformBuffer {
constructor(gl, data, boundLocation = 0) {
this.boundLocation = boundLocation;
this.data = new Float32Array(data);
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
update(gl, data, offset = 0) {
this.data.set(data, offset);
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
};
这样创建统一缓冲区的想法
const perScene = new UniformBuffer(gl, [
...vec4.create(),
...vec4.create(),
], 0); // and bind it to bind location 0?
const perObject = new UniformBuffer(gl, [
...vec4.create(),
], 1); // and bind it to bind location 1?
for (let i = 0; i < objects.length; i++) {
perObject.update(gl, [
...vec4.fromValues(0, 0, 1, 1),
]);
}
在渲染循环中,然后通过调用
perScene.update(gl, [
...vec4.fromValues(1, 0, 0, 1),
], 4); // giving an offset to update only the 2nd color.
然后我将查看场景中的所有对象,我的想法是像这样更新perObject统一缓冲区
const perScene = new UniformBuffer(gl, [
...vec4.create(),
...vec4.create(),
], 0); // and bind it to bind location 0?
const perObject = new UniformBuffer(gl, [
...vec4.create(),
], 1); // and bind it to bind location 1?
for (let i = 0; i < objects.length; i++) {
perObject.update(gl, [
...vec4.fromValues(0, 0, 1, 1),
]);
}
我这里有一个工作片段
class UniformBuffer{
构造函数(总帐,数据,边界位置=0){
this.boundLocation=boundLocation;
this.data=新的Float32Array(数据);
this.buffer=gl.createBuffer();
gl.bindBuffer(gl.UNIFORM\u BUFFER,this.BUFFER);
总账缓冲区数据(总账统一缓冲区、本数据、总账动态绘图);
gl.bindBuffer(gl.UNIFORM\u BUFFER,null);
gl.bindBufferBase(gl.UNIFORM\u BUFFER,this.boundLocation,this.BUFFER);
}
更新(总账、数据、偏移=0){
此.data.set(数据,偏移量);
gl.bindBuffer(gl.UNIFORM\u BUFFER,this.BUFFER);
gl.bufferSubData(gl.UNIFORM_BUFFER,0,this.data,0,null);
gl.bindBuffer(gl.UNIFORM\u BUFFER,null);
gl.bindBufferBase(gl.UNIFORM\u BUFFER,this.boundLocation,this.BUFFER);
}
};
常量顶点=`#版本300 es
均匀渗层{
vec4-1;
vec4-2;
};
均匀排列模型{
vec4-3;
};
在vec3 a_位置;
输出vec3v_颜色;
void main(){
gl_位置=vec4(a_位置,1.0);
v_color=color1.rgb+color2.rgb;//有效
//v_color=color1.rgb+color2.rgb+color3.rgb;//不起作用
}
`;
常量片段=`#版本300 es
高精度浮点;
精度高;
在vec3 v_颜色中;
外显vec4外显色;
void main(){
outColor=vec4(v_color,1.0);
}
`;
常数几何={
位置:[-0.5,-0.5,0,-0.5,0.5,0,0.5,-0.5,0,0.5,0],
指数:[0,2,1,1,2,3],
};
常量renderList=[];
//步骤1(创建画布)
var canvas=document.getElementById(“canvas”);
var gl=canvas.getContext(“webgl2”);
如果(!gl){
log(“没有webgl2好友”);
}
//步骤2(创建程序)
常量v=gl.createShader(gl.VERTEX_着色器);
gl.shaderSource(v,顶点);
总帐编辑主任(五);
常量f=gl.createShader(gl.FRAGMENT\u着色器);
gl.shaderSource(f,片段);
总帐编辑主任(f);
const program=gl.createProgram();
德国劳埃德船级社附件(程序,v);
德国劳埃德船级社附件(程序,f);
总账链接程序(程序);
//步骤3(创建VAO)
const positionAttributeLocation=gl.getAttributeLocation(程序“a_位置”);
const colorUniformLocation=gl.getUniformLocation(程序“颜色”);
const positionsBuffer=gl.createBuffer();
const indicatesbuffer=gl.createBuffer();
const vao=gl.createVertexArray();
bindVertexArray总帐(vao);
//位置和索引
gl.EnableVertexAttributeArray(位置属性位置);
gl.bindBuffer(gl.ARRAY_BUFFER,positionsBuffer);
gl.bufferData(gl.ARRAY\u BUFFER、新Float32Array(geometry.positions)、gl.STATIC\u DRAW);
gl.VertexAttributePointer(位置属性位置,3,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY\u BUFFER,null);
gl.bindBuffer(gl.ELEMENT\u ARRAY\u BUFFER,indicatesbuffer);
gl.bufferData(gl.ELEMENT\u ARRAY\u BUFFER、新UINT16阵列(几何体索引)、gl.STATIC\u DRAW);
//步骤4(创建UBO)
//已绑定到位置0
const perScene=新的UniformBuffer(gl[
…vec4.create(),//颜色1
…vec4.create(),//颜色2
], 0);
//绑定到位置1?
const perModel=新的UniformBuffer(gl[
…vec4.create(),//颜色3
], 3);
//步骤5(添加实例)
for(设i=0;i<1;i++){
renderList.push({
id:我,
vao:vao,
节目:节目,,
颜色:[0,1,1],
});
}
//第6步(抽签)
gl.clearColor(0,0,0,0);
总帐启用(总帐深度测试);
总图视口(0,0,canvas.width,canvas.height);
perScene.更新(德国劳埃德船级社[
…vec4.fromValues(1,0,0,1),
…vec4.fromValues(0,1,0,1),
]);
for(设i=0;i
画布{
背景色:黑色;
}
因此,您做错的第一件事就是没有调用gl.getUniformBlockIndex
。就像uniform一样,您必须查询每个块的位置或索引
第二件事是块统一是间接的一级,您需要调用gl.uniformBlockBinding(program,uniformblockdex,uniformBufferIndex)
uniformblockdex
是从gl.getuniformblockdex
获得的索引<代码>uniformBufferIndex
类似于纹理单元。存在N个统一的缓冲区索引。您可以从0
到MAX\u UNIFORM\u buffer\u BINDINGS-1
选择任何缓冲区索引
如果您有一个程序使用块A、B,另一个程序使用块A和C,则此间接寻址会有所帮助。在这种情况下,块A可能在两个程序中具有不同的索引,但您让它从相同的uniformBufferIndex中提取其值
请注意,此状态为每个程序状态,因此,如果您计划对同一统一块始终使用相同的统一缓冲区索引,则可以在初始化时设置它
把它说得更清楚。你有一个着色器程序。它有状态
var someProgram = {
uniforms: {
projectionMatrix: [1, 0, 0, 0, 0, ... ], // etc
},
uniformBlockIndcies[ // one per uniform block
0,
0,
0,
],
...
}
接下来是全局状态的统一缓冲区索引
glState = {
textureUnits: [ ... ],
uniformBuffers: [ null, null, null ..., ],
};
告诉程序每个统一缓冲区块使用哪个统一缓冲区索引与gl.uniformBlockBinding
。然后使用gl.bindBufferBase
或gl.bind将缓冲区绑定到该索引