首页 > 解决方案 > 以较低的分辨率渲染一些内容

问题描述

我正在使用昂贵的海洋着色器(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/

在此处输入图像描述


编辑 5:我最新的方法,混合 EDIT3 和 EDIT4。有两个场景,海洋/太阳添加到背景/次要场景和球体添加到主要场景。在不执行任何 renderer.clear() 并将 renderer.autoClear 设置为 false 的情况下,我可以渲染两个场景,并且球体“进入”添加到辅助场景的海洋,到目前为止一切都很好。(当然还没有反射,但我可以解决这个问题,将球体的副本添加到次要场景)。然后,我可以在渲染次要场景之前降低分辨率(第 166 行)。但是如果我稍后恢复它以使球体以原始分辨率渲染(取消注释第 173 行),第一个场景消失并呈现白色。我不明白为什么两次更改分辨率会导致这种情况,我可能忘记更新后面的东西,但我看不到它:/ https://jsfiddle.net/spacorum/o91se8fz/

在此处输入图像描述

标签: performancemobilethree.jsrenderresolution

解决方案


海洋渲染缓慢的部分原因是环境立方体贴图的每帧重建。如果您没有靠近水的物体不断变化,您可能只需偶尔更新一次环境地图,或者当您切换天空或其他东西时更新一次。

编辑:只需重新阅读您的问题..您可能走在正确的道路上。您需要自己控制帧缓冲区的清除。设置renderer.autoClear = false,并在渲染缩小的海洋之前调用renderer.clear()。否则,三在渲染海洋后自动清除缓冲区。@spacorum

如果您不需要每帧完整的 envmap 重建,我最初的答案也可能仍然适用,并允许您以全分辨率渲染水。


推荐阅读