Webgl 上传统一块的正确顺序是什么?

Webgl 上传统一块的正确顺序是什么?,webgl,webgl2,Webgl,Webgl2,在的示例页面中,有以下内容: uniformBlockBinding() bindBuffer() 缓冲数据() bindBufferBase() 但从概念上讲,这不是更正确吗 bindBuffer() 缓冲数据() uniformBlockBinding() bindBufferBase() 其想法是,上传到缓冲区(bindBuffer+bufferData)应该不知道缓冲区将用于什么——然后,当相关缓冲区发生变化时,分别使用uniformBlockBinding()+bindBufferBa

在的示例页面中,有以下内容:

  • uniformBlockBinding()
  • bindBuffer()
  • 缓冲数据()
  • bindBufferBase()
  • 但从概念上讲,这不是更正确吗

  • bindBuffer()
  • 缓冲数据()
  • uniformBlockBinding()
  • bindBufferBase()
  • 其想法是,上传到缓冲区(bindBuffer+bufferData)应该不知道缓冲区将用于什么——然后,当相关缓冲区发生变化时,分别使用uniformBlockBinding()+bindBufferBase()更新每个着色器的制服?

    两者都不比另一个“更正确”;他们都工作。但是如果你谈论的是关注点的分离,那么第一个更好地强调正确的分离

    glUniformBlockBinding
    修改程序;它不影响缓冲区对象或上下文缓冲区状态的性质。事实上,根据所有权利,这个调用甚至不应该在同一个函数中;这是程序对象设置的一部分。在现代GL教程中,他们会使用,因此函数甚至不会出现。对于较旧的代码,应在创建程序后将其设置为已知的常量值,然后将其保留

    因此,在为缓冲区分配存储和将其绑定到索引绑定点以供使用之间调用函数会产生这样的印象,即他们应该在每一帧调用
    glUniformBlockBinding
    ,这是错误的印象


    说到错误的印象,
    glBindBufferBase
    甚至不应该在那里调用。该代码的其余部分是缓冲区设置代码;只能在应用程序开始时执行一次
    glBindBufferBase
    应在渲染过程中调用,而不是在设置过程中调用。在一个好的应用程序中,该调用不应该靠近
    glGenBuffers
    调用。

    添加应答,因为接受的应答包含大量与WebGL2无关的信息

    在初始化时调用
    uniformBlockBinding
    。对于给定的程序,它设置特定程序将从哪个统一缓冲区索引绑定点获得特定的统一缓冲区

    在渲染时调用
    bindBufferRange
    bindBufferBase
    将特定缓冲区绑定到特定的统一缓冲区索引绑定点

    如果还需要将新数据上载到该缓冲区,则可以调用
    bufferData

    伪码

    // 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, ...)
    
    请注意,没有“正确”的顺序。这里的问题是,如何更新缓冲区实际上取决于您。由于您可能在一个缓冲区中以不同的偏移量存储多个统一缓冲区数据,因此像上面那样调用
    gl.bufferData/gl.bufferSubData
    实际上是不“正确的”,这只是100秒的一种方式


    WebGL2(GLES 3.0 ES)不支持公认答案中提到的
    布局(binding=x)
    。WebGL2中也没有
    glGenBuffers
    ,谢谢!只有当缓冲区被更新时才需要调用
    bindBufferBase()
    ,对吗?(更新缓冲区需要
    bindBuffer()+bufferData()
    ,但不需要genBuffer(),因为我们只是重复使用一个创建的缓冲区?)此外,为了方便起见,如果索引+绑定点在着色器编译时只缓存一次,那么查询并获取它是否会比硬编码常量糟糕?(我知道每次查找都不好,但如果只查找一次…)WebGL2/OpenGL ES 3.0/GLSL ES 3.0没有GLSL中统一块的布局绑定设置,因此您必须调用
    uniformBlockBinding
    。至于在GLSL中设置它们或使用
    glUniformBlockBinding
    设置它们,这是一个意见问题。我是一个试图保持干爽的人(不要重复你自己),所以我会选择生成着色器,在这种情况下,可以在生成着色器时使用决定绑定位置的代码,或者使用一些共享常量预处理器文件,或者我会选择使用
    glUniformBlockBinding
    这样做,因为在任何情况下,我都可以按名称集中管理位置,而不必在遇到冲突时手动重新编写一堆着色器。您应该选择标记OpenGL或WebGL。答案会有所不同。OpenGL支持映射缓冲区,WebGL不支持(因为它不安全),所以更新统一块缓冲区的方式可能会非常不同。此外,OpenGL是一个C api,WebGL是一个JavaScript api,因此更新数据的方法有很大不同。在OpenGL中,可以声明与统一块数据匹配的结构。在JavaScript中,你不能这样做,你必须以非常不同的方式来做。此外,WebGL不支持在GLSL中设置绑定索引,正如您接受的答案所建议的那样。谢谢-将此更改为接受的答案,特别是考虑到删除的“opengl”标记后续问题-但不确定它是否应该是它自己的,所以发布。。。采样器位置是否可以/应该在初始时间绑定?e、 g.德国劳埃德船级社uniform1i(u_取样器,bindPoint);是的,这应该是它自己的问题,但这是一个意见的问题。gl.uniform设置程序状态,因此,如果您想预先确定特定程序将使用哪些采样器单元或纹理单元,那么请确保预先这样做是有意义的。我不使用取样器。我很少遇到需要使用具有不同采样器参数的纹理的情况。也许当我遇到这种情况时,我会开始使用它们。我并不是说它们不存在,只是说至少对于我参与的项目来说,它们是罕见的。