【发布时间】:2021-03-03 04:24:08
【问题描述】:
我在三个场景(使用 AFrame)中需要环境映射来进行照明。使用标准 HDR 立方体贴图,我得到以下结果:
就基于粗糙度的模糊而言,这是正确的,因为我生成了 mipmap,并且 minFilter 设置为 LinearMipmapLinearFilter。这种方法的问题是没有应用环境照明——场景中的光,定向光,是唯一向场景提供任何照明信息的东西。不幸的是,无论 HDRI 有多亮,这都会导致完全黑色的阴影。
但是,如果除了上述之外,我还使用 Three 的 PMREMGenerator,环境照明问题就解决了。不幸的是,结果就是这样:
如图所示,纹理过滤现在已经不正常了。根据 PMREMGen 脚本本身留下的 cmets。
这个类从 cubeMap 环境纹理生成一个预过滤的 Mipmapped Radiance Environment Map (PMREM)。这允许根据材料粗糙度快速访问不同级别的模糊。它被打包成一种特殊的 CubeUV 格式,允许我们执行自定义插值,以便我们可以支持非线性格式,例如 RGBE。与传统的 mipmap 链不同,它只会在相同 LOD_MIN 分辨率下下降更多过滤的“mips”,并与更高的粗糙度级别相关联。通过这种方式,我们可以在限制采样计算的同时保持分辨率以平滑地插入漫反射光照。
...这让我相信输出应该被平滑,就像我的第一个例子一样。
这是第一个示例的代码:
const ctl = new HDRCubeTextureLoader();
ctl.setPath(hdrPath);
ctl.setDataType(THREE.UnsignedByteType);
const hdrUrl = [
`${src}/px.hdr`,
`${src}/nx.hdr`,
`${src}/py.hdr`,
`${src}/ny.hdr`,
`${src}/pz.hdr`,
`${src}/nz.hdr`
];
const hdrSky = ctl.load(hdrUrl, tex => this.skies[src] = hdrSky );
// Then later...
obj.material.envMap = this.skies[this.skySources[index]];
obj.material.needsUpdate = true;
这是第二个示例的代码:
const ctl = new HDRCubeTextureLoader();
ctl.setPath(hdrPath);
ctl.setDataType(THREE.UnsignedByteType);
const hdrUrl = [
`${src}/px.hdr`,
`${src}/nx.hdr`,
`${src}/py.hdr`,
`${src}/ny.hdr`,
`${src}/pz.hdr`,
`${src}/nz.hdr`
];
const pmremGen = new PMREMGenerator(this.el.sceneEl.renderer);
pmremGen.compileCubemapShader();
const hdrSky = ctl.load(hdrUrl, tex => {
const hdrRenderTarget = pmremGen.fromCubemap(hdrSky);
this.skies[src] = hdrRenderTarget.texture;
});
// Then later...
obj.material.envMap = this.skies[this.skySources[index]];
obj.material.needsUpdate = true;
我似乎在过滤方面碰壁了。即使我在 PMREMGenerator.js 中显式更改过滤类型并打开 mipmap 生成,结果似乎也是一样的。这是一个使用 PMREMGenerator 没有任何问题的官方示例:https://threejs.org/examples/webgl_materials_envmaps_hdr.html
作为结束语,我会注意到我们正在使用 Three.js r111(并且有一些原因我们无法完全将其关闭),所以我从最新版本的 Three 中引入了当前版本的 PMREMGenerator在撰写本文时(r122 - 需要更高版本,因为 r111 的编写方式完全不同)。因此,如果这一切都是由版本之间的某些冲突引起的,我不会感到惊讶。
编辑:只需将生成的 envmap 作为标准地图放在某些平面上,令我惊讶的是,甚至没有一个模糊的 LODS 出现。这是我的样子:
它应该是这样的(不要介意圆环结):
编辑:我现在找到了一种解决方法(基本上,不使用 PMREMGenerator),但如果发现解决方案,我会保留它。
【问题讨论】:
-
你能上传它吗?我无法使用 Threejs 示例 hdrs 复制它(我尝试过 here)
-
遗憾的是,这个项目太大而无法上传到故障(它使用 Mozilla Hubs:github.com/mozilla/hubs)。我怀疑这个问题与多个脚本中的各种不匹配的三个版本有关是原因。完全复制问题可能需要复制整个环境(我意识到这对于在线请求帮助并不是特别好——但无论如何我还是这样做了,以防我遗漏了一些明显的东西)。目前,我通过不使用 PMREMGenerator 并直接应用我的立方体贴图来解决这个问题。