理解WebGL状态

理解WebGL状态,webgl,Webgl,我能在哪里找到任何文档记录WebGL调用所需的先决条件吗 我已经对WebGL的基础知识有了相当强的掌握,但现在我正在创建自己的“框架”,我需要更深入的理解 例如,enableVertexAttributeArray调用。此调用是否要求当前着色器处于“使用”状态?它将此“已启用”标志存储在何处?如果我切换着色器程序,我是否必须在以后再次使用它时重新启用它 我想要一些图表来解释所有“有状态”信息存储在哪里,以及何时脱离上下文 另一个例子是使用gl.bindBuffer,数组缓冲区和元素数组缓冲区的缓

我能在哪里找到任何文档记录WebGL调用所需的先决条件吗

我已经对WebGL的基础知识有了相当强的掌握,但现在我正在创建自己的“框架”,我需要更深入的理解

例如,enableVertexAttributeArray调用。此调用是否要求当前着色器处于“使用”状态?它将此“已启用”标志存储在何处?如果我切换着色器程序,我是否必须在以后再次使用它时重新启用它

我想要一些图表来解释所有“有状态”信息存储在哪里,以及何时脱离上下文

另一个例子是使用gl.bindBuffer,数组缓冲区和元素数组缓冲区的缓冲区是否存储在不同的位置

考虑到所有这些,是否建议在JavaScript中使用并行状态以避免运行WebGL调用?i、 e.存储“currentBuffer”对象,以避免在已绑定的情况下反复绑定同一缓冲区。我可以想象,在一般情况下,这会造成相当多的状态复制,但对性能来说可能相当好


这是一个基本问题,但很难找到相关信息。

我最近给出了一个类似的答案,但我只是说有很多,并提供了规范的链接,没有复制粘贴任何内容。吸取了教训,我可以解决这个问题。但这只是一个合理的警告,如果人们称WebGL为“有状态的”,他们的意思是。但是包含WebGL可以生成的所有错误的文档称为规范。我不会复制所有可能的错误,因为这很容易使它翻倍,如果不是更多的话

首先,因为明确询问了绑定目标,所以这里是查询所有这些目标的方式,不包括扩展:

gl.getParameter( gl.ARRAY_BUFFER_BINDING);
gl.getParameter( gl.ELEMENT_ARRAY_BUFFER_BINDING);
gl.getParameter( gl.FRAMEBUFFER_BINDING);
gl.getParameter( gl.RENDERBUFFER_BINDING);
gl.getParameter( gl.TEXTURE_BINDING_2D);
gl.getParameter( gl.TEXTURE_BINDING_CUBE_MAP);
现在你不必通过这个庞大的列表来找到这些。但是,如果您编写了一个框架,并且希望了解该状态,那么您可能也希望使用所有其他框架

如果你现在看看程序的状态,没有太多的重叠。人们甚至可以做实验,看看状态是如何变化的

或者,您可能想检查着色器的工作情况。仍然看不到真正的重叠

您看到
getVertexAttrib
返回一个缓冲区,因此这似乎是相关的。缓冲区本身并不比普通阵列缓冲区更令人兴奋。这些内容不是用JavaScript编写的,而是在遥远的gpu土地上,努力工作以支持家庭

所以程序和顶点数组可能没有那么多共同点。通过猜测很难推断,但如果您知道(或抽象出)所有这些获取者,则很容易发现

为了完整性,并帮助您理解状态,我还复制了所有其他内容

我还没有放弃缓和。所以也许你想检查一下你制服的价值。这有时真的很有用

下面是一些更有用的getter:

当然,每个人都爱的人:

哦,这里这个实际上属于顶点属性,几乎忘记了。由于重要的遗留原因,它是分开的

(pname必须是该节点上的顶点属性数组指针)


除非我忘了什么,这基本上就是WebGL状态的全部。这看起来可能很多,但我个人发现所有这些都对理解事物是如何工作的非常有帮助。如果没有这些,你基本上是被蒙住眼睛,不得不一直猜测,并且按照教程告诉你调用函数的确切顺序,这在WebGL中并不适用——因为有很多事情,但你也可以犯错误。

Screenius的答案相当完整

这是一个

简洁的版本是:

在WebGL 1.0中,制服按程序排列,纹理过滤和包装按纹理排列。其他一切都是全球性的。它包括所有属性和所有纹理单元

从以前的一些答案粘贴,涵盖这一点

您可以像这样考虑属性和纹理单元

gl = { 
   arrayBuffer: someBuffer, 
   vertexArray: {
     elementArrayBuffer: someOtherBuffer,
     attributes: [], 
   },
};
调用
gl.bindBuffer
时,您只需在gl状态下设置两个全局变量之一

gl.bindBuffer = function(bindPoint, buffer) {
   switch (bindPoint) {
      case: this.ARRAY_BUFFER:
         this.arrayBuffer = buffer;
         break;
      case: this.ELEMENT_ARRAY_BUFFER:
         this.vertexArray.elementArrayBuffer = buffer;
         break;
   }
};
调用
gl.VertexAttributePointer
时,它会将
arrayBuffer
的当前值复制到指定的属性

gl.vertexAttribPointer = function(index, size, type, normalized, stride, offset) {
    var attribute = this.vertexArray.attributes[index];
    attribute.size = size;
    attribute.type = type;
    attribute.normalized = normalized;
    attribute.stride = stride;
    attribute.offset = offset;
    attribute.buffer = this.arrayBuffer;  // copies the current buffer reference.
};
纹理的工作原理类似

gl = { 
    activeTextureUnit: 0,
    textureUnits: [], 
};
gl.activeTexture
设置您正在使用的纹理单元

gl.activeTexture = function(unit) {
   this.activeTextureUnit = unit - this.TEXTURE_0;  // make it zero based.
};
每个纹理单元都有一个
texture\u 2D
和一个
texture\u CUBEMAP
so
gl。bindTexture(b,t)
是有效的

gl.bindTexture = function(bindPoint, texture) {
   var textureUnit = this.textureUnits[this.activeTextureUnit];
   switch (bindPoint) {
       case this.TEXTURE_2D:
           textureUnit.texture2D = texture;
           break;
       case this.TEXTURE_CUBEMAP:
           textureUnit.textureCubeMap = texture;
           break;
   }
};
其余的是全局状态,如清晰颜色、视口、混合设置、模具设置、启用/禁用内容,如
深度测试
剪刀测试



只是一个旁注:如果你在上面的例子中启用
vertexArray
成为它自己的对象,你可以用
bindVertexArrayOES

绑定,那么我承认我花了一段时间才理解这篇文章的含义。我说要理解状态存储在哪里,我应该简单地看看我将如何查询它,这会告诉我,这是正确的吗?e、 g.如果我使用getParameter,它必须是“全局的”,如果我使用getProgramParameter,它必须与程序一起存储?这是有道理的。我想可以查询的任何内容都是独立的,因此存在gl.ARRAY\u BUFFER\u绑定和gl.ELEMENT\u ARRAY\u BUFFER\u绑定这一事实意味着它们是完全独立的绑定。@Brendannable是的,您的思路是正确的!嘿,我知道这已经有一段时间没有得到回答了,但我现在也在挖掘webgl状态的主题。以类似json的方式查看
gl={…}
状态非常有用。是否有任何白皮书/规范列出了完整的“webgl状态”?不需要函数
pname                           returned type
RENDERBUFFER_WIDTH              GLint
RENDERBUFFER_HEIGHT             GLint
RENDERBUFFER_INTERNAL_FORMAT    GLenum
RENDERBUFFER_RED_SIZE           GLint
RENDERBUFFER_GREEN_SIZE         GLint
RENDERBUFFER_BLUE_SIZE          GLint
RENDERBUFFER_ALPHA_SIZE         GLint
RENDERBUFFER_DEPTH_SIZE         GLint
RENDERBUFFER_STENCIL_SIZE       GLint
pname               returned type
TEXTURE_MAG_FILTER  GLenum
TEXTURE_MIN_FILTER  GLenum
TEXTURE_WRAP_S      GLenum
TEXTURE_WRAP_T      GLenum
gl = { 
   arrayBuffer: someBuffer, 
   vertexArray: {
     elementArrayBuffer: someOtherBuffer,
     attributes: [], 
   },
};
gl.bindBuffer = function(bindPoint, buffer) {
   switch (bindPoint) {
      case: this.ARRAY_BUFFER:
         this.arrayBuffer = buffer;
         break;
      case: this.ELEMENT_ARRAY_BUFFER:
         this.vertexArray.elementArrayBuffer = buffer;
         break;
   }
};
gl.vertexAttribPointer = function(index, size, type, normalized, stride, offset) {
    var attribute = this.vertexArray.attributes[index];
    attribute.size = size;
    attribute.type = type;
    attribute.normalized = normalized;
    attribute.stride = stride;
    attribute.offset = offset;
    attribute.buffer = this.arrayBuffer;  // copies the current buffer reference.
};
gl = { 
    activeTextureUnit: 0,
    textureUnits: [], 
};
gl.activeTexture = function(unit) {
   this.activeTextureUnit = unit - this.TEXTURE_0;  // make it zero based.
};
gl.bindTexture = function(bindPoint, texture) {
   var textureUnit = this.textureUnits[this.activeTextureUnit];
   switch (bindPoint) {
       case this.TEXTURE_2D:
           textureUnit.texture2D = texture;
           break;
       case this.TEXTURE_CUBEMAP:
           textureUnit.textureCubeMap = texture;
           break;
   }
};