Я пытаюсь создать приложение, которое будет имитировать длительную съемку. Идея заключается в том, что я захватываю текущий кадр с веб-камеры и складываю его на холст. Со временем фото «разоблачит», станет ярче и ярче. (см. http://www.chromeexperiments.com/detail/light-paint-live-mercury/?f=)trjs фрагментарный шейдер с использованием переработанных буферов кадров
У меня есть шейдер, который отлично работает. Это похоже на режим добавления «добавить» в Photoshop. Проблема в том, что я не могу заставить его переработать предыдущий кадр.
Я думал, что это будет что-то простое, как renderer.autoClear = false;
, но этот вариант, кажется, ничего не делает в этом контексте.
Вот код, который использует THREE.EffectComposer для применения шейдера.
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();
}
Вот шейдер. Ничего особенного.
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")
[Это обсуждение] (https://github.com/mrdoob/three.js/issues/587), похоже, указывает, что вы должны создать WebGLRenderer следующим образом: 'new WebGLRenderer ({preserveDrawingBuffer: true})', и установите для параметра 'renderer.autoClearColor' значение false. – voithos
Это будет работать для создания эффектов на геометрию (например, размытие движения), но это не влияет на фактические текстуры геометрии. Это то, что я пытаюсь настроить. –