Threejs:网格标准 material 反射问题

Threejs: mesh standard material reflection issues

我偶然发现了一些浏览器和设备呈现 MeshStandardMaterial 反射效果不佳的问题。

考虑下面的 example

this example 下面:

两次比较都是运行同时在同一台电脑上,同样的显卡,相同的属性,但是不同的浏览器。可以看到,右边的倒影几乎无法辨认。

此外,我在锐角处遇到了一些三角测量问题,这使得反射看起来好像是在顶点着色器中计算的:

我了解不同的浏览器具有不同的 WebGL 功能,如 http://webglreport.com/ 上的结果所示:

有人知道 IE/Edge 浏览器缺少哪些 WebGL 扩展或功能,我可以寻找吗?如果不满足必要的要求,我想放置一个使用不同 material 的嗅探器。或者,如果有人有完整的解决方案,那就更好了。我已经尝试使用 EnvMap 的 minFilter 属性,但反射的计算方式仍然不同。

我不知道需要哪些扩展,但您可以轻松测试。在你初始化之前 THREE.js 放一些像这样的代码

const extensionsToDisable = [
  "OES_texture_float", 
  "OES_texture_float_linear",
];

WebGLRenderingContext.prototype.getExtension = function(oldFn) {
  return function(extensionName) {
    if (extensionsToDisable.indexOf(extensionName) >= 0) {
      return null;
    }
    return oldFn.call(this, name);
  };
}(WebGLRenderingContext.prototype.getExtension);

WebGLRenderingContext.prototype.getSupportedExtensions = function(oldFn) {
  return function() {
    const extensions = oldFn.call(this);
    return extensions.filter(e => extensionsToDisable.indexOf(e) < 0);
  };
}(WebGLRenderingContext.prototype.getSupportedExtensions);

然后选择性地禁用扩展,直到 Firefox/Chrome 看起来与 IE/Edge 相同。

我要测试的第一件事是禁用 Chrome/Firefox 中不在 IE/Edge 中的每个扩展,只是为了验证将它们全部关闭是否会重现 IE/Edge 行为。

如果它确实重现了问题,那么我会进行二进制搜索(打开一半禁用的扩展),然后重复直到找到所需的。

const extensionsToDisable = [
  "EXT_blend_minmax",
  "EXT_disjoint_timer_query",
  "EXT_shader_texture_lod",
  "EXT_sRGB",
  "OES_vertex_array_object",
  "WEBGL_compressed_texture_s3tc_srgb",
  "WEBGL_debug_shaders",
  "WEBKIT_WEBGL_depth_texture",
  "WEBGL_draw_buffers",
  "WEBGL_lose_context",
  "WEBKIT_WEBGL_lose_context", 
];

WebGLRenderingContext.prototype.getExtension = function(oldFn) {
  return function(extensionName) {
    if (extensionsToDisable.indexOf(extensionName) >= 0) {
      return null;
    }
    return oldFn.call(this, name);
  };
}(WebGLRenderingContext.prototype.getExtension);

WebGLRenderingContext.prototype.getSupportedExtensions = function(oldFn) {
  return function() {
    const extensions = oldFn.call(this);
    return extensions.filter(e => extensionsToDisable.indexOf(e) < 0);
  };
}(WebGLRenderingContext.prototype.getSupportedExtensions);

const gl = document.createElement("canvas").getContext("webgl");
console.log(gl.getSupportedExtensions().join('\n'));
console.log("WEBGL_draw_buffers:", gl.getExtension("WEBGL_draw_buffers"));