DOF v2, on scene or canvas?

I’m trying to get DoF v2 to work with scenes in one canvas but I don’t get where it should be set. In each scene, it doesn’t show up for me (I may be wrongly put it in sceneInitFunctionsByName).
Should it be at each scene level? Or at the more global canvas level?

I successfully did it with EffectComposer in DoF v1 but something happens after a few seconds and in the browser console I get a warning:

localhost/:1 [.WebGL-0x55d9aba78e20] GL_OUT_OF_MEMORY: Internal error: 0x00000505: Unexpected driver error.
localhost/:1 WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost

From there, my UBUNTU session is kind of corrupted, the GPU memory issue has contaminated other apps using the GPU (other browser and apps) and I have to reboot the computer to fully clean the shared memory.
It happens on Firefox 99 and Chromium 100 but faster to fail on Chromium.

I think it’s not a bug, just me not figuring where is the right place in scenes in one canvas :slight_smile:

BTW, the dof v1 issue is not the main point here.

DoF v2 works better in my opinion but I didn’t get it working with scenes in one canvas at all. No error, but simply not being applied.

To test it: simply get the code from the bottom of the page and try to implement dof v2.

Bump :slight_smile:
@Mugen87 any idea?

Please demonstrate with a live example what you are doing. It’s then easier to debug the issue.

Thank you for your time @Mugen87 !

OK, here’s what I tried in svelte, using source to limit size (but imported twice for the moment).
There’s no error but no DoF and a vertically compressed camera view with poor fps at scene 1.

	import {
		MeshBasicMaterial,
		PlaneBufferGeometry,
		BoxGeometry,
		DoubleSide,
		VideoTexture,
		RGBAFormat,
		Mesh,
		DirectionalLight,
		PerspectiveCamera,
		WebGLRenderer,
		Scene,
		Color,
		CubeTextureLoader,
		Vector2,
		WebGLRenderTarget,
		MeshPhongMaterial,
		BoxBufferGeometry,
		SphereBufferGeometry,
		MeshLambertMaterial,
		ShaderMaterial,
		UniformsUtils,
		OrthographicCamera,
		PlaneGeometry
	} from 'three/src/Three.js';
	import { TrackballControls } from './trackball.js';
	import { BokehShader, BokehDepthShader } from 'three/examples/jsm/shaders/BokehShader2.js';

	// vars
	let materialDepth;
	const postprocessing = { enabled: true };
	const shaderSettings = {
		rings: 3,
		samples: 4
	};
	function main() {
		const canvas = document.querySelector('#c');
		const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: true });

		const sceneElements = []; 
		function addScene(elem, fn) {
			sceneElements.push({ elem, fn });
		}
		//DoFv2
		const depthShader = BokehDepthShader;
		effectController = {
			enabled: true,
			jsDepthCalculation: true,
			shaderFocus: false,
			fstop: 2.2,
			maxblur: 1.0,
			showFocus: false,
			focalDepth: 2.8,
			manualdof: false,
			vignetting: false,
			depthblur: false,
			threshold: 0.5,
			gain: 2.0,
			bias: 0.5,
			fringe: 0.7,
			focalLength: 35,
			noise: true,
			pentagon: false,
			dithering: 0.0001
		};
		const postprocessing = { enabled: true };
		const shaderSettings = {
			rings: 3,
			samples: 4
		};

		materialDepth = new ShaderMaterial({
			uniforms: depthShader.uniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader
		});

		function makeScene(elem) {
			const scene = new Scene();

			const fov = 45;
			const aspect = 2; // the canvas default
			const near = 0.1;
			const far = 5;
			const camera = new PerspectiveCamera(60, 16 / 9, 0.1, 3000);
			camera.position.set(0, 1, 2);
			camera.lookAt(0, 0, 0);
			scene.add(camera);

			//DoFv2
			materialDepth.uniforms['mNear'].value = camera.near;
			materialDepth.uniforms['mFar'].value = camera.far;

			const controls = new TrackballControls(camera, elem);
			// controls.noZoom = true;
			controls.noPan = true;

			{
				const color = 0xffffff;
				const intensity = 1;
				const light = new DirectionalLight(color, intensity);
				light.position.set(-1, 2, 4);
				scene.add(light);
			}

			return { scene, camera, controls };
		}

		const sceneInitFunctionsByName = {
			box: (elem) => {
				const { scene, camera, controls } = makeScene(elem);
				const geometry = new BoxBufferGeometry(10, 10, 10);
				const material = new MeshPhongMaterial({ color: 'red' });
				const mesh = new Mesh(geometry, material);
				for (let i = 0; i < 1500; i++) {
					const object = new Mesh(
						geometry,
						new MeshLambertMaterial({ color: Math.random() * 0xffffff })
					);

					object.position.x = Math.random() * 800 - 400;
					object.position.y = Math.random() * 800 - 400;
					object.position.z = Math.random() * 800 - 400;

					scene.add(object);
				}

				scene.add(mesh);
				return (time, rect) => {
					mesh.rotation.y = time * 0.1;
					// mesh.position.z = Math.sin(time * 0.5) * 50;
					camera.aspect = rect.width / rect.height;
					// camera.updateMatrixWorld();

					camera.updateProjectionMatrix();
					controls.handleResize();
					controls.update();
					//DoFv2
					initPostprocessing();
					// not working
					// postprocessing.rtTextureDepth.setSize(window.innerWidth, window.innerHeight);
					// postprocessing.rtTextureColor.setSize(window.innerWidth, window.innerHeight);

					// postprocessing.bokeh_uniforms['textureWidth'].value = window.innerWidth;
					// postprocessing.bokeh_uniforms['textureHeight'].value = window.innerHeight;

					renderer.setSize(window.innerWidth, window.innerHeight);

					renderer.render(scene, camera);
				};
			},
			pyramid: (elem) => {
				const { scene, camera, controls } = makeScene(elem);
				const radius = 0.8;
				const widthSegments = 4;
				const heightSegments = 2;
				const geometry = new SphereBufferGeometry(radius, widthSegments, heightSegments);
				const material = new MeshPhongMaterial({
					color: 'blue',
					flatShading: true
				});
				const mesh = new Mesh(geometry, material);
				scene.add(mesh);
				return (time, rect) => {
					mesh.rotation.y = time * 0.1;
					camera.aspect = rect.width / rect.height;
					camera.updateProjectionMatrix();
					controls.handleResize();
					controls.update();
					renderer.render(scene, camera);
				};
			}
		};
		document.querySelectorAll('[data-diagram]').forEach((elem) => {
			// @ts-ignore
			const sceneName = elem.dataset.diagram;
			const sceneInitFunction = sceneInitFunctionsByName[sceneName];
			const sceneRenderFunction = sceneInitFunction(elem);
			addScene(elem, sceneRenderFunction);
		});

		function resizeRendererToDisplaySize(renderer) {
			const canvas = renderer.domElement;
			const width = canvas.clientWidth;
			const height = canvas.clientHeight;
			const needResize = canvas.width !== width || canvas.height !== height;
			if (needResize) {
				renderer.setSize(width, height, false);
			}
			return needResize;
		}

		const clearColor = new Color('#000');
		function render(time) {
			time *= 0.001;

			resizeRendererToDisplaySize(renderer);

			renderer.setScissorTest(false);
			renderer.setClearColor(clearColor, 0);
			renderer.clear(true, true);
			renderer.setScissorTest(true);

			const transform = `translateY(${window.scrollY}px)`;
			renderer.domElement.style.transform = transform;

			for (const { elem, fn } of sceneElements) {
				// get the viewport relative position of this element
				const rect = elem.getBoundingClientRect();
				const { left, right, top, bottom, width, height } = rect;

				const isOffscreen =
					bottom < 0 ||
					top > renderer.domElement.clientHeight ||
					right < 0 ||
					left > renderer.domElement.clientWidth;

				if (isOffscreen) {
				}
				if (!isOffscreen) {
					const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
					renderer.setScissor(left, positiveYUpBottom, width, height);
					renderer.setViewport(left, positiveYUpBottom, width, height);

					fn(time, rect);
				}
			}

			requestAnimationFrame(render);
		}

		requestAnimationFrame(render);
	}
	//DoFv2
	function animate(renderer, scene, camera) {
		requestAnimationFrame(animate);
		render(renderer, scene, camera);
	}
	function render(renderer, scene, camera) {
		const time = Date.now() * 0.00015;

		camera.position.x = Math.cos(time) * 400;
		camera.position.z = Math.sin(time) * 500;
		camera.position.y = Math.sin(time / 1.4) * 100;
		// camera.lookAt(target);

		camera.updateMatrixWorld();

		if (postprocessing.enabled) {
			renderer.clear();

			// render scene into texture

			renderer.setRenderTarget(postprocessing.rtTextureColor);
			renderer.clear();
			renderer.render(scene, camera);

			// render depth into texture

			scene.overrideMaterial = materialDepth;
			renderer.setRenderTarget(postprocessing.rtTextureDepth);
			renderer.clear();
			renderer.render(scene, camera);
			scene.overrideMaterial = null;

			// render bokeh composite

			renderer.setRenderTarget(null);
			renderer.render(postprocessing.scene, postprocessing.camera);
		} else {
			scene.overrideMaterial = null;

			renderer.setRenderTarget(null);
			renderer.clear();
			renderer.render(scene, camera);
		}
	}

	function initPostprocessing() {
		postprocessing.scene = new Scene();

		postprocessing.camera = new OrthographicCamera(
			window.innerWidth / -2,
			window.innerWidth / 2,
			window.innerHeight / 2,
			window.innerHeight / -2,
			-10000,
			10000
		);
		postprocessing.camera.position.z = 100;

		postprocessing.scene.add(postprocessing.camera);

		postprocessing.rtTextureDepth = new WebGLRenderTarget(window.innerWidth, window.innerHeight);
		postprocessing.rtTextureColor = new WebGLRenderTarget(window.innerWidth, window.innerHeight);

		const bokeh_shader = BokehShader;

		postprocessing.bokeh_uniforms = UniformsUtils.clone(bokeh_shader.uniforms);

		postprocessing.bokeh_uniforms['tColor'].value = postprocessing.rtTextureColor.texture;
		postprocessing.bokeh_uniforms['tDepth'].value = postprocessing.rtTextureDepth.texture;
		postprocessing.bokeh_uniforms['textureWidth'].value = window.innerWidth;
		postprocessing.bokeh_uniforms['textureHeight'].value = window.innerHeight;

		postprocessing.materialBokeh = new ShaderMaterial({
			uniforms: postprocessing.bokeh_uniforms,
			vertexShader: bokeh_shader.vertexShader,
			fragmentShader: bokeh_shader.fragmentShader,
			defines: {
				RINGS: shaderSettings.rings,
				SAMPLES: shaderSettings.samples
			}
		});

		postprocessing.quad = new Mesh(
			new PlaneGeometry(window.innerWidth, window.innerHeight),
			postprocessing.materialBokeh
		);
		postprocessing.quad.position.z = -500;
		postprocessing.scene.add(postprocessing.quad);
	}

	onMount(() => {
		main();
	});
</script>

and html + style

<svelte:head>
	<title>Svelte</title></svelte:head
>
<div class="forcanvas">
	<canvas id="c" />
	<p>
		<span data-diagram="box" class="left" />
		I love boxes. Presents come in boxes. When I find a new box I'm always excited to find out what's
		inside.
	</p>
	<p>
		<span data-diagram="pyramid" class="right" />
		When I was a kid I dreamed of going on an expedition inside a pyramid and finding a undiscovered
		tomb full of mummies and treasure.
	</p>
</div>

<style>
	#c {
		position: absolute;
		left: 0;
		top: 0;
		width: 100vw;
		height: 100vh;
		display: block;
		z-index: -1;
	}
	*[data-diagram] {
		display: inline-block;
		width: 10em;
		height: 6em;
	}
	.left {
		float: left;
		margin-right: 0.25em;
	}
	.right {
		float: right;
		margin-left: 0.25em;
	}
	p {
		margin: 1em auto;
		max-width: 500px;
		font-size: xx-large;
	}
</style>

There’s no DoF in the scene 1 (box).

Bump @Mugen87

With live example I was hoping you share something like: Edit fiddle - JSFiddle - Code Playground