在没有上下文的情况下访问 WebGL constants/enums

Access WebGL constants/enums without context

我觉得很奇怪,所有的WebGL常量都被定义为渲染上下文的成员。这意味着如果上下文被包装在某个库中,访问这些常量就会出现问题。

我有什么理由不能明确定义它们吗?或者,如果它们是实现定义的,也许是第一次创建上下文时,将所有枚举值写入某个全局对象?

基本上,我不想写 new renderer.Texture(renderer.gl.TEXTURE_2D)new renderer.Texture("TEXTURE_2D"),而是想写 new renderer.Texture(WebGL.TEXTURE_2D).

您可以自由地将它们定义为您自己的常量。事实上,它可能会使您的代码更快

const TEXTURE_2D = 0x0DE1
...
gl.bindTexture(TEXTURE_2D, someTexture);

完全没问题。而且,如果该代码是 运行 通过现代 JavaScript 压缩器,它将变成这个

gl.bindTexture(0x0DE1, someTexture);

这可以说会更快。比 gl.TEXTURE_2D 更快,因为使用 gl.TEXTURE_2D JavaScript 引擎必须始终检查是否有人没有将 gl.TEXTURE_2D 分配给其他东西。比 TEXTURE_2D 快,因为即使是 const 变量也代表正在创建的东西,而 0x0DE1 绝对不会。

只是因为稍后我可能会收到一些问题,我上面关于速度的观点是 JavaScript 引擎必须在您每次调用时检查

 gl.bindTexture(gl.TEXTURE2D, ...)

某处有人没有做

 gl.TEXTURE_2D = 123

或属性getter

 Object.defineProperty(gl, 'TEXTURE_2D', {
   enumerable: true,
   writable: false,
   get() {
     console.log('TEXTURE_2D was accessed at', (new Error()).stack));
     return 0xDE1;
   }
 });

JavaScript 引擎无法假定 TEXTURE_2D 属性 未更改。每次都要检查。

至于 const 可能存在也可能没有一般速度差异,但是例如,如果我们创建一个函数 returns 像这样的函数

function makeFuncThatReturnsValue(value) {
  const v = value;
  return function() {
    return v;
  }
}

我们可以看到每次调用makeFuncThatReturnsValue都会在闭包中创建并捕获一个新的v

直接使用文字不会有这个问题,不会创建任何东西。当然你不想直接使用文字,幻数是不好的,但如果你用现代压缩器编译你的 JavaScript 它会在适当的地方将任何 const 换成文字。

运行一个例子通过Google's closure compiler

代码:

const w = {
  TEXTURE_2D: 0x0DE1,
};

gl.bindTexture(w.TEXTURE_2D, null);

Result:

gl.bindTexture(3553,null);

您可以使用 WebGLRenderingContextWebGL2RenderingContext 访问它们,而无需创建上下文实例。例如:

console.log(WebGLRenderingContext.TEXTURE_2D); // 3553