我已经调整了这个后处理示例http://mrdoob.github.com/three.js/examples/webgl_postprocessing_dof.html以应用景深/散景效果。如何指定焦点范围(或任何可以调用的范围)?
如果相机远平面为 10000,而模型尺寸为 10,则无法聚焦到模型的各个部分 - 因为它试图从 1-10000(近相机到远相机)而不是 1-10 聚焦(在相机和我的模型背面之间),实际感兴趣的区域。
在我意识到将相机远平面设置得尽可能低(与场景大小大致相同)之后,它确实工作正常,因此可以在实际模型所在的位置调整焦点。
现在我不能再做相机远平面的技巧了,因为我添加了一个天空盒,所以相机需要让它的远平面与模型尺寸有很大的关系。这会破坏景深;我可以聚焦很近或很远,但整个模型要么完全模糊,要么根本不模糊,因为可调节距离太大(一直到天空盒)。
如果我知道我想要关注的领域,我如何在我的代码中指定它?
这是我的设置代码:
dof_material_depth = new THREE.MeshDepthMaterial();
dof_scene = new THREE.Scene();
dof_camera = new THREE.OrthographicCamera(SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, -10000, 10000 );
dof_camera.position.z = 100;
dof_scene.add( dof_camera );
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
dof_rtTextureDepth = new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, pars );
dof_rtTextureColor = new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, pars );
dof_bokeh_shader = THREE.BokehShader;
dof_bokeh_uniforms = THREE.UniformsUtils.clone(dof_bokeh_shader.uniforms );
dof_bokeh_uniforms[ "tColor" ].value = dof_rtTextureColor;
dof_bokeh_uniforms[ "tDepth" ].value = dof_rtTextureDepth;
dof_bokeh_uniforms[ "focus" ].value = 1.1;
dof_bokeh_uniforms[ "aspect" ].value = SCREEN_WIDTH / SCREEN_HEIGHT;
dof_materialBokeh = new THREE.ShaderMaterial( {
uniforms: dof_bokeh_uniforms,
vertexShader: dof_bokeh_shader.vertexShader,
fragmentShader: dof_bokeh_shader.fragmentShader
});
dof_quad = new THREE.Mesh( new THREE.PlaneGeometry(SCREEN_WIDTH, SCREEN_HEIGHT), dof_materialBokeh );
dof_quad.position.z = -500;
dof_scene.add(dof_quad );
这里是渲染部分:
renderer.render(scene, camera, dof_rtTextureColor, true );
scene.overrideMaterial = dof_material_depth;
renderer.render(scene, camera, dof_rtTextureDepth, true );
dof_scene.overrideMaterial = null;
render(dof_scene, dof_camera );
var delta = 0.01;
composerScene.render( delta);
编辑:
通过在渲染深度材质之前为相机设置一个低远平面,然后在渲染合成之前恢复正常,我确实设法获得了预期的结果:
renderer.render(scene, camera, dof_rtTextureColor, true );
var oldfar = camera.far; // this goes to skybox
camera.far = scenesize; // this goes to just behind the model
scene.overrideMaterial = dof_material_depth;
renderer.render(scene, camera, dof_rtTextureDepth, true );
camera.far = oldfar;
dof_scene.overrideMaterial = null;
render(dof_scene, dof_camera );
var delta = 0.01;
composerScene.render( delta);
这很完美。不过,我会留下这个问题,因为我对 WebGLL / 3D 编程很陌生,想学习,并且想知道是否可以在着色器/材质设置阶段做到这一点。