从r112开始,默认的MeshStandardMaterial(在这种情况下,特别是加载glTF文件时使用的,但也可能在其他情况下使用)在某些GPU上显示出条带失真。 具体来说,我在Pixelbook和每一代Pixel手机上都看到了这个问题。 我尝试过的Nvidia台式机GPU或Oculus Go或Oculus Quest都不会发生此问题。
还应该注意的是,对于我在各种移动设备上的特定应用程序(包括那些没有呈现伪影的设备),相对于r111而言,我已经观察到该材质的新着色器对性能产生了显着影响。
工件看起来像这样(在Pixelbook上用Three.js r112渲染)
预期的输出看起来像这样(在同一Pixelbook上用Three.js r111渲染)
实时链接,当前使用r112: https ://xrdinosaurs.com
该页面上的所有恐龙都表现出该问题,但是具有大面积平坦或平滑颜色的恐龙(例如TRex的腹部)往往会更加突出。
屏幕截图中的材质(下面完整粘贴)使用glTF扩展名“ KHR_materials_pbrSpecularGlossiness”,并具有漫反射,法线和镜面/光泽度纹理。
{
"doubleSided": true,
"emissiveFactor": [
0,
0,
0
],
"extensions": {
"KHR_materials_pbrSpecularGlossiness": {
"diffuseFactor": [
0.46512957319999998,
0.46512957319999998,
0.46512957319999998,
1
],
"diffuseTexture": {
"index": 4,
"texCoord": 0
},
"glossinessFactor": 0.27610518290000002,
"specularFactor": [
0.92244664629999995,
0.92244664629999995,
0.92244664629999995
],
"specularGlossinessTexture": {
"index": 6,
"texCoord": 0
}
}
},
"name": "TRex",
"normalTexture": {
"index": 5,
"scale": 1,
"texCoord": 0
}
}
我可以确认我的Pixel(1)上有问题。 但是,仅在使用KHR_materials_pbrSpecularGlossiness
时才出现伪像。
GLTFLoader
将lights_physical_fragment
着色器块的代码替换为以下内容:@toji您可以通过将上面的代码替换为:来修改应用程序的GLTFLoader
副本吗?
var lightPhysicalFragmentChunk = [
'PhysicalMaterial material;',
'material.diffuseColor = diffuseColor.rgb;',
'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );',
'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',
'material.specularRoughness = max( 1.0 - glossinessFactor, 0.0525 );// 0.0525 corresponds to the base mip of a 256 cubemap.',
'material.specularRoughness += geometryRoughness;',
'material.specularRoughness = min( material.specularRoughness, 1.0 );',
'material.specularColor = specularFactor.rgb;',
].join( '\n' );
@elalish即使此修补程序不能解决问题,在任何情况下都应将其添加到GLTFLoader
,对吗?
@ Mugen87是的,可以肯定。 我会看看我是否也可以在Pixel 3上进行再现。
@toji我没有在Android 10的Pixel 3上进行所有Pixels ...
驱动程序错误? 我不确定是哪条线触发了它。 我敢肯定,几何抗锯齿的存在/不存在都不会使这种伪像成为可能。
@toji我还尝试了专用的
gh,天黑了实际上意味着PMREM生成完全失败了,这是由于发现了这个怪异的错误和解决方法: https :
我在Chrome和Firefox上在OnePlus 5T上重现了OP的错误。
谢谢! 将补丁应用到GLTFLoader
,观察到条带伪影减少了,但没有消除。
补丁之前:
修补后:
基本上,它看起来像固定了其中一个乐队。 :)(屏幕截图是在Pixelbook上拍摄的,但在Pixel 4 XL上也观察到了。目前,我身上没有其他测试设备。)
很高兴修补您要测试的任何其他更改,或者如果要在本地进行测试,可以查看https://github.com/toji/xr-dinosaurs 。 (不需要任何服务器组件。)
至于性能:并非完全黄油,但也不错。
谢谢。 😁努力工作。 在这种情况下,在更新到r112的过程中,我注意到了perf回归并询问@mrdoob 。 他建议这可能是新的,更准确的标准着色器,并建议将某些材质替换MeshLambertMaterial
进行验证。 由于无论如何环境模型都没有正确配置PBR材质,因此我将其强制放到Lambert并留在了那里,这又获得了perf回归,然后又恢复了一些(因为它占用了很大的视口)。标准材料,因为它们是“英雄”资产。
旁注:由于渲染器检查MeshStandardMaterial
当GLTFLoader
使用镜面/光泽度材料加载网格时, Scene.environment
当前不起作用。
但是, GLTFLoader
ShaderMaterial
为每种高光/光泽度材质创建一个
当不使用环境贴图时,我无法重现条带伪像。 在像素(1)上,通过简单的照明设置(如环境光和点光源),一切看起来都不错。
嗯,使用环境图似乎对物理材料存在更多问题。 查看以下示例在Android 10 Pixel 1上的外观。
https://threejs.org/examples/webgl_materials_envmaps_exr
https://threejs.org/examples/webgl_materials_physical_clearcoat
https://threejs.org/examples/webgl_materials_envmaps_hdr
我无法在iMac上复制这些工件。
我的机器上发生了一件很奇怪的事情,我能够在所有使用新PMREMGenerator
示例中重现这些工件。 但是只有在本地运行它们时; 在线查看它们时(来自threejs.org页面),它们都显示正确。
我从未遇到过这样的问题,我完全不知道是什么原因引起的。
我正在使用GeForce GTX 750 TI运行Windows 10,所以我认为这不是特定于设备的问题。
但是只有在本地运行它们时; 在线查看它们时(来自threejs.org页面),它们都显示正确。
请注意, dev
版本具有prod
尚不存在的更改。 能否请您检查当前的master
分支,然后执行本地测试?
您能检出当前的master分支,然后执行本地测试吗?
注意到这种行为后,我尝试过的第一件事是相同的结果。 真的很好奇。
您可以使用隐身窗口进行测试吗? 有时可能会缓存内容,或者浏览器扩展会干扰,这可能确实令人困惑
尝试隐身,结果相同:(
我相信我知道为什么会发生这种结合。
在生成Mip的过程中,我的本地(不正确)版本正在创建黑带,而该黑带在实时版本中不存在。
这也会复制到较低的Mip级别。
这可能是由于某些不正确的坐标采样而发生的,我已经尝试过手动禁用各向异性过滤,但是问题仍然存在。 很难准确指出正在发生的事情,尤其是因为我无法确定为什么它在同一台计算机上表现出两种不同的行为。
@elalish在多个示例上进行了一些测试之后,我能够查明这些工件的实际原因。 与我在上一篇文章中所说的相反,问题的根本原因与坐标采样不正确有关,而是与PMREMGenerator
处理devicePixelRatio
。
在具有标称浮点pixelRatio
我们在生成的纹理上得到了“坏”的mipmap坐标。 因此,存在小的差距和重叠的区域。 我还发现我的机器具有不同的devicePixelRatios
这取决于我是在本地(0.899 ..)还是在线(1)上查看示例,这就是为什么我仅在本地查看这些工件。
我通过禁用setPixelRatio
设置了一个简单的测试,它似乎可以解决问题,如果其他情况如此,那么最好重构PMREMGenerator
处理它的方式。
@toji @ plut0nist会在提供这些工件的设备上检查以下示例吗?
@sciecode非常感谢您找出根本原因! 我看看是否可以解决问题。
@sciecode :已在我的设备上验证。 DEV示例测试在环境图中显示出非常明显的黑线,而TEST示例则没有。 很棒的调试,谢谢!
我很好奇为什么为什么PMREMGenerator
需要占devicePixelRatio
,所以我开始挖掘。 事实证明,这是因为renderer.setViewport()
自动将DPR转换为您发送的任何值,这似乎很明显是默认目标帧缓冲区以外的渲染目标的错误行为,默认目标帧缓冲区分配的像素值不正确占所有像素的比例。 我建议这里的“正确”行为是内部rendere.setViewport()
应该使用getTargetPixelRatio()
,当活动渲染目标不是默认值时,它将返回1
。 不过,我绝对可以看到这会带来向后兼容的问题。
最有用的评论
@elalish在多个示例上进行了一些测试之后,我能够查明这些工件的实际原因。 与我在上一篇文章中所说的相反,问题的根本原因与坐标采样不正确有关,而是与
PMREMGenerator
处理devicePixelRatio
。在具有标称浮点
pixelRatio
我们在生成的纹理上得到了“坏”的mipmap坐标。 因此,存在小的差距和重叠的区域。 我还发现我的机器具有不同的devicePixelRatios
这取决于我是在本地(0.899 ..)还是在线(1)上查看示例,这就是为什么我仅在本地查看这些工件。我通过禁用
setPixelRatio
设置了一个简单的测试,它似乎可以解决问题,如果其他情况如此,那么最好重构PMREMGenerator
处理它的方式。@toji @ plut0nist会在提供这些工件的设备上检查以下示例吗?
DEV示例
测试例