2014-03-26 74 views
2

我试图使用THREE.js实现路径跟踪器。我基本上是渲染一个全屏四边形,并且路径追踪发生在像素着色器中。与Three.js的积累着色器

我想要一个更高的采样率,一种方法是为每个像素采样一个路径并累加生成的图像。 (即平均每个着色器通道获得的图像)

因为它是我能够生成我需要的图像,但我不知道如何积累它们。我的猜测是我必须使用两个渲染目标;一个会包含“最新”的采样图像,一个会包含目前显示的所有图像的平均值。

我只是不知道如何从WebGLRenderTarget获取数据并使用它来操纵另一个渲染目标中包含的数据。这甚至有可能是Three.js可能的吗?我一直在研究FrameBuffer Objects,这看起来像是一个很有前途的路径,我正在梳理MrDoob的FBO例子(http://www.mrdoob.com/lab/javascript/webgl/particles/particles_zz85.html),它看起来很有前途,但我不确定我是否走向了正确的道路。

+0

请参阅http://threejs.org/examples/webgl_gpgpu_birds.html。它展示了两个渲染目标之间乒乓球的例子。 – WestLangley

回答

2

我认为问题是你不能从同一个缓冲区读写。假设你渲染一帧图像,你需要一个输出到累积缓冲区的通道。下一帧,你需要做你的计算,并保存到同一个缓冲区,但如果我理解正确,这对目前的WebGL是不可能的。

你可以做的是有两个缓冲区。在着色器中,您将东西输出到缓冲区并进行计算,只需添加另一个纹理采样器,从前一帧读取一个,保存到下一个纹理采样器,然后交替。你将始终拥有你的累计值,你可以使用任何你想添加的数学,但是你需要确保你正在正确的帧读取正确的缓冲区。

three.js有一个用于后期处理的插件,这对于做这样的事情应该非常方便。

var flipFlop = true; 
var buffer1 = THREE.WebGLRenderTarget(BUFFERSIZE, BUFFERSIZE, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, type: THREE.FloatType}); 
var buffer2 = THREE.WebGLRenderTarget(BUFFERSIZE, BUFFERSIZE, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, type: THREE.FloatType}); 


function render() { 
    // If we are in frame1 read buffer from frame0 and add it to whatever you compute 
    yourComputeShaderMaterial.uniforms._accumulationBuffer.value = flipFlop ? buffer2 : buffer1; 

    if (flipFlop) // Frame 0 
     renderer.render(scene, camera, buffer1); 
    else // Frame 1 
     renderer.render(scene, camera, buffer2); 

    // Get whatever just renderered in this frame and use it 
    yourEndShader.uniforms._accumulationBuffer.value = !flipFlop ? buffer2 : buffer1; 

    // Switch frame 
    flipFlop = !flipFlop; 
} 
+0

感谢您的好评。最后我用纯WebGL重新实现了整个事物,你可以在http://tinyurl.com/k7adpb6看到结果! – XenoChrist

+0

甜蜜的演示,这是从一个特定的教程? – pailhead

+0

不是真的,只是基于简单的路径跟踪算法和其他教程/示例,我可以找到网络。整个事情是相当彻底的评论,所以不要犹豫,通过源头看! – XenoChrist