webgl2.0规范(下)

773 阅读53分钟

3.7.7 程序和着色器

描述了在 WebGL 中如何创建和使用程序和着色器。

1. [WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram program, DOMString name) (OpenGL ES 3.0.6 §3.9.2.3man page)
  • 如果program是由不同于当前WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误并返回-1。
2.any getProgramParameter(WebGLProgram? program, GLenum pname) (OpenGL ES 3.0.6 §6.1.12man page)
  • 如果program是由不同于当前WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误并返回null。

  • 根据传递的programpname返回相应的值。返回的类型是请求的pname的自然类型,如下表所示:

    pnamereturned type
    DELETE_STATUSGLboolean
    LINK_STATUSGLboolean
    VALIDATE_STATUSGLboolean
    ATTACHED_SHADERSGLint
    ACTIVE_ATTRIBUTESGLint
    ACTIVE_UNIFORMSGLint
    TRANSFORM_FEEDBACK_BUFFER_MODEGLenum
    TRANSFORM_FEEDBACK_VARYINGSGLint
    ACTIVE_UNIFORM_BLOCKSGLint

    如果pname不在上面的表格中,将生成INVALID_ENUM错误并返回null。

    如果在执行此函数过程中生成任何OpenGL错误,则返回null。

3.7.8 Uniforms 和 attributes

介绍了如何设置和获取统一变量和属性数据。

1.any getUniform(WebGLProgram program, WebGLUniformLocation location) (OpenGL ES 3.0.6 §6.1.12man page)
  • 如果programlocation是由与此上下文不同的WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误。

在传递的程序中的传递位置处返回统一值。返回的类型取决于统一类型。WebGL 2.0中的新统一类型的返回类型如下表所示:

uniform typereturned type
uintGLuint
uvec2Uint32Array (with 2 elements)
uvec3Uint32Array (with 3 elements)
uvec4Uint32Array (with 4 elements)
mat2x3Float32Array (with 6 elements)
mat2x4Float32Array (with 8 elements)
mat3x2Float32Array (with 6 elements)
mat3x4Float32Array (with 12 elements)
mat4x2Float32Array (with 8 elements)
mat4x3Float32Array (with 12 elements)
any sampler typeGLint

与WebGL 1.0共享的统一类型的返回类型与WebGL 1.0中的相同。

2.void uniform[1234]ui(WebGLUniformLocation? location, ...)
3.void uniform[1234]uiv(WebGLUniformLocation? location, ...)
4.void uniformMatrix[234]x[234]fv(WebGLUniformLocation? location, ...) (OpenGL ES 3.0.6 §2.12.6man page)
  • 上述各个uniform*函数会将指定的统一变量或统一变量设置为提供的值。如果传递的location不为null且不是通过之前对getUniformLocation的调用从当前使用的程序获得的,将会生成INVALID_OPERATION错误。如果传递的location为null,则传递的数据将被静默忽略,不会更改任何统一变量。

如果传递给任何矢量形式的数组(以v结尾的形式)具有无效的长度,将生成INVALID_VALUE错误。长度无效的情况包括长度过短或不是指定类型的整数倍。

在具有srcLength参数的重载中:

  • 如果srcLength为0,则默认为data.length - srcOffset
  • 如果srcOffset + srcLengthdata.length还长,则生成INVALID_VALUE错误。
5.void vertexAttribI4[u]i(GLuint index, ...)
6.void vertexAttribI4[u]iv(GLuint index, ...) (OpenGL ES 3.0.6 §2.8man page)
  • 将传递的常数整数值设置为指定索引处的顶点属性。通过vertexAttrib设置的值可以通过带有CURRENT_VERTEX_ATTRIB参数的getVertexAttrib函数返回,即使在此期间进行了对drawArraysdrawElements的调用。

如果传递给任何矢量形式的数组(以v结尾的形式)过于短,则会生成INVALID_VALUE错误。

7.void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset) (OpenGL ES 3.0.6 §2.9man page)
  • 将当前绑定到ARRAY_BUFFER目标的WebGLBuffer对象分配给传递索引处的顶点属性。值始终保留为整数值。Size表示每个属性的组件数量。Stride和offset以字节为单位。传递的stride和offset必须适合传递的类型和大小,否则将生成INVALID_OPERATION错误;请参阅Buffer Offset and Stride Requirements。如果offset为负数,将生成INVALID_VALUE错误。如果没有将WebGLBuffer绑定到ARRAY_BUFFER目标且offset为非零,则会生成INVALID_OPERATION错误。在WebGL中,支持的最大stride为255;请参阅Vertex Attribute Data Stride
8.any getVertexAttrib(GLuint index, GLenum pname) (OpenGL ES 3.0.6 §6.1.12man page)
  • 返回有关传递索引处顶点属性的pname请求的信息。返回的类型取决于所请求的信息,如下表所示:

    pnamereturned type
    VERTEX_ATTRIB_ARRAY_BUFFER_BINDINGWebGLBuffer
    VERTEX_ATTRIB_ARRAY_ENABLEDGLboolean
    VERTEX_ATTRIB_ARRAY_SIZEGLint
    VERTEX_ATTRIB_ARRAY_STRIDEGLint
    VERTEX_ATTRIB_ARRAY_TYPEGLenum
    VERTEX_ATTRIB_ARRAY_NORMALIZEDGLboolean
    CURRENT_VERTEX_ATTRIBOne of Float32Array, Int32Array or Uint32Array (each with 4 elements)
    VERTEX_ATTRIB_ARRAY_INTEGERGLboolean
    VERTEX_ATTRIB_ARRAY_DIVISORGLint

    对于CURRENT_VERTEX_ATTRIB,返回类型由针对给定索引的vertexAttrib系列函数的最近调用决定。也就是说,如果使用了vertexAttribI4i*,返回类型将为Int32Array;如果使用了vertexAttribI4ui*,返回类型将为Uint32Array;否则,返回类型将为Float32Array。

    所有返回序列或类型化数组的查询每次都返回一个新对象。

    如果pname不在上述表格中,会生成一个INVALID_ENUM错误。

    如果生成OpenGL错误,会返回null。

3.7.9 向绘制缓冲区写入数据

解释了如何将数据写入绘制缓冲区,包括设置清除颜色、深度等。

1.void clear(GLbitfield mask) (OpenGL ES 3.0.6 §4.2.3man page)
  • 清除缓冲区以预设值。如果需要清除的缓冲区中包括整数颜色缓冲区,则会生成INVALID_OPERATION错误,不会执行清除操作。
2.void vertexAttribDivisor(GLuint index, GLuint divisor) (OpenGL ES 3.0.6 §2.9man page)
  • 设置通过绘制时,由index标识的顶点属性前进的速率。
3.void drawArrays(GLenum mode, GLint first, GLsizei count) (OpenGL ES 3.0.6 §2.9.3man page)
4.void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset) (OpenGL ES 3.0.6 §2.9.3man page)
5.void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) (OpenGL ES 3.0.6 §2.9.3man page)
  • [Draw Operation].
    使用当前启用的顶点属性绘制instanceCount个几何实例。具有非零分配因子的顶点属性在每个分配因子实例时前进一次。
6.void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei instanceCount) (OpenGL ES 3.0.6 §2.9.3man page)
  • [Draw Operation].
    使用当前绑定的元素数组缓冲绘制instanceCount个几何实例。具有非零分配因子的顶点属性在每个分配因子实例时前进一次。
7.void drawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset) (OpenGL ES 3.0.6 §2.9.3man page)
  • [Draw Operation].
    使用当前绑定的元素数组缓冲进行绘制。所有在WebGL 1.0规范的写入绘图缓冲区部分中指定的drawElements的错误条件也适用。

    此外,如果用于绘制的索引超出了范围[startend],实现可以保证在超出范围的数组访问中定义的行为,或者只是丢弃参数startend并调用drawElements。在任何情况下,不应因此原因生成GL错误。

在调用drawElementsdrawArraysdrawRangeElements及其实例化变体时,WebGL 2.0会执行比OpenGL ES 3.0规定更多的错误检查:

  • 如果CURRENT_PROGRAM为null,将生成INVALID_OPERATION错误;
  • 范围检查;
  • 活动统一块支持;
  • VertexAttrib函数必须与着色器属性类型匹配。

3.7.10 从绘制缓冲区读取像素

描述了从绘制缓冲区读取像素数据的方法。

1.undefined readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, [AllowShared] ArrayBufferView dstData, GLuint dstOffset) (OpenGL ES 3.0 §4.3.2man page)
  • [Read Operation].

    如果有一个WebGLBuffer绑定到PIXEL_PACK_BUFFER目标,将生成INVALID_OPERATION错误。

    如果未满足pixel store parameter constraints,将生成INVALID_OPERATION错误。

    如果dstDatadstOffset处开始的读取操作所需的空间不足,将生成INVALID_OPERATION错误。

这是一个阻塞操作,因为为了返回结果,WebGL必须完全完成对源帧缓冲区的所有先前渲染操作。在多进程WebGL实现中,这还会产生一个昂贵的跨进程往返,以从远程进程获取结果。 考虑改用将数据读取到PIXEL_PACK_BUFFER中的readPixels。然后使用getBufferSubData从该缓冲区中读取数据。(参见getBufferSubData以了解如何在该调用中避免阻塞。)

2.void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLintptr offset) (OpenGL ES 3.0 §4.3.2man page)
  • 如果没有WebGLBuffer绑定到PIXEL_PACK_BUFFER目标,将生成INVALID_OPERATION错误。

  • offset是字节偏移量,指示了从WebGLBuffer的数据存储中的哪个位置开始存储像素数据;如果offset小于0,将生成INVALID_VALUE错误。如果考虑到像素存储模式,WebGLBuffer的数据存储的剩余部分不足以检索指定矩形中的所有像素,将生成INVALID_OPERATION错误。

3.7.11 多个渲染目标

说明了如何使用多个渲染目标来进行并行渲染。

1.void drawBuffers(sequence<GLenum> buffers) (OpenGL ES 3.0.6 §4.2.1man page)
  • 定义绘制缓冲区,将所有片段颜色写入其中。

    这不进行绘制操作,仅为后续调用设置状态。

2.void clearBufferfv(GLenum buffer, GLint drawbuffer, Float32List values, optional GLuint srcOffset = 0);
3.void clearBufferiv(GLenum buffer, GLint drawbuffer, Int32List values, optional GLuint srcOffset = 0);
4.void clearBufferuiv(GLenum buffer, GLint drawbuffer, Uint32List values, optional GLuint srcOffset = 0);
5.void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); (OpenGL ES 3.0.6 §4.2.3man page) These are [Draw Operations].
  • 将指定缓冲区中的每个像素设置为一个常数值。应该根据颜色缓冲区的类型选择使用哪种clearBuffer函数,类型在以下表格中给出:

    Type of bufferclearBuffer function
    floating pointclearBufferfv
    fixed pointclearBufferfv
    signed integerclearBufferiv
    unsigned integerclearBufferuiv

    如果bufferCOLOR_BUFFER且函数不是根据上述表格选择的,将会生成一个INVALID_OPERATION错误,且不会进行清除操作。

对于ArrayBufferView入口点,如果从srcOffset开始的values中的元素不足,会生成INVALID_VALUE错误。

clearBufferfi可以用于清除深度和模板缓冲区。buffer必须为DEPTH_STENCIL,且drawBuffer必须为零。depthstencil分别是深度和模板值。

如果此函数尝试清除完整帧缓冲的缺失附件,则不会进行清除操作,也不会生成错误,详见绘制到缺失附件

3.7.12 查询对象

描述了查询对象的概念和使用方法,用于获取 GPU 信息。

1.WebGLQuery? createQuery() (OpenGL ES 3.0.6 §2.14man page)
  • 创建一个WebGLQuery对象,并将其初始化为一个查询对象名称,就像通过调用glGenQueries函数一样。
2.void deleteQuery(WebGLQuery? query) (OpenGL ES 3.0.6 §2.14man page)
  • 如果query是由不同于当前上下文的WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误。

将传入的WebGLQuery中包含的查询对象标记为删除,就像通过调用glDeleteQueries函数一样。如果对象已经标记为删除,则此调用没有效果。请注意,当JS对象被销毁时,底层GL对象将自动标记为删除,但此方法允许作者提前将对象标记为删除。

3.[WebGLHandlesContextLoss] GLboolean isQuery(WebGLQuery? query) (OpenGL ES 3.0.6 §6.1.7man page)
  • 如果传入的WebGLQuery对象有效,则返回true;否则返回false。

如果查询是由不同于当前上下文的WebGL2RenderingContext生成的,则返回false。

如果查询的invalidated标志已设置,则返回false。

4.void beginQuery(GLenum target, WebGLQuery query) (OpenGL ES 3.0.6 §2.14man page)
  • 如果query是由不同于当前的WebGL2RenderingContext生成的,则会生成一个INVALID_OPERATION错误。

开始一个异步查询。Target指示要执行的查询类型。

5.void endQuery(GLenum target) (OpenGL ES 3.0.6 §2.14man page)
  • 标记要跟踪的命令序列的结束,用于给定的查询类型target。当最终查询结果可用时,查询对象会被更新以指示此结果,然后可以通过调用getQueryParameter来检索结果。
6. WebGLQuery? getQuery(GLenum target, GLenum pname) (OpenGL ES 3.0.6 §6.1.7man page)
  • 返回关于查询目标target的信息,其中target必须是ANY_SAMPLES_PASSEDANY_SAMPLES_PASSED_CONSERVATIVE(用于遮挡查询)或TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN(用于基元查询)之一。pname指定查询对象目标参数的符号名称。目前必须是CURRENT_QUERY,返回目标的当前活动查询或null。

如果targetpname不在上述列表中,会生成INVALID_ENUM错误并返回null。

如果在执行此函数期间生成了任何OpenGL错误,则返回null。

7.[any getQueryParameter]()(WebGLQuery query, GLenum pname) (OpenGL ES 3.0.6 §6.1.7man page)
  • 如果query是由不同于当前WebGL2RenderingContext的上下文生成的,则会生成INVALID_OPERATION错误。

返回查询对象的参数pnameQUERY_RESULT返回查询对象的通过样本计数器的值。QUERY_RESULT_AVAILABLE返回样本计数器是否立即可用。返回的类型是请求的参数pname的自然类型,如下表所示:

pname返回类型
QUERY_RESULTGLuint
QUERY_RESULT_AVAILABLEGLboolean
  • 如果pname不在上述表中,会生成INVALID_ENUM错误并返回null。

    如果query不是有效的查询对象,或者是当前活动的查询对象,则会生成INVALID_OPERATION错误并返回null。

    如果在执行此函数期间生成了任何OpenGL错误,则返回null。

    为了确保在各个平台上实现一致的行为,只有在用户代理的event loop未执行任务时,才能使查询的结果可用。换句话说:

    • 只有在控制权返回到用户代理的主循环后,查询的结果才能可用。

    • 在循环中反复获取查询的QUERY_RESULT_AVAILABLE参数,而不将控制权返回给用户代理,必须始终返回相同的值。

    当控制权返回到用户代理的事件循环时,查询的结果可能会可用,也可能不会可用。不能保证使用一个延迟为0的单个setTimeout回调或一个单独的requestAnimationFrame回调,就足够时间让WebGL实现提供查询的结果。

    与OpenGL ES 3.0规范相比,此更改是为了防止应用程序依赖于能够在同一帧中发出查询并获取其结果。为了在各种设备之间实现最佳的可移植性和最佳的性能,应用程序必须预期查询的结果将异步地变为可用。

3.7.13 采样器对象

介绍了采样器对象的创建和使用,用于定义纹理采样参数。

1.WebGLSampler? createSampler() (OpenGL ES 3.0.6 §3.8.2man page)
  • 创建一个WebGLSampler对象,并像调用glGenSamplers一样用一个采样器对象名称进行初始化。.
2.void deleteSampler(WebGLSampler? sampler) (OpenGL ES 3.0.6 §3.8.2man page)
  • 如果sampler是由不同于当前的WebGL2RenderingContext生成的,将生成一个INVALID_OPERATION错误。

    将传递的WebGLSampler中包含的采样器对象标记为删除,就像调用glDeleteSamplers一样。如果对象已经标记为删除,则此调用不会产生任何效果。请注意,底层的GL对象将在JS对象被销毁时自动标记为删除,但此方法允许作者提前标记对象以进行删除。

3.[WebGLHandlesContextLoss] GLboolean isSampler(WebGLSampler? sampler) (OpenGL ES 3.0.6 §6.1.5man page)
  • 如果传递的WebGLSampler是有效的,则返回true;否则返回false。

    如果采样器是由不同于当前的WebGL2RenderingContext生成的,则返回false。

    如果采样器的invalidated flag设置为true,则返回false。

4.void bindSampler(GLuint unit, WebGLSampler? sampler) (OpenGL ES 3.0.6 §3.8.2man page)
  • 如果sampler是由不同于当前WebGL2RenderingContext生成的,则生成INVALID_OPERATION错误。

    将传递的WebGLSampler中包含的采样器对象绑定到指定索引处的纹理单元。如果在纹理单元上绑定了采样器,采样器的状态会覆盖该纹理单元上绑定的纹理的采样状态。如果sampler为null,则当前绑定的采样器将从纹理单元解绑。一个采样器对象可以同时绑定到多个纹理单元。

    如果unit大于或等于MAX_COMBINED_TEXTURE_IMAGE_UNITS的值,则生成INVALID_VALUE错误。

    尝试绑定一个标记为删除的对象将生成INVALID_OPERATION错误,当前绑定不会受影响。

5.void samplerParameteri(WebGLSampler sampler, GLenum pname, GLint param)
6.void samplerParameterf(WebGLSampler sampler, GLenum pname, GLfloat param)(OpenGL ES 3.0.6 §3.8.2man page)
  • 如果sampler是由不同于当前WebGL2RenderingContext生成的,则生成INVALID_OPERATION错误。

    根据传递的采样器设置给定pname的值。pname的值如下表所示:

    pname
    TEXTURE_COMPARE_FUNC
    TEXTURE_COMPARE_MODE
    TEXTURE_MAG_FILTER
    TEXTURE_MAX_LOD
    TEXTURE_MIN_FILTER
    TEXTURE_MIN_LOD
    TEXTURE_WRAP_R
    TEXTURE_WRAP_S
    TEXTURE_WRAP_T
    如果pname不在上述表中,会生成INVALID_ENUM错误。

    如果sampler不是有效的sampler对象,会生成INVALID_OPERATION错误。

    7.any getSamplerParameter(WebGLSampler sampler, GLenum pname) (OpenGL ES 3.0.6 §6.1.5man page)
  • 如果sampler是由不同于当前的WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误。

    根据请求的信息,返回关于给定的WebGLSampler(作为sampler传递)的pname所请求的信息。返回的类型取决于所请求的信息,如下表所示:

    pnamereturned type
    TEXTURE_COMPARE_FUNCGLenum
    TEXTURE_COMPARE_MODEGLenum
    TEXTURE_MAG_FILTERGLenum
    TEXTURE_MAX_LODGLfloat
    TEXTURE_MIN_FILTERGLenum
    TEXTURE_MIN_LODGLfloat
    TEXTURE_WRAP_RGLenum
    TEXTURE_WRAP_SGLenum
    TEXTURE_WRAP_TGLenum

    如果pname不在上述表中,会生成INVALID_ENUM错误。

    如果sampler不是有效的sampler对象,会生成INVALID_OPERATION错误。

    如果在执行此函数时生成任何OpenGL错误,则返回null。

3.7.14 同步对象

描述了同步对象的作用和使用方法,用于同步 GPU 操作。

1.WebGLSync? fenceSync(GLenum condition, GLbitfield flags) (OpenGL ES 3.0.6 §5.2man page)
  • 创建一个新的fence sync对象,并在GL命令流中插入一个关联的fence命令。
2.[WebGLHandlesContextLoss] GLboolean isSync(WebGLSync? sync) (OpenGL ES 3.0.6 §6.1.8man page)
  • 如果传递的WebGLSync对象有效,则返回true;否则返回false。

    如果这个同步对象是由与当前WebGL2RenderingContext不同的上下文生成的,则返回false。

    如果这个同步对象的无效标志被设置,则返回false。

3.void deleteSync(WebGLSync? sync) (OpenGL ES 3.0.6 §5.2man page)
  • 如果sync是由与当前WebGL2RenderingContext不同的上下文生成的,将会生成一个INVALID_OPERATION错误。

    将传递的WebGLSync对象中的同步对象标记为删除,就好像调用了glDeleteSync一样。如果该对象已经被标记为删除,调用将不会产生任何效果。需要注意的是,当JS对象被销毁时,底层的GL对象将自动标记为删除,但是这个方法允许开发者提前标记一个对象为删除。

4.[GLenum clientWaitSync(WebGLSync sync, GLbitfield flags, GLuint64 timeout)]() (OpenGL ES 3.0.6 §5.2.1man page)
  • 如果sync是由与当前WebGL2RenderingContext不同的上下文生成的,将会生成一个INVALID_OPERATION错误。

    阻塞执行,直到传递的同步对象被标记为已信号或经过了指定的超时时间。timeout以纳秒为单位。

    返回四个状态值中的一个。如果在调用clientWaitSync时,sync已经被标记为信号,返回值将为ALREADY_SIGNALED。即使timeout为零,如果sync被标记为信号,也将始终返回ALREADY_SIGNALED。如果在sync被标记为信号之前指定的超时时间已过期,则返回TIMEOUT_EXPIRED。如果在超时时间过期之前,sync被标记为信号,返回CONDITION_SATISFIED。最后,如果发生错误,除了按照下面的规定生成错误外,将返回WAIT_FAILED而不会阻塞。

    flags控制命令刷新行为,可能包括SYNC_FLUSH_COMMANDS_BIT。如果在flags中设置了任何其他位,将生成一个INVALID_OPERATION错误。如果在调用clientWaitSync时,在flags中设置了SYNC_FLUSH_COMMANDS_BIT并且sync未被标记为信号,则在阻塞sync之前将执行等效于flush的操作。

    正如在差异部分中讨论的,为了防止主线程被阻塞很长时间,WebGL实现必须强制实施一个短的最大超时时间。可以通过使用参数MAX_CLIENT_WAIT_TIMEOUT_WEBGL调用getParameter来查询实现定义的超时时间。如果timeout大于这个实现定义的超时时间,则会生成一个INVALID_OPERATION错误。

    实现定义的最大超时时间没有指定。它应该设置得足够低,以防止应用程序等待很长时间来妨碍交互性。实现可以强制执行零最大超时。WebGL应用程序不应该使用clientWaitSync来阻塞执行很长时间。

    如果在执行此函数期间生成任何OpenGL错误,则返回WAIT_FAILED

    为了确保跨平台的一致行为,同步对象只有在用户代理的event loop未执行任务时才能转换为已信号状态。换句话说:

    • 对于新创建的同步对象,clientWaitSync不能返回CONDITION_SATISFIEDALREADY_SIGNALED,直到控制已返回到用户代理的主循环中。
5.void waitSync(WebGLSync sync, GLbitfield flags, GLint64 timeout) (OpenGL ES 3.0.6 §5.2.1man page)
  • 如果sync是由与当前WebGL2RenderingContext不同的上下文生成的,将会生成一个INVALID_OPERATION错误。

    立即返回,但在GL服务器上等待,直到传递的同步对象被标记为信号或经过了实现相关的超时时间。传递的timeout必须设置为TIMEOUT_IGNORED

在无法在多个GL上下文之间进行同步的情况下,调用waitSync实际上是一个无操作(no-op)。

6.[any getSyncParameter(WebGLSync sync, GLenum pname)]() (OpenGL ES 3.0.6 §6.1.8man page)
  • 如果sync是由与当前WebGL2RenderingContext不同的上下文生成的,将会生成一个INVALID_OPERATION错误。

    返回给定WebGLSync对象的传递的pname的值。返回的类型是所请求pname的自然类型,如下表所示:

    pname返回类型
    OBJECT_TYPEGLenum
    SYNC_STATUSGLenum
    SYNC_CONDITIONGLenum
    SYNC_FLAGSGLbitfield

    如果pname不在上述表中,将生成一个INVALID_ENUM错误,并返回null。

    如果在执行此函数期间生成任何OpenGL错误,则返回null。

    为确保在各个平台上保持一致的行为,只有当用户代理的event loop未执行任务时,同步对象才能过渡到已标记状态。换句话说:

    • 同步对象必须在控制权返回给用户代理的主循环之后才能变为已标记状态。
    • 反复在循环中获取同步对象的SYNC_STATUS参数,而不将控制权返回给用户代理,必须始终返回相同的值。

3.7.15 变换反馈

WebGL 中的变换反馈模式用于捕获由顶点着色器写入的输出变量的值。这些顶点在进行平面着色和剪裁之前被捕获。变换后的顶点可以选择在存储到一个或多个缓冲对象后被丢弃,或者可以传递到剪裁阶段进行进一步处理。捕获的输出变量集在程序链接时确定。

如果某个输出变量被指定为要流式传输到变换反馈缓冲对象,但实际上并未由顶点着色器写入,其值将被设置为 0。这涉及到变换反馈原语捕获,其中可以捕获原语属性的值,并在后续流程中使用。

1.WebGLTransformFeedback? createTransformFeedback() (OpenGL ES 3.0.6 §2.15.1, similar to glGenTransformFeedbacks)
  • 创建一个WebGLTransformFeedback对象,并将其初始化为一个变换反馈对象名称,就好像通过调用glGenTransformFeedbacks来生成一样。
2.void deleteTransformFeedback(WebGLTransformFeedback? transformFeedback) (OpenGL ES 3.0.6 §2.15.1, similar to glDeleteTransformFeedbacks)
  • 如果transformFeedback是由不同于当前上下文的WebGL2RenderingContext生成的,将会生成INVALID_OPERATION错误。

    将传递的WebGLTransformFeedback中包含的变换反馈对象标记为删除,就好像通过调用glDeleteTransformFeedbacks一样。如果对象已经标记为删除,调用将没有任何效果。请注意,底层的GL对象将在JS对象销毁时自动标记为删除,但这种方法允许作者提前标记对象为删除状态。

3.[WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? transformFeedback) (OpenGL ES 3.0.6 §6.1.11man page)
  • 如果传递的WebGLTransformFeedback有效,则返回true,否则返回false。

    如果变换反馈是由不同于当前上下文的WebGL2RenderingContext生成的,则返回false。

    如果变换反馈的无效标志已设置,则返回false。

4.void bindTransformFeedback (GLenum target, WebGLTransformFeedback? transformFeedback) (OpenGL ES 3.0.6 §2.15.1man page)
  • 如果transformFeedback是由不同于当前WebGL2RenderingContext生成的,则会生成一个INVALID_OPERATION错误。

    绑定给定的WebGLTransformFeedback对象。如果transformFeedback为null,则绑定上下文提供的默认变换反馈对象。尝试绑定一个标记为删除的对象将生成一个INVALID_OPERATION错误,当前的绑定状态将保持不变。

5.void beginTransformFeedback(GLenum primitiveMode) (OpenGL ES 3.0.6 §2.15.2man page)
6.void endTransformFeedback() (OpenGL ES 3.0.6 §2.15.2man page)
7.void pauseTransformFeedback() (OpenGL ES 3.0.6 §2.15.2man page)
8.void resumeTransformFeedback() (OpenGL ES 3.0.6 §2.15.2man page)
9.void transformFeedbackVaryings(WebGLProgram program, sequence<DOMString> varyings, GLenum bufferMode) (OpenGL ES 3.0.6 §2.12.8man page)
  • 如果program是由不同于当前WebGL2RenderingContext生成的,则会生成一个INVALID_OPERATION错误。
10.WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram program, GLuint index) (OpenGL ES 3.0.6 §2.12.8man page)
  • 如果program是由不同于当前WebGL2RenderingContext生成的,则会生成一个INVALID_OPERATION错误。

3.7.16 统一变量缓冲区对象

介绍了统一变量缓冲区对象的创建和使用,用于在多个着色器程序之间共享数据。

1.void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer) (OpenGL ES 3.0.6 §2.10.1.1man page)
  • 如果 buffer 是由不同于当前上下文的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    将给定的 WebGLBuffer 对象绑定到由 target 指定的目标数组中的 index 处的绑定点。

2.void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size) (OpenGL ES 3.0.6 §2.10.1.1man page)
  • 如果 buffer 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    WebGLBuffer 对象的缓冲区的指定范围(由 offsetsize 表示)绑定到由 target 指定的目标数组中的 index 处的绑定点。

3.sequence<GLuint>? getUniformIndices(WebGLProgram program, sequence<DOMString> uniformNames) (OpenGL ES 3.0.6 §2.12.6man page)
  • 如果 program 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    此函数检索 program 中多个 uniform 的索引。

    如果在函数执行过程中生成了任何 OpenGL 错误,则返回 null。

4.any getActiveUniforms(WebGLProgram program, sequence<GLuint> uniformIndices, GLenum pname) (OpenGL ES 3.0.6 §2.12.6man page)
  • 如果 program 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    此函数查询指定在 uniformIndices 数组中的索引所对应的 program 中每个 uniform 的参数值,该参数名为 pname。返回的类型是请求的 pname 的自然类型,如下表所示:

    pnamereturned type
    UNIFORM_TYPEsequence
    UNIFORM_SIZEsequence
    UNIFORM_BLOCK_INDEXsequence
    UNIFORM_OFFSETsequence
    UNIFORM_ARRAY_STRIDEsequence
    UNIFORM_MATRIX_STRIDEsequence
    UNIFORM_IS_ROW_MAJORsequence

    如果 pname 不在上述表格中,将生成 INVALID_ENUM 错误。

    如果在执行此函数期间生成任何 OpenGL 错误,则返回 null。

5.GLuint getUniformBlockIndex(WebGLProgram program, DOMString uniformBlockName) (OpenGL ES 3.0.6 §2.12.6man page)
  • 如果 program 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    此函数用于检索在 program 中的一个统一变量块(uniform block)的索引。

6.any getActiveUniformBlockParameter(WebGLProgram program, GLuint uniformBlockIndex, GLenum pname) (OpenGL ES 3.0.6 §2.12.6man page)
  • 如果 program 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    此函数用于检索有关在 program 中活动的统一变量块(uniform block)的信息。返回的类型取决于所请求的 pname,如下表所示:

    pnamereturned type
    UNIFORM_BLOCK_BINDINGGLuint
    UNIFORM_BLOCK_DATA_SIZEGLuint
    UNIFORM_BLOCK_ACTIVE_UNIFORMSGLuint
    UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICESUint32Array
    UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADERGLboolean
    UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADERGLboolean

    如果 pname 不在上述表中的内容中,则会生成 INVALID_ENUM 错误。

    如果 uniformBlockIndex 不是 program 的活动块统一变量(uniform block),或者大于等于 ACTIVE_UNIFORM_BLOCKS 的值,则会生成 INVALID_VALUE 错误。

    如果生成了 OpenGL 错误,则会返回 null。

7.DOMString? getActiveUniformBlockName(WebGLProgram program, GLuint uniformBlockIndex) (OpenGL ES 3.0.6 §2.12.6man page)
  • 如果 program 是由不同于当前上下文的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    program 中检索位于 uniformBlockIndex 处的活动块统一变量(uniform block)的名称。

8.void uniformBlockBinding(WebGLProgram program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) (OpenGL ES 3.0.6 §2.12.6.5man page)
  • 如果 program 是由不同于当前的 WebGL2RenderingContext 生成的,则会生成 INVALID_OPERATION 错误。

    为活动块统一变量(uniform block)分配绑定点。

3.7.17 顶点数组对象

顶点数组对象(有时称为VAO)封装了与顶点处理器使用的数据定义相关的所有状态。

1.void bindVertexArray(WebGLVertexArrayObject? vertexArray) (OpenGL ES 3.0.6 §2.11man page)
  • 如果vertexArray是由不同于当前WebGL2RenderingContext的上下文生成的,则会生成INVALID_OPERATION错误。

    绑定给定的WebGLVertexArrayObject对象。如果vertexArray为null,则绑定上下文提供的默认顶点数组。尝试绑定已删除的顶点数组将生成INVALID_OPERATION错误,当前的绑定状态将保持不变。

2.WebGLVertexArrayObject? createVertexArray() (OpenGL ES 3.0.6 §2.11, similar to glGenVertexArrays)
  • 创建一个WebGLVertexArrayObject对象,并将其初始化为顶点数组对象的名称,就像调用glGenVertexArrays一样。
3.void deleteVertexArray(WebGLVertexArrayObject? vertexArray) (OpenGL ES 3.0.6 §2.11, similar to glDeleteVertexArrays)
  • 如果vertexArray是由不同于当前上下文的WebGL2RenderingContext生成的,则会生成INVALID_OPERATION错误。

    将包含在传递的WebGLVertexArrayObject中的顶点数组对象标记为删除,就像通过调用glDeleteVertexArrays一样。如果该对象已经标记为删除,则此调用无效。请注意,当JS对象被销毁时,底层的GL对象将自动标记为删除,但此方法允许作者提前标记对象为删除。

4.[WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray) (OpenGL ES 3.0.6 §6.1.10man page)
  • 如果传递的WebGLVertexArrayObject是有效的,则返回true;否则返回false。

    如果顶点数组是由不同于当前上下文的WebGL2RenderingContext生成的,则返回false。

    如果顶点数组的无效标志被设置,则返回false。

4.webgl1.0和webgl2.0的其他不同

4.1 向后不兼容性

4.1.1 错误

WebGL 2.0 API在WebGL 1.0 API生成错误的情况下可能会有不同的行为。使用WebGL 1.0 API编写的代码如果生成错误,不保证在WebGL 2.0中能够向前兼容。

4.1.2 扩展

一些在WebGL 1.0 API中可能被支持的扩展在WebGL 2.0 API中被移除。有关更多细节,请参阅WebGL扩展注册表。

通常,扩展只会在WebGL 2.0 API中存在等效功能的情况下被移除,这些功能可以是核心规范中的一部分,也可以是改进的扩展。当将使用WebGL 1.0扩展的应用程序修改为在WebGL 2.0 API上运行时,通常可以为每个提升的扩展创建一个虚拟扩展对象,该对象只是将调用重定向到相应的WebGL 2.0 API函数。如果应用程序使用了着色器语言扩展,通常需要将着色器移植到GLSL ES 3.00。

4.1.3 非二次幂纹理访问

在WebGL 2.0 API中,纹理访问的工作方式与OpenGL ES 3.0 API相同。换句话说,与WebGL 1.0 API不同,非2的幂纹理没有特殊限制。所有的多级纹理映射和所有的包装模式都支持非2的幂图像。

4.1.4 原始重启始终被启用

在WebGL 2.0中,PRIMITIVE_RESTART_FIXED_INDEX是一种功能,允许通过固定索引值来表示原始重启。这意味着在WebGL 2.0中,无论何时都默认启用了固定索引的原始重启功能。这种功能可以使渲染图元更加灵活,并且无需在顶点数据中指定特殊的重启值。

4.1.5 Framebuffer Object 关联对象

在WebGL 1.0中,DEPTH_STENCIL_ATTACHMENT是除了DEPTH_ATTACHMENTSTENCIL_ATTACHMENT之外的一个替代附件点。然而,在WebGL 2.0中,DEPTH_STENCIL_ATTACHMENT被视为DEPTH_ATTACHMENTSTENCIL_ATTACHMENT的别名,即相同的图像附加到DEPTH_ATTACHMENTSTENCIL_ATTACHMENT,覆盖了附加到这两个附件点的原始图像。

考虑以下操作序列:

  1. 将渲染缓冲区1附加到DEPTH_ATTACHMENT
  2. 将渲染缓冲区2附加到DEPTH_STENCIL_ATTACHMENT
  3. 将null附加到DEPTH_STENCIL_ATTACHMENT

在WebGL 1.0中,帧缓冲最终会将渲染缓冲区1附加到DEPTH_ATTACHMENT,而STENCIL_ATTACHMENT没有附加图像;然而,在WebGL 2.0中,既没有DEPTH_ATTACHMENT也没有STENCIL_ATTACHMENT附加图像。

在WebGL 2.0中,不再适用于帧缓冲对象附件的约束条件。如果不同的图像绑定到了深度和模板附件点,checkFramebufferStatus将返回FRAMEBUFFER_UNSUPPORTED,并且使用附件为DEPTH_STENCIL_ATTACHMENTgetFramebufferAttachmentParameter将生成INVALID_OPERATION错误。

4.1.6 在TexSubImage2D调用中的纹理类型。

在WebGL 1.0 API中,传递给texSubImage2D的类型参数必须与最初定义纹理对象时使用的类型相匹配(即使用texImage2D)。然而,在WebGL 2.0 API中,这个限制被取消了。

4.1.7 在copyTexSubImage2DreadPixels调用中的越界行为:

在WebGL 1.0中,在帧缓冲区外读取像素时,要求copyTexSubImage2DreadPixels不要触及越界像素对应的目标范围。

在WebGL 2.0中,当绑定了PACK_BUFFER对象并且PACK_ROW_LENGTH不为零且小于宽度,或者绑定了UNPACK_BUFFER对象并且UNPACK_ROW_LENGTH不为零且小于宽度,或者UNPACK_IMAGE_HEIGHT不为零且小于高度时,打包/解包一行/图像可能会延伸到下一行/图像。如果该部分越界,像素值可能会相应地改变。

4.1.8 copyTex{Sub}Image2D调用的颜色转换

在WebGL 1.0(OpenGL ES 2.0)中,允许internalformat的组件大小小于源缓冲区的内部格式的相应组件大小。然而,在WebGL 2.0(OpenGL ES 3.0)中,如果internalformat是sized格式,其组件大小必须与源缓冲区的有效内部格式的相应组件大小完全匹配。

在WebGL 1.0和2.0中,转换为internalformat时,源缓冲区的组件可以被丢弃,但不能添加新的组件。这确保了数据的正确性和一致性,以便在不同的内部格式之间进行数据转换和操作。

4.1.9 getFramebufferAttachmentParameter with FRAMEBUFFER_ATTACHMENT_OBJECT_NAME

如果在WebGL 1.0 / ES 2.0中使用getFramebufferAttachmentParameter函数,且参数pnameFRAMEBUFFER_ATTACHMENT_OBJECT_NAME,而附着点没有图像附着,那么会生成一个INVALID_OPERATION错误。但是在WebGL 2.0 / ES 3.0中,不会生成错误,而是返回null。这种变化在处理没有图像附着的情况时提供了更好的错误处理和数据查询方式。

4.2 在webgl2.0中增加的新功能

4.3 GLSL ES 3.00支持

除了支持OpenGL ES Shading Language版本1.00外,WebGL 2.0 API还接受使用OpenGL ES Shading Language版本3.00 [GLES30GLSL]编写的着色器,但有一些限制。

不得允许着色器引用其他版本GLSL中可用的状态变量或函数,例如在桌面版本的OpenGL中找到的变量或函数。

与WebGL 1.0 API一样,以 "webgl_" 和 "webgl" 开头的标识符被保留供WebGL使用。以这些前缀开始声明函数、变量、结构名称或结构字段的着色器不得被允许加载。这些保留前缀的标识符用于避免命名冲突和混淆。

4.3.1 最大代码单元

WebGL 1.0支持长度最多为256个字符的令牌。WebGL 2.0遵循《OpenGL ES Shading Language,版本3.00》(OpenGL ES 3.0.6 §1.5.1)的规定,允许在ESSL 1和ESSL 3着色器中使用长度最多为1024个字符的令牌。包含超过1024个字符长度令牌的着色器必须编译失败。

4.3.2 最大Uniform和Attribute长度

WebGL 2.0 对统一变量和属性位置的长度施加了1024字符的限制。

4.4 顶点属性分配器

在WebGL 2.0 API中,顶点属性的分配器非零时,在调用drawArrays和drawElements时不会前进。(OpenGL ES 3.0.6 §2.9.3)

5.WebGL与OpenGL ES 3.0之间的差异

本节描述了相对于OpenGL ES 3.0 API所做的更改,以改善在各种操作系统和设备之间的可移植性。

5.1 缓冲对象绑定

WebGL缓冲类型设置此类型的绑定点
未定义
元素数组ELEMENT_ARRAY_BUFFER
其他数据除ELEMENT_ARRAY_BUFFER、COPY_READ_BUFFER和COPY_WRITE_BUFFER之外的所有绑定点

在WebGL 2.0 API中,缓冲区的WebGL缓冲类型最初设置为未定义。然后,使用目标参数调用bindBuffer、bindBufferRange或bindBufferBase,除COPY_READ_BUFFER或COPY_WRITE_BUFFER之外的任何缓冲区绑定点,将根据上表设置要绑定缓冲区的WebGL缓冲类型。将类型未定义的缓冲区绑定到COPY_READ_BUFFER或COPY_WRITE_BUFFER绑定点将将其类型设置为其他数据。

任何尝试绑定已删除缓冲区的这些函数调用都会生成INVALID_OPERATION错误,且绑定状态将保持不变。

任何尝试将具有元素数组WebGL缓冲类型的WebGLBuffer绑定到其他数据下的绑定点,或将具有其他数据WebGL缓冲类型的WebGLBuffer绑定到ELEMENT_ARRAY_BUFFER,都会生成INVALID_OPERATION错误,且绑定点状态将保持不变。

这个限制意味着给定的缓冲对象可以包含索引或其他数据,但不能同时包含两者。

这些限制类似于WebGL 1.0规范中的缓冲对象绑定限制。

为了防止在GPU上写入索引缓冲区,从而使得在CPU端对索引数据进行任何检查变得代价高昂,增加了此限制。将索引缓冲区与其他缓冲数据区分开,也更好地映射到Direct3D API。

5.2 复制缓冲区

尝试使用copyBufferSubData在具有元素数组和其他数据WebGL缓冲类型的缓冲区之间进行复制,如Buffer Object Binding一节中所述,将生成INVALID_OPERATION错误,并且不会执行复制操作。

与上述缓冲对象绑定限制类似。

5.3 通过Transform Feedback预防未定义行为

在当前绑定的变换反馈对象中同时绑定到索引化的TRANSFORM_FEEDBACK_BUFFER绑定点和WebGL API中的任何其他绑定点,除了通用的TRANSFORM_FEEDBACK_BUFFER绑定点,是不允许的。任何尝试使用这样的双重绑定缓冲区的操作都会失败,并生成INVALID_OPERATION错误,无论是否启用了变换反馈。例如,如果缓冲区也绑定到当前的变换反馈对象,则对PIXEL_PACK_BUFFER的readPixels操作将失败。

如果不生成错误,则读取或写入的值将是未定义的。 (OpenGL ES 3.0.6 §2.15.2)

如果同一缓冲区在活动变换反馈中绑定到多个索引化绑定点,beginTransformFeedback将生成INVALID_OPERATION错误。

这只会在SEPARATE_ATTRIBS模式下发生。

这是D3D11中的限制,不允许将两个不同的流写入同一缓冲区。

5.4 绘制缓冲区

MAX_COLOR_ATTACHMENTS参数的值必须等于MAX_DRAW_BUFFERS参数的值。

这些参数不应该有不同的用例。

如果ESSL1片段着色器既不写入gl_FragColor也不写入gl_FragData,那么在着色器执行后,其后的片段颜色值将保持不变。如果ESSL3片段着色器中未定义相应的输出变量,则在着色器执行后,其后的片段颜色值将保持不变。

如果不在着色器执行期间写入所有用户定义的输出变量,默认情况下它们将被设置为零。

为了获得最佳性能,输出数组不应包含未在着色器执行期间访问的任何元素。

如果片段着色器写入的值与相应颜色缓冲区的格式不匹配(例如,输出变量是整数,但相应颜色缓冲区具有浮点格式,反之亦然),且颜色缓冲区状态未被DrawBuffers设置为NONE,则绘制操作将生成INVALID_OPERATION错误;如果颜色缓冲区状态被DrawBuffers设置为NONE,则它们将保持不变。

如果任何附着有附件的绘制缓冲区没有定义的片段着色器输出,则绘制操作将生成INVALID_OPERATION,除非colorMask的所有4个通道都设置为false。

5.5 没有程序二进制

在WebGL 2.0 API中,不支持访问编译后的着色器程序的二进制表示。这包括OpenGL ES 3.0中的GetProgramBinary、ProgramBinary和ProgramParameteri入口点。此外,在WebGL 2.0 API中,不支持使用getParameter查询程序二进制长度以及使用getParameter查询程序二进制格式。

5.6 范围检查

除了WebGL 1.0规范的“启用顶点属性和范围检查”部分中指定的范围检查外,drawElements、drawRangeElements或drawElementsInstanced引用的索引,如果大于MAX_ELEMENT_INDEX参数,即使它们在绑定缓冲区的存储范围内,绘制调用也会生成INVALID_OPERATION错误。对于触发了原始重启的索引,不执行范围检查,如果启用了原始重启。WebGL 1.0 API中为drawArrays指定的范围检查也适用于WebGL 2.0 API中的drawArraysInstanced。

OpenGL鲁棒性扩展未指定使用超过MAX_ELEMENT_INDEX的索引会发生什么情况,因此将它们传递给驱动程序是有风险的。在MAX_ELEMENT_INDEX与最大无符号整数值相同的平台上,此部分不会产生影响。

5.7 活动统一块支持

在WebGL 2.0 API中,如果用于绘制命令的程序中的任何活动统一块未由足够大的缓冲区对象支持,尝试使用drawArrays、drawElements、drawRangeElements或其实例化变体进行绘制,将生成INVALID_OPERATION错误。

在OpenGL中,不足的统一块支持允许导致GL中断或终止。请参阅OpenGL ES 3.0规范第2.12.6节(OpenGL ES 3.0.6 §2.12.6),下面的“Uniform Buffer Object Bindings”。

5.8 默认帧缓冲区

WebGL始终具有默认帧缓冲区。FRAMEBUFFER_UNDEFINED枚举已从WebGL 2.0 API中删除。

5.9 字符串长度查询

在WebGL 2.0 API中,枚举ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH、TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH、UNIFORM_BLOCK_NAME_LENGTH和UNIFORM_NAME_LENGTH被删除,这些枚举除了WebGL 1.0 API中删除的类似枚举。

5.10 无效清除操作

在WebGL 2.0 API中,当指定的清除值的类型与正在清除的缓冲区的类型不匹配时,尝试执行清除操作将生成INVALID_OPERATION错误,而不是产生未定义的结果。

5.11 无效纹理偏移

在WebGL 2.0 API中,GLSL着色器尝试使用超出由实现定义的MIN_PROGRAM_TEXEL_OFFSET和MAX_PROGRAM_TEXEL_OFFSET参数范围的纹理偏移值时,必须在编译时失败。

使用超出有效范围的偏移将返回未定义的结果,因此不能允许这样做。偏移必须是GLSL ES规范中的常量表达式,因此可以在编译时根据正确的范围检查值。

5.12 Texel抓取

在WebGL 2.0 API中,具有OpenGL ES 3.0 API中未定义结果的Texel抓取必须返回零,或者在WebGL 2.0 API中,从不完整纹理抓取的情况下,返回纹理源颜色(0, 0, 0, 1)。

为了确保安全性,需要能够测试超出范围的Texel抓取的行为。

5.13 GLSL ES 1.00片段着色器输出

在WebGL 2.0 API中,用于将值静态分配给gl_FragData[n](其中n不等于常量值0)的OpenGL ES Shading Language 1.00版本的片段着色器必须在WebGL 2.0 API中编译失败。这是为了与OpenGL ES 3.0规范第4.2.1节(OpenGL ES 3.0.6 §4.2.1)和OpenGL ES Shading Language 3.00.6规范第1.5节(GLSL ES 3.00.6 §1.5)保持一致。与OpenGL ES 3.0 API一样,仅支持WebGL 2.0 API中的GLSL ES 3.00着色器的多个片段着色器输出。

5.14 不支持MapBufferRange

WebGL 2.0 API中已删除MapBufferRange、FlushMappedBufferRange和UnmapBuffer入口点。以下枚举值也已删除:BUFFER_ACCESS_FLAGS、BUFFER_MAP_LENGTH、BUFFER_MAP_OFFSET、MAP_READ_BIT、MAP_WRITE_BIT、MAP_INVALIDATE_RANGE_BIT、MAP_INVALIDATE_BUFFER_BIT、MAP_FLUSH_EXPLICIT_BIT和MAP_UNSYNCHRONIZED_BIT。

可以通过使用getBufferSubData入口点来读取缓冲区数据,而不是使用MapBufferRange。

5.15 TIMEOUT_IGNORED

在WebGL 2.0 API中,TIMEOUT_IGNORED被定义为一个GLint64值,其值为-1,而不是一个值为0xFFFFFFFFFFFFFFFF的GLuint64值。这是因为JavaScript无法准确表示如此大的整数。由于相同的原因,waitSync使用GLint64值而不是GLuint64值作为超时参数。

5.16 clientWaitSync

在WebGL 2.0 API中,WebGL实现必须对调用clientWaitSync施加短时间的最大超时限制,以避免阻塞主线程的执行时间过长。可以通过使用参数MAX_CLIENT_WAIT_TIMEOUT_WEBGL调用getParameter来查询此超时。

实现定义的最大超时未指定。实现可以强制执行零最大超时,这是可以接受的。

5.17 顶点属性别名

WebGL 2.0 API实现必须严格遵循GLSL ES 3.00.6第12.46节的规定,即不允许任何顶点属性别名。正如[GLES30] p57中所述,GLSL ES 1.00着色器仍然可以使用别名,如WebGL 1.0规范中的“属性别名”部分所允许的。

5.18 PRIMITIVE_RESTART_FIXED_INDEX始终启用

在WebGL 2.0中不支持使用OpenGL ES 3.0中的Enable/Disable来控制的PRIMITIVE_RESTART_FIXED_INDEX上下文状态。相反,WebGL 2.0的行为就好像此状态始终已启用。这是与WebGL 1.0相比的兼容性差异。

当drawElements、drawElementsInstanced或drawRangeElements处理索引时,如果索引的值是数据类型的最大值(对于UNSIGNED_BYTE索引为255,UNSIGNED_SHORT为65535,UNSIGNED_INT为4294967295),则顶点不会正常处理。相反,就好像绘图命令以紧接其前面的顶点结束,并且另一个绘图命令立即以相同的参数启动,但只传输从原始指定的索引到最初指定的索引的末尾的索引。

为了避免基于Direct3D的WebGL实现中的性能问题,引入了这种兼容性差异。如果不需要原始重启行为,可以调整应用程序和内容创建工具,以避免使用最大顶点索引。

5.19 无纹理重排列

OpenGL ES 3.0引入了在纹理对象上设置四通道重排列操作的新状态,允许对引用该纹理的任何着色器内执行的每次纹理查找都进行重排列。这些纹理重排列在WebGL 2.0中不受支持。TEXTURE_SWIZZLE_*枚举值从WebGL 2.0 API中删除。

在基于Direct3D的WebGL实现中,无法以高性能方式实现纹理重排列。依赖此功能的应用程序在这些实现上将运行得更慢。应用程序仍然可以在着色器中重排纹理提取的结果,并且可以在上传纹理数据之前对纹理数据进行重排列,而无需使用此接口。

5.20 在链接失败的程序上应失败的查询

OpenGL ES 3.0允许应用程序在链接失败的情况下枚举和查询指定程序的活动变量和接口块的属性,即使该程序未链接成功(OpenGL ES 3.0.6 §2.12.3)。在WebGL中,这些命令将始终在链接失败的程序上生成INVALID_OPERATION错误,并且不返回任何信息。

在OpenGL ES 3.0中,返回的信息是实现相关的,可能是不完整的。添加了错误条件以确保在所有平台上都有一致的行为。

5.21 片段着色器中的颜色值必须匹配颜色缓冲区格式

片段着色器写入的颜色值可以是浮点数、有符号整数或无符号整数。如果片段着色器写入的值与相应颜色缓冲区的格式不匹配,在OpenGL ES 3.0中结果是未定义的(OpenGL ES 3.0.6 §3.9.2.3)。在WebGL中,在相应的绘图调用中,包括drawArrays、drawElements、drawArraysInstanced、drawElementsInstanced和drawRangeElements,会生成INVALID_OPERATION错误。

如果颜色缓冲区具有标准化的定点格式,浮点颜色值将被转换以匹配格式;在这种情况下不会生成错误。

5.22 纹理采样器类型必须匹配内部纹理格式

纹理查找函数根据传递给查找函数的采样器类型将值返回为浮点数、无符号整数或有符号整数。如果使用错误的采样器类型进行纹理访问,即采样器类型与纹理内部格式不匹配,返回的值在OpenGL ES Shading Language 3.00.6(OpenGL ES Shading Language 3.00.6 §8.8)中是未定义的。在WebGL中,在相应的绘图调用中,包括drawArrays、drawElements、drawArraysInstanced、drawElementsInstanced和drawRangeElements,会生成INVALID_OPERATION错误。

如果采样器类型为浮点数,而内部纹理格式为标准化整数,则视为匹配,返回的值会在范围[0, 1]内转换为浮点数。

5.23 查询结果不能在当前帧中提供

在OpenGL ES 3.0中,如果调用适当的原语(例如glFinish()或其他同步API),查询的结果可能在发出查询的同一帧中提供。在WebGL中,为了提高应用程序的可移植性,查询的结果必须在发出查询的同一帧中永远不会提供给应用程序。有关讨论和基本原理,请参阅getQueryParameter的规范。

5.24 GLSL ES 3.00 #extension指令位置

WebGL 1.0规范中的GLSL ES #extension指令位置仅适用于OpenGL ES Shading Language 1.00着色器。它不适用于使用OpenGL ES Shading Language 3.00编写的着色器。在使用OpenGL ES Shading Language 3.00编写的着色器中,#extension指令必须出现在非预处理令牌之前,无论扩展规范中写了什么。

这样做是为了使WebGL 2.0更接近已编写的GLSL ES 3.00规范。比本地GLES驱动程序更严格地执行限制,使行为变得明确定义。

5.25 仅支持uniform块中的std140布局

GLSL ES 3.00规范支持uniform块的shared、packed和std140布局限定符,定义了如何在统一缓冲区的存储中布局变量。在这些限定符中,WebGL 2.0规范仅支持std140布局,该布局在OpenGL ES 3.0.6 §2.12“顶点着色器”的子节“标准统一块布局”中定义。试图使用shared或packed布局限定符的着色器将无论是编译阶段还是链接阶段都会失败。

编译的初始状态就好像声明了以下内容:

layout(std140) uniform;

此限制的实施旨在通过避免暴露特定于某个供应商GPU的uniform块布局来提高可移植性。

5.26 不允许的GLSL ES 3.00运算符变体

在WebGL 2.0 API中,不允许使用以下着色语言结构,并且尝试使用它们必须导致编译错误:

  • 应用于void、数组或包含数组的结构的三元运算符
  • 应用于void、数组或包含数组的结构的序列运算符

此限制确保在支持OpenGL ES 3.0的设备之间实现轻松移植。

5.27 checkFramebufferStatus可能返回FRAMEBUFFER_INCOMPLETE_DIMENSIONS

所有附加的图像必须具有相同的宽度和高度;否则,checkFramebufferStatus将返回FRAMEBUFFER_INCOMPLETE_DIMENSIONS。

在OpenGL ES 3中,为帧缓冲附加的图像不需要具有相同的宽度和高度才能成为帧缓冲完整,FRAMEBUFFER_INCOMPLETE_DIMENSIONS不是checkFramebufferStatus的有效返回值之一。然而,在Direct3D 11中,在Windows中模拟OpenGL ES 3行为时,所有渲染目标必须在所有维度上具有相同的大小(请参阅msdn手册页)。在DirectX 11上模拟ES3语义将效率低下。为了在各个平台上实现一致的WebGL 2.0行为,保持WebGL 2.0对所有附加图像必须具有相同宽度和高度的限制是合理的。

5.28 uniform块匹配

在WebGL 2.0 API中,即使仅在非矩阵变量上独占应用,布局限定符row_major和column_major在匹配的uniform块中也必须匹配。

已知此uniform块匹配规则在OpenGL ES 3.0实现之间不一致。

5.29 使帧缓冲区失效后的帧缓冲内容

在OpenGL ES 3.0中,调用invalidateFramebuffer或invalidateSubFramebuffer后,受影响区域的内容变得实际上是未定义的。在WebGL 2.0中,内容要么保持不变,要么全部变为0。

对于WebGL 2.0实现来说,使invalidateFramebuffer或invalidateSubFramebuffer成为无操作是可以接受的。

5.30 不匹配纹理类型 FLOAT_32_UNSIGNED_INT_24_8_REV 的 ArrayBufferView

在使用ArrayBufferView的texImage2D和texImage3D中,如果类型为FLOAT_32_UNSIGNED_INT_24_8_REV且srcData不为null,则会生成INVALID_OPERATION错误。

在使用ArrayBufferView的texSubImage2D和texSubImage3D中,如果类型为FLOAT_32_UNSIGNED_INT_24_8_REV,则会生成INVALID_ENUM错误。

5.31 VertexAttrib函数必须与着色器属性类型匹配

如果满足以下任何情况之一,尝试使用drawArrays、drawElements、drawRangeElements或其实例化变体将生成INVALID_OPERATION错误:

  • 使用vertexAttribPointer、vertexAttrib{1234}f或vertexAttrib{1234}fv,并且槽索引处的着色器属性的基本类型不是浮点数(例如,是有符号或无符号整数);
  • 使用type为UNSIGNED_BYTE、UNSIGNED_SHORT或UNSIGNED_INT的vertexAttribIPointer,或使用vertexAttribI4ui或vertexAttribI4uiv,并且槽索引处的着色器属性的基本类型不是无符号整数(例如,是浮点数或有符号整数);
  • 使用type为BYTE、SHORT或INT的vertexAttribIPointer,或使用vertexAttribI4i或vertexAttribI4iv,并且槽索引处的着色器属性的基本类型不是有符号整数(例如,是浮点数或无符号整数)。

这个未定义的行为在OpenGL ES 3.0规范的第2.8节中(OpenGL ES 3.0.6 §2.8)。

5.32 Transform Feedback基元捕获

如果某个输出变量被指定为流式传送到缓冲对象,但实际上未被顶点着色器写入,则其值被设置为0。

这个未定义的行为在OpenGL ES 3.0规范的第2.15.2节中(OpenGL ES 3.0.6 §2.15.2)。

5.33 gl_FragDepth

如果片段着色器静态地为gl_FragDepth分配一个值,并且对于未执行分配给gl_FragDepth的语句的任何片段,将使用值0。

这个未定义的行为在OpenGL ES 3.0规范的第3.9.2节中(OpenGL ES 3.0.6 §3.9.2)。

5.34 帧缓冲颜色附件

如果一个图像附加到帧缓冲的多个颜色附件点,checkFramebufferStatus返回FRAMEBUFFER_UNSUPPORTED。一个图像可以是单个mip级别,一个数组切片(来自2D数组或立方体贴图),或一个3D纹理切片。

这是Direct3D 11的一个限制,在其上OpenGL ES 3行为在Windows上进行模拟。为了在所有平台上实现一致的WebGL 2.0行为,合理地在WebGL 2.0中添加这个限制。

5.35 从TexImageSource上传的像素存储参数

UNPACK_ALIGNMENT和UNPACK_ROW_LENGTH被忽略。UNPACK_ALIGNMENT以字节为单位指定,并且对于TexImageSource对象,它是隐式的,并且依赖于实现。UNPACK_ROW_LENGTH目前未使用。

可以使用UNPACK_参数来进行子矩形选择。UNPACK_SKIP_PIXELS和UNPACK_SKIP_ROWS确定子矩形的起点,而宽度和高度参数确定子矩形的大小。

对于3D纹理,宽度、高度和深度参数指定要解包到的纹素数组的矩形区域。UNPACK_SKIP_IMAGES和UNPACK_IMAGE_HEIGHT允许从2D源选择多个切片。UNPACK_IMAGE_HEIGHT确定两个切片之间的行距。例如,一个高度为30像素的TexImageSource可以通过使用高度等于10、UNPACK_IMAGE_HEIGHT设置为20和深度等于2进行上传,从而将顶部10行和底部10行上传到3D纹理的两个切片中。如果UNPACK_IMAGE_HEIGHT为0,则两个切片之间的行距默认为高度。

对于一个宽度为20像素的HTMLImageElement,传递width = 10的纹理上传将导致只选择图像的左半部分进行上传,从而生成纹理的宽度为10。在这个例子中,如果额外设置了UNPACK_SKIP_PIXELS为10,只有图像的右半部分会被选择进行解包。

此外,UNPACK_SKIP_IMAGES仅适用于3D入口点,而不适用于2D入口点。

例如,上面的32x48图像具有六种颜色,每种颜色的大小为16x16,它被上传到宽度=2、高度=1和深度=3的3D纹理中。

如果UNPACK_SKIP_PIXELS为0,UNPACK_SKIP_ROWS为0,UNPACK_IMAGE_HEIGHT为0,则整个纹素数组被设置为红色。 如果UNPACK_SKIP_PIXELS为16,UNPACK_SKIP_ROWS为16,UNPACK_IMAGE_HEIGHT为0,则整个纹素数组被设置为黄色。 如果UNPACK_SKIP_PIXELS为0,UNPACK_SKIP_ROWS为0,UNPACK_IMAGE_HEIGHT为16,则纹素数组的第一个切片为红色,第二个切片为蓝色,第三个切片为紫色。 如果UNPACK_SKIP_PIXELS为16,UNPACK_SKIP_ROWS为0,UNPACK_IMAGE_HEIGHT为16,则纹素数组的第一个切片为绿色,第二个切片为黄色,第三个切片为粉色。

5.36 像素存储参数的约束

定义:

DataStoreWidth := ROW_LENGTH ? ROW_LENGTH : width DataStoreHeight := IMAGE_HEIGHT ? IMAGE_HEIGHT : height 如果PACK_SKIP_PIXELS + width > DataStoreWidth,则readPixels生成INVALID_OPERATION错误。

如果UNPACK_SKIP_PIXELS + width > DataStoreWidth,那么texImage2D和texSubImage2D将生成INVALID_OPERATION错误。如果没有绑定PIXEL_UNPACK_BUFFER且srcData为null,则texImage2D不适用于此规则。

如果UNPACK_SKIP_PIXELS + width > DataStoreWidth或UNPACK_SKIP_ROWS + height > DataStoreHeight,那么texImage3D和texSubImage3D将生成INVALID_OPERATION错误。如果没有绑定PIXEL_UNPACK_BUFFER且srcData为null,则texImage3D不适用于此规则。

这些约束将这些参数的使用规范化为指定像素存储的子区域。例如,在readPixels的情况下,如果我们想将像素存储到整个数据存储的子区域中,可以使用PACK_ROW_LENGTH指定数据存储的宽度,并使用PACK_SKIP_PIXELS、PACK_SKIP_ROWS、width和height指定子区域的x偏移、y偏移、宽度和高度。

这些约束还禁止了行和图像的重叠,在OpenGL ES 3.0 DEQP测试套件中没有测试这些情况,许多驱动程序的行为是不正确的。它们还禁止跳过随机像素或行,但可以通过相应地调整数据存储偏移来实现。

此外,对于从TexImageSource上传的内容,隐含的UNPACK_ROW_LENGTH和UNPACK_ALIGNMENT并没有严格定义。这些限制确保在隐含的UNPACK_参数的情况下,无论如何都可以保持一致且高效的行为。

如果UNPACK_FLIP_Y_WEBGL或UNPACK_PREMULTIPLY_ALPHA_WEBGL设置为true,则如果它们从PIXEL_UNPACK_BUFFER上传数据,texImage2D和texSubImage2D将生成INVALID_OPERATION错误。

如果UNPACK_FLIP_Y_WEBGL或UNPACK_PREMULTIPLY_ALPHA_WEBGL设置为true,则如果它们从PIXEL_UNPACK_BUFFER或非null的客户端端ArrayBufferView上传数据,texImage3D和texSubImage3D将生成INVALID_OPERATION错误。

5.37 不支持ETC2和EAC压缩纹理格式

OpenGL ES 3.0要求支持以下ETC2和EAC压缩纹理格式:COMPRESSED_R11_EAC、COMPRESSED_SIGNED_R11_EAC、COMPRESSED_RG11_EAC、COMPRESSED_SIGNED_RG11_EAC、COMPRESSED_RGB8_ETC2、COMPRESSED_SRGB8_ETC2、COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2、COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2、COMPRESSED_RGBA8_ETC2_EAC和COMPRESSED_SRGB8_ALPHA8_ETC2_EAC。

这些纹理格式在WebGL 2.0中默认不受支持。

这些格式在大多数桌面GPU硬件上不受本地支持。因此,支持这些格式需要在WebGL实现或底层驱动程序中进行软件解压缩。这导致视频内存使用大幅增加,从而导致WebGL应用程序的性能损失,这对应用程序是不可见的。

在硬件原生支持ETC2和EAC压缩纹理格式的情况下(例如,移动OpenGL ES 3.0+硬件),它们可以通过扩展WEBGL_compressed_texture_etc来暴露出来。

5.38 UNIFORM_BUFFER_OFFSET_ALIGNMENT的值必须能被4整除

UNIFORM_BUFFER_OFFSET_ALIGNMENT的值,以基本机器单位表示,必须能被4整除。

如果UNIFORM_BUFFER_OFFSET_ALIGNMENT的值不能被4整除,则会使将ArrayBuffers上传到绑定了BindBufferRange的uniform缓冲区变得不实际。

5.39 同步对象的结果不能在当前帧中使用

在OpenGL ES 3.0中,如果调用了适当的原语(例如glFinish()或其他同步API),则同步对象可以在发出同步的同一帧中被信号化。在WebGL中,为了提高应用程序的可移植性,在发出同步的同一帧中,同步对象不能转换为信号状态。有关讨论和理由,请参见getQueryParameter和clientWaitSync的规范。

5.40 blitFramebuffer矩形宽度/高度限制

blitFramebuffer()的src和dst参数必须设置,以便源矩形和目标矩形的宽度和高度的结果小于或等于可以存储在GLint中的最大值。如果将任何宽度或高度值计算为GLint时会导致整数溢出,则blitFramebuffer()会生成INVALID_VALUE错误。

在大多数桌面OpenGL驱动程序上使用大于32位整数最大值大小的矩形进行blitFramebuffer会触发问题,在使用blitFramebuffer对帧缓冲进行缩放的情况下没有通用的解决方案。

5.41 GenerateMipmap需要正的图像尺寸

generateMipmap要求TEXTURE_BASE_LEVEL的尺寸都是正数。

尽管GLES 3.0.6在技术上允许在0x0图像上调用GenerateMipmap,但是立方体贴图必须是立方体完全的,因此具有正的尺寸。 此更改通过允许纹理的基本级别完整性的概念来简化实现,否则需要进行非Mipmap采样验证。由于GenerateMipmap对0x0纹理没有影响,并且在WebGL 1中是不合法的(0不是2的幂),因此很容易添加这个限制。此外,GenerateMipmap将成为唯一一个必须在未定义的纹理图像上操作的入口点,从而跳过了一个常见的验证步骤。

5.42 deleteQuery在查询处于活动状态时隐式调用endQuery

在GLES中,DeleteQueries不会隐式结束查询,即使它们是活动的。

这个偏差最初没有被明确规定,但是通过一致性测试,它在各个浏览器之间被隐式标准化。一些实现发现这种行为更容易实现。将此行为恢复以匹配GLES规范可能会破坏内容,而且在这个阶段更好的是规范我们所实现的内容。

5.43 必需的压缩纹理格式

实现必须至少支持一组压缩纹理格式。

实现必须支持:

WEBGL_compressed_texture_etc AND/OR ( WEBGL_compressed_texture_s3tc AND WEBGL_compressed_texture_s3tc_srgb AND EXT_texture_compression_rgtc ) 为了最好地支持我们的生态系统,我们要求实现支持ETC2/EAC格式(在GLES3或类似的驱动程序上是通用的,例如许多手机)或S3TC格式(在所有其他驱动程序上是通用的)。这确保作者在所有设备上都可以始终使用压缩纹理(包括srgb变体),同时仅维护对两种不同格式的支持。

每个套件中大致等效的格式如下:

用途S3TC/RGTC选项(桌面)ETC2/EAC选项(移动)
R11 unsignedCOMPRESSED_RED_RGTC1_EXTCOMPRESSED_R11_EAC
R11 signedCOMPRESSED_SIGNED_RED_RGTC1_EXTCOMPRESSED_SIGNED_R11_EAC
RG11 unsignedCOMPRESSED_RED_GREEN_RGTC2_EXTCOMPRESSED_RG11_EAC
RG11 signedCOMPRESSED_SIGNED_RED_GREEN_RGTC2_EXTCOMPRESSED_SIGNED_RG11_EAC
RGB8 unsignedCOMPRESSED_RGB_S3TC_DXT1_EXTCOMPRESSED_RGB8_ETC2
RGB8 sRGBCOMPRESSED_SRGB_S3TC_DXT1_EXTCOMPRESSED_SRGB8_ETC2
RGB8 punchthrough unsignedCOMPRESSED_RGBA_S3TC_DXT1_EXTCOMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
RGB8 punchthrough sRGBCOMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXTCOMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
RGBA8 unsignedCOMPRESSED_RGBA_S3TC_DXT5_EXTCOMPRESSED_RGBA8_ETC2_EAC
RGBA8 sRGBCOMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXTCOMPRESSED_SRGB8_ALPHA8_ETC2_EAC

5.44 例如,sampler2DShadow不能保证使用LINEAR过滤

当TEXTURE_COMPARE_MODE设置为COMPARE_REF_TO_TEXTURE时,即使使用了所需的扩展LINEAR过滤,纹理始终是完整的。然而,使用LINEAR过滤时是否发生是由实现定义的。(实现可能会使用NEAREST采样)

这个功能在GLES中的规范不够详细。这是常见但不是普遍的。我们在这里选择保守,尽管实现可能会对请求此功能的情况发出警告。

5.45 常量混合颜色受限

如果底层平台对常量混合颜色进行了限制,实现可以在存储时对常量混合颜色进行限制。应用程序可以查询BLEND_COLOR参数以检查有效的行为。

5.46 通用TRANSFORM_FEEDBACK_BUFFER状态位置

TRANSFORM_FEEDBACK_BUFFER通用缓冲绑定点已从每个对象状态移动到上下文状态。

类似的更改已在OpenGL ES 3.2中进行了。