webgl如何绘制许多立方体
webgl how to draw many cubes
我正在尝试使用webGL绘制5161个立方体。问题是并不是所有的立方体都画出来了。经过一些搜索,我认为这是因为我在一个VBO调用中传递了太多顶点。您可以在这里查看jsfiddle:http://jsfiddle.net/n5fjhe21/.您可以使用QWERASDF和箭头键四处移动,但目前还没有很好地实现。
我的抽奖电话过去是这样的:
function render(){
gl.uniformMatrix4fv(u_matrixLoc, false, new Float32Array(pMatrix));
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, data.triangles.length, gl.UNSIGNED_SHORT, 0);
}
所以我会做一次data.pushData(),然后根据需要进行渲染;速度很快。glObject是一个立方体数组。
data.pushData = function(){
// pushData once then call drawElements on every render call doesnt work as I hit some kind of limit;
// not all cubes are drawn; I think the draw calls must be split up;
data.vertices = [];
data.uv = [];
data.triangles = [];
var vertexOffset = 0;
glObjects.forEach(function pushingObject(o){
data.vertices.push.apply(data.vertices,o.vertices);
data.uv.push.apply(data.uv,o.uv);
o.triangles.forEach(function pushingTriangles(index){
data.triangles.push(index+vertexOffset);
});
vertexOffset += o.vertices.length/3; // change to component length later
});
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.vertices),gl.DYNAMIC_DRAW );
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.uv),gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.triangles), gl.DYNAMIC_DRAW );
};
但问题(我认为)是我一次传递了太多的顶点。所以我尝试将pushData和render合并在一起:
data.render = function(){
data.vertices = [];
data.uv = [];
data.triangles = [];
var vertexOffset = 0;
glObjects.forEach(function pushingObject(o){
if (vertexOffset + o.vertices.length > 65536){
vertexOffset = 0;
glDraw();
data.vertices.length = 0;
data.uv.length = 0;
data.triangles.length = 0;
}
data.vertices.push.apply(data.vertices,o.vertices);
data.uv.push.apply(data.uv,o.uv);
o.triangles.forEach(function pushingTriangles(index){
data.triangles.push(index+vertexOffset);
});
vertexOffset += o.vertices.length/3; // change to component length later
});
glDraw();
function glDraw(){
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.vertices),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.uv),gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.triangles), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, data.triangles.length, gl.UNSIGNED_SHORT, 0);
}
};
但这还不够快,因为正如我所了解到的,传递新的bufferData很慢。所以我的问题是,在这种情况下该怎么办?我无法找到任何处理此问题的webgl资源。我的感觉倾向于创建多个VBO对象,但我想首先确保我的方向是正确的。作为一个后续问题,假设如果需要绘制许多具有唯一位置(x,y,z)和方向(rX,rY,rZ)的立方体,如何实现它?提前谢谢。
好的,我解决了我的问题,我把这个留给掉队者:
基本上,我的想法是正确的,因为每个索引绘图(drawElements)只能引用VBO中的2^16个元素,所以我需要使用多个绘图调用。我的第一个实现中的缺陷是,我实际上试图在每次渲染调用中重建一个由多个立方体顶点组成的新的大型数组。不用说,这是非常缓慢的。因此,我实际上应该只创建一次typedArray/buffer。为了克服2^16元素引用的限制,我所要做的就是将一个大类型的数组分离成可管理的大小,这正是这个新版本的pushData所做的:
data.pushData = function(){
// ensure each vertex attribute has less than 2^16 vertices because that is how many that be be referenced each time
// with gl.drawElements call
function newChunk(){
return {
vertices: [],
uv: [],
triangles: []
}
}
var chunk = newChunk();
var vertexOffset = 0;
glObjects.forEach(function pushingVerts(o){
if (vertexOffset + o.vertices.length > 65536){
vertexOffset = 0;
data.chunks.push(chunk);
chunk = newChunk();
}
chunk.vertices.push.apply(chunk.vertices,o.vertices);
chunk.uv.push.apply(chunk.uv,o.uv);
o.triangles.forEach(function pushingTriangles(index){
chunk.triangles.push(index+vertexOffset);
});
vertexOffset += o.vertices.length/3; // change to component length later
});
data.chunks.push(chunk);
data.chunks.forEach(function toTypeArray(c){
c.vertices = new Float32Array(c.vertices);
c.uv = new Float32Array(c.uv);
c.triangles = new Uint16Array(c.triangles);
});
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizeofFloat * 65536*3,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizeofFloat * 65536*2,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sizeofFloat * 65536, gl.DYNAMIC_DRAW);
// for some reason only allocating sizeofUnsignedShort * 65536 is not enough.
return data.chunks;
};
然后简单地渲染:
data.renderChunks = function(){
data.chunks.forEach(function renderChunk(c){
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, c.vertices);
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, c.uv);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer);
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, c.triangles);
gl.drawElements(gl.TRIANGLES, c.triangles.length, gl.UNSIGNED_SHORT, 0);
});
};
此外,为了避免构建新缓冲区的开销,我从使用gl.bufferData改为使用gl.bbufferSubData。
有了这个,我现在可以画60000个立方体(至少):http://jsfiddle.net/n5fjhe21/1/
- 为什么在许多浏览器中drawImage()的性能略好于createPattern()
- 在Nodejs中为许多用户处理计时器
- 当有许多形式时,Fancybox脚本不起作用
- 如何动态创建许多Jquery颜色选择器(eyecon)
- 我如何编程许多不同的条件和操作
- html画布中的等轴测立方体投影
- 它是否创建了许多不利于JavaScript性能的变量
- 使用Jquery从页面上的许多重复类中获取特定元素
- jQuery无限循环,动画化许多项目
- 从Three.js场景中删除许多对象的速度较慢
- JavaScript检查某些文本中的许多关键字
- AJAX请求许多链接
- Selenium如何批处理许多isElementDisplayed调用
- 如果有许多元素使用相同的类,我如何使用JavaScript获取特定的元素
- getDataAsJSON()在PHP中是一个未定义的函数,但许多解释如何使用JSONP的网站都说要使用它
- 饼干.JS如何记住许多变化
- 如何使用 jQuery 触发对包含许多列表项的列表的单击
- 在 Angular 中对许多相同的表进行排序
- 使用镶边立方体浏览器
- webgl如何绘制许多立方体