Note that there are some explanatory texts on larger screens.

plurals
  1. POthreejs fragment shader using recycled frame buffers
    primarykey
    data
    text
    <p>I'm trying to make an app that will simulate long exposure photography. The idea is that I grab the current frame from the webcam and composite it onto a canvas. Over time, the photo will 'expose', getting brighter and brighter. (see <a href="http://www.chromeexperiments.com/detail/light-paint-live-mercury/?f=" rel="nofollow noreferrer">http://www.chromeexperiments.com/detail/light-paint-live-mercury/?f=</a>)</p> <p>I have a shader that works perfectly. It's just like the 'add' blend mode in photoshop. The problem is that I can't get it to recycle the previous frame. </p> <p>I thought that it would be something simple like <code>renderer.autoClear = false;</code> but that option seems to do nothing in this context.</p> <p>Here's the code that uses THREE.EffectComposer to apply the shader.</p> <pre><code> onWebcamInit: function () { var $stream = $("#user-stream"), width = $stream.width(), height = $stream.height(), near = .1, far = 10000; this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize(width, height); this.renderer.autoClear = false; this.scene = new THREE.Scene(); this.camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, near, far); this.scene.add(this.camera); this.$el.append(this.renderer.domElement); this.frameTexture = new THREE.Texture(document.querySelector("#webcam")); this.compositeTexture = new THREE.Texture(this.renderer.domElement); this.composer = new THREE.EffectComposer(this.renderer); // same effect with or without this line // this.composer.addPass(new THREE.RenderPass(this.scene, this.camera)); var addEffect = new THREE.ShaderPass(addShader); addEffect.uniforms[ 'exposure' ].value = .5; addEffect.uniforms[ 'frameTexture' ].value = this.frameTexture; addEffect.renderToScreen = true; this.composer.addPass(addEffect); this.plane = new THREE.Mesh(new THREE.PlaneGeometry(width, height, 1, 1), new THREE.MeshBasicMaterial({map: this.compositeTexture})); this.scene.add(this.plane); this.frameTexture.needsUpdate = true; this.compositeTexture.needsUpdate = true; new FrameImpulse(this.renderFrame); }, renderFrame: function () { this.frameTexture.needsUpdate = true; this.compositeTexture.needsUpdate = true; this.composer.render(); } </code></pre> <p>Here is the shader. Nothing fancy.</p> <pre><code> uniforms: { "tDiffuse": { type: "t", value: null }, "frameTexture": { type: "t", value: null }, "exposure": { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = uv;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D frameTexture;", "uniform sampler2D tDiffuse;", "uniform float exposure;", "varying vec2 vUv;", "void main() {", "vec4 n = texture2D(frameTexture, vUv);", "vec4 o = texture2D(tDiffuse, vUv);", "vec3 sum = n.rgb + o.rgb;", "gl_FragColor = vec4(mix(o.rgb, sum.rgb, exposure), 1.0);", "}" ].join("\n") </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload