【发布时间】:2019-02-11 15:38:38
【问题描述】:
我正在使用昂贵的海洋着色器 (https://threejs.org/examples/webgl_shaders_ocean.html),它会破坏旧移动设备的用户体验(帧速率从 60fps 下降到 20fps)。如果在渲染器上设置较低的像素比(2 而不是 3),我可以获得双倍的 FPS(大约 40fps)。我还以编程方式将画布大小减小到 50%,然后通过 CSS 将其增大以填充屏幕但分辨率较低。
这两个操作是我现在可以做的最好的事情来提高性能。但是成本很高,因为我不仅在海洋中,而且在场景中涉及的所有其他模型中都失去了很多分辨率。
我正在寻找一种方法以低分辨率渲染昂贵的部分(如此着色器材质),以在渲染后恢复它,我的意思是:在海洋网格平面上定义 onBeforeRender 以便我可以将分辨率降低到 1 /3,例如。然后,在渲染完网格之后,我可以使用 onAfterRender 来恢复原来的像素比例。我可以毫无问题地降低 onBeforeRender 的分辨率,但是当我在 AfterRender 上恢复原始的高质量分辨率时,屏幕变黑了。这些是我对https://threejs.org/examples/js/objects/Water.js的更改
scope.onBeforeRender = function ( renderer, scene, camera ) {
(original onBeforeRender code)
renderer.setPixelRatio( 0.5 );
renderer.render( scene, mirrorCamera, renderTarget, false );
};
scope.onAfterRender = function ( renderer, scene, camera ) {
renderer.setPixelRatio( 2 );
};
我想知道这个策略是否正确。我至少在正确的道路上吗?这是一个基本的 JSFiddle 来说明这个问题。有一个名为“overrideFunctions()”的方法,它重新定义了 Water.js onBeforeRender() 以在渲染海洋之前降低像素比率。然后,我们定义“onAfterRenderer()”来恢复原始质量,以便模型可以在高分辨率上渲染。
https://jsfiddle.net/spacorum/y5398gLm
注释了三行。如果取消注释第 168 行,全局质量将降低到仅 0.25dpi。这没关系,但是如果您随后取消注释第 174 行,模型就会消失,天空呈现黑色......并且画布太小了。在渲染海洋之前,我也尝试过您的建议 renderer.clear() ,但现在没有任何区别。这么近。。
编辑 3:这是我最接近的展示我需要的东西。海洋的孤立、低分辨率版本,包括反射。如果我能设法以正常分辨率显示其余部分,那就可以做到: https://jsfiddle.net/spacorum/f63z2ceg/
编辑 4: 只是尝试使用不同的技术:主场景和背景场景。我最近已经尝试过类似的东西,但我被卡住了。在这个测试中,我设法显示了一个低分辨率版本的大海,将其背景场景渲染到 WebGLRenderTarget(仅使用窗口大小的 1/10)。它似乎有所改善,但我不确定计算是否相同,我只是以较低的分辨率显示它。无论如何,按照这种方式,我无法让球体看到海内(我想这很正常,因为它们在不同的场景中,对吧?)。 renderer.clearDepth 能以某种方式帮助这里吗? https://jsfiddle.net/spacorum/wbtcx9re/
EDIT 5:我的最新方法,混合 EDIT3 和 EDIT4。有两个场景,海洋/太阳添加到背景/次要场景和球体添加到主要场景。在不执行任何 renderer.clear() 并将 renderer.autoClear 设置为 false 的情况下,我可以渲染两个场景,并且球体“进入”添加到辅助场景的海洋,到目前为止一切都很好。 (当然还没有反射,但我可以解决这个问题,将球体的副本添加到次要场景)。然后,我可以在渲染次要场景之前降低分辨率(第 166 行)。但是如果我稍后恢复它以使球体以原始分辨率渲染(取消注释第 173 行),第一个场景消失并呈现白色。我不明白为什么两次更改分辨率会导致这种情况,我可能忘记更新后面的东西,但我看不到它:/ https://jsfiddle.net/spacorum/o91se8fz/
【问题讨论】:
标签: performance mobile three.js render resolution