简体   繁体   English

WebGL; 缓冲区还是uniform4fv?

[英]WebGL; Buffer or uniform4fv?

I'm currently learning WebGL and I'm in the progress of rendering a scene with a LOT of identical cubes, but with different translates. 我目前正在学习WebGL,并且正在使用很多相同的立方体但使用不同的转换渲染场景。

I believe I have 2 options in regards to drawing these; 我相信我有2种选择可以选择这些选项;

  • Buffer a single cube, use a uniform4fv for translate and resend it for each cube (to the vertex shader). 缓冲单个多维数据集,使用uniform4fv进行转换,然后为每个多维数据集将其重新发送到顶点着色器。

  • Buffer up all my cubes (vertices hardcoded with translate). 缓冲所有我的多维数据集(使用translate硬编码的顶点)。

My question is in regards to which option is preferable in which cases? 我的问题是在哪种情况下哪种选择更可取? - I'd think the first option was preferable, but that depends on the overhead or updating the uniform variable. -我认为第一种选择更可取,但这取决于开销或更新统一变量。

First of all it depends on whether the objects you are rendering is dynamic or static. 首先,这取决于您要渲染的对象是动态还是静态。

For static geometry, method 2 will be more efficient. 对于静态几何,方法2将更有效。

For dynamic geometry, it depends. 对于动态几何,这取决于。 The trade off is between the overhead of state change with method 1 versus the cost of calculating the new vertices on CPU + uploading those vertices to GPU every frame with method 2. It is difficult to quantify the exact cost of state change, but, it is certain that larger objects takes longer to calculate and update to the GPU. 需要权衡的是方法1的状态更改的开销与在CPU上计算新顶点的成本+用方法2的每帧将这些顶点上载到GPU的成本之间的平衡。很难量化状态更改的确切成本,但是,可以确定较大的对象需要更长的时间才能计算并更新到GPU。

From experience, method 2 works better with "smallish" objects such as sprites, boxes etc and method 1 works better with "complex" objects that have thousands+ of vertices. 根据经验,方法2适用于“较小”的对象(如精灵,盒子等),方法1适用于具有数千个以上顶点的“复杂”对象。 What exactly quantify as "smallish" or "complex" is probably gpu and driver dependent and you have to test on an individual basis. 确切地量化为“较小”或“复杂”的内容可能取决于gpu和驱动程序,因此您必须逐个进行测试。

drawElements is almost always preferred over drawArrays whenever possible. drawElements总是使用drawElements而不是drawArrays

As WaclawJasper said there's lots of tradeoffs. 正如WaclawJasper所说,有很多折衷方案。

The general way to do things in WebGL is one draw call per object (your first method). 在WebGL中执行操作的一般方法是每个对象一个绘画调用(您的第一个方法)。

Another would be to use instanced drawing using ANGLE_instanced_arrays . 另一种方法是使用ANGLE_instanced_arrays实例化绘图。 In that method your translations would be stored in a buffer. 在这种方法中,您的翻译将存储在缓冲区中。 You'd update the buffer only one translation per instance (vs one per vertex in your second method). 您只需为每个实例更新一次缓冲区翻译(与第二种方法中的每个顶点更新)。 That method assumes all instances are the same. 该方法假定所有实例都是相同的。

If your geometry happened to be mixed (cube + sphere + pyramid) yet another method would be to put your orientation data in a texture. 如果您的几何体恰好混合在一起(立方体+球体+金字塔),另一种方法是将方向数据放入纹理中。 By giving each vertex an instanceId you can use that to compute the location of that instance's data in the texture. 通过为每个顶点指定一个instanceId,您可以使用它来计算实例数据在纹理中的位置。 In this case you'd be updating one orientation per instance like the previous method. 在这种情况下,您将像以前的方法一样为每个实例更新一个方向。 It's just you'd be updating a texture instead of a buffer. 只是您要更新纹理而不是缓冲区。 If the hardware supports reading from floating point textures ( OES_texture_float ) which AFAICT most hardware does at this point, this method is pretty easy. 如果硬件支持此时浮点纹理( OES_texture_float )的读取,则AFAICT大多数硬件都可以做到这一点,这种方法非常简单。

As an example of storing orientation in a texture three.js optionally stores bone matrices in textures for skinned mesh rendering to get around a limited number of uniforms. 作为在纹理中存储方向的示例,Three.js可选地在纹理中存储骨骼矩阵以进行蒙皮网格渲染,以避开有限数量的制服。

note that using textures you could also put the vertex data in a texture. 请注意,使用纹理还可以将顶点数据放入纹理中。 The buffers would then just contain vertex indices. 然后,缓冲区将仅包含顶点索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM