What is the correct sequence for uploading a uniform block?

不问归期 提交于 2021-01-27 11:59:09

问题


In the example page at https://www.lighthouse3d.com/tutorials/glsl-tutorial/uniform-blocks/ has this:

  1. uniformBlockBinding()
  2. bindBuffer()
  3. bufferData()
  4. bindBufferBase()

But conceptually, wouldn't this be more correct?

  1. bindBuffer()
  2. bufferData()
  3. uniformBlockBinding()
  4. bindBufferBase()

The idea being that uploading to a buffer (bindBuffer+bufferData) should be agnostic about what the buffer will be used for - and then, separately, uniformBlockBinding()+bindBufferBase() would be used to update those uniforms, per shader, when the relevant buffer has changed?


回答1:


Adding answer since the accepted answer has lots of info irrelevant to WebGL2

At init time you call uniformBlockBinding. For the given program it sets up which uniform buffer index bind point that particular program will get a particular uniform buffer from.

At render time you call bindBufferRange or bindBufferBase to bind a specific buffer to a specific uniform buffer index bind point

If you also need to upload new data to that buffer you can then call bufferData

In pseudo code

// at init time

for each uniform block
   gl.uniformBlockBinding(program, indexOfBlock, indexOfBindPoint)

// at render time

for each uniform block
   gl.bindBufferRange(gl.UNIFORM_BUFFER, indexOfBindPoint, buffer, offset, size)
   if (need to update data in buffer)
      gl.bufferData/gl.bufferSubData(gl.UNIFORM_BUFFER, data, ...)

Note that there is no “correct” sequence. The issue here is that how you update your buffers is really up to you. Since you might store multiple uniform buffer datas in a single buffer at different offsets then calling gl.bufferData/gl.bufferSubData like above is really not “correct”, it’s just one way of 100s.

WebGL2 (GLES 3.0 ES) does not support the layout(binding = x) mentioned in the accepted answer. There is also no such thing as glGenBuffers in WebGL2




回答2:


Neither is "more correct" than the other; they all work. But if you're talking about separation of concerns, the first one better emphasizes correct separation.

glUniformBlockBinding modifies the program; it doesn't affect the nature of the buffer object or context buffer state. Indeed, by all rights, that call shouldn't even be in the same function; it's part of program object setup. In a modern GL tutorial, they would use layout(binding=X) to set the binding, so the function wouldn't even appear. For older code, it should be set to a known, constant value after creating the program and then left alone.

So calling the function between allocating storage for the buffer and binding it to an indexed bind point for use creates the impression that they should be calling glUniformBlockBinding every frame, which is the wrong impression.

And speaking of wrong impressions, glBindBufferBase shouldn't even be called there. The rest of that code is buffer setup code; it should only be done once, at the beginning of the application. glBindBufferBase should be called as part of the rendering process, not the setup process. In a good application, that call shouldn't be anywhere near the glGenBuffers call.



来源:https://stackoverflow.com/questions/56760912/what-is-the-correct-sequence-for-uploading-a-uniform-block

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!