I see a lot of projects using CopyShader at the end of a post-processing chain. I cannot find any documentation of it on Three.js. What does it do exactly? Additionally, why is setRenderTarget necessary here? If removed, the effects are not applied. But if it is included, then it will 'freeze' an a-scene in place, stopping all animations. I am able to use tick and setInterval to resume the animation, but the performance takes a huge hit.
For example:
var composer = new THREE.EffectComposer( renderer );
renderer.setRenderTarget( composer.readBuffer );
var renderPass = new THREE.RenderPass( scene, camera );
var copyPass = new THREE.ShaderPass( CopyShader );
composer.addPass( renderPass );
var vignettePass = new ShaderPass( VignetteShader );
vignettePass.uniforms[ "darkness" ].value = 1.0;
composer.addPass( vignettePass );
composer.addPass( copyPass );
composer.render();
this.composer = composer; // To run as composer.render()
The postprocessing pipeline renders back and forth between 2 offscreen buffers. When the final pass is complete, the result needs to be copied to the actual screen. That's what the CopyShader does. Conceivably you could architect your passes so that the final pass rendered directly to the visible screen, but in practice, that introduces some complexity.
Related
I have one Renderer object and two scene objects. One scene contains the objects that should not be processed by the unrealbloom post-processing pass and the other scene contains all “glowing” objects.
Now I thought I could do:
const THREED_Composer = new THREE.EffectComposer( THREED_Renderer );
const THREED_RenderPass = new THREE.RenderPass( THREED_Scene, THREED_Camera );
const THREED_RenderPassGlow = new THREE.RenderPass(
THREED_SceneGlow, THREED_Camera );
const THREED_BloomPass = new THREE.UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight), 0.5, 0.5, 0.4);
//THREED_BloomPass.renderToScreen = false; ???
THREED_Composer.addPass( THREED_RenderPassGlow );
THREED_Composer.addPass( THREED_BloomPass );
THREED_Composer.addPass( THREED_RenderPass );
The intention was to first render the glowing objects and then render the non-glowing objects over them. I want the non-glowing objects to be able to obscure the glowing objects.
My animate function looks like this:
function animate()
{
if(GLOBAL_FocusLost)
return;
requestAnimationFrame(animate);
update();
THREED_Composer.render();
}
Ultimate goal:
I want to have glowing monolith in the midst of a room that can be obscured by all other objects.
I tried to read my way through the documentation but I think that I do not understand it enough.
Cheers. Any help is very much appreciated!
I have a model, a background sky and a ground surface. Texturing the surface results in no surface.
I've tried the basic approach and come to the conclusion that it is probably that the scene is being rendered before the texture has finished loading. Having searched and found various possible solutions, I have tried several of them, without really understanding how they are supposed to work. None of them has worked. One problem is that it is an old problem and most of the suggestions involve outdated versions of the three.js library.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
}
);
// This variation does not work either
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple.htm
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple7jsV0.15b.htm
The first of the above is the complete page in which the ground is a plain billiard table green. The second is the page containing the above code.
There appear to be no error (Last time I tried.)
By the time your texture loads and you add the ground, your scene has already rendered (and there is no other render call).
You need to call renderer.render(scene, camera); after adding the ground to the scene.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
renderer.render(scene, camera); // <--- add this line
}
);
I'm trying to add a SSAO shader pass to the an earlier fiddle which was the result of: EffectComposer second pass "overwrites" first pass
Unfortunately I get a black screen I created a new fiddle which I will update with my findings:
http://jsfiddle.net/mqt1ng2r/
Creating the depthshader and the target for the depth shader to render onto:
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
depthMaterial.blending = THREE.NoBlending;
depthTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat } );
Creating the SSAO shader pas and adding it to the composer
var effect = new THREE.ShaderPass( THREE.SSAOShader );
effect.uniforms[ 'tDepth' ].value = depthTarget;
effect.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
effect.uniforms[ 'cameraNear' ].value = camera.near;
effect.uniforms[ 'cameraFar' ].value = camera.far;
effect.renderToScreen = true;
composer.addPass( effect );
The render loop rendering the scene with the override material set first befor the composer is rendered
requestAnimationFrame( animate );
//renderer.clear(); // changed -------------
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthTarget );
scene.overrideMaterial = null;
composer.render();
A side question which came up is would you be able to add the rendering of the scene with the depth target to the composer too?
Reason for this question is that the rendertarget is different and a override material is to be set. I couldnt find any way do do this, does it even sound reasonable to do this or am i miss using the effect composer here?
Found out that the SSAO is partially working if i set effect.uniforms[ 'onlyAO' ].value = 1; then you can see it working but setting it to 0 results in a black screen. Looking at the code of the EffectComposer now to see what is happening.
Hopefully someone can help me out once again.
Like I said I'll update this post and the fiddle with my attempts
Interesting links on the subject:
Pull request to add resize support to SSAO demo https://github.com/mrdoob/three.js/pull/6820
Edits:
Added some relevant snippets of the code (posting all here would clutter the question)
Added interesting links
effect.uniforms[ 'onlyAO' ].value = 1;
I,m trying to put multiple passes in EffectComposer and everything is fine except for BokehPass.
My code look like this (I already got a scene, camera and renderer):
...
var renderPass = new THREE.RenderPass( scene, camera );
var postRenderer = new THREE.EffectComposer( renderer );
var copyPass = new THREE.ShaderPass( THREE.CopyShader );
var bokehSettings = {
focus : 1.0, aperture : 0.025, maxblur : 1.0,
width: window.innerWidth, height : window.innerHeight
}
var bokehPass = new THREE.BokehPass( scene, camera, bokehSettings );
var bleachPass = new THREE.ShaderPass( THREE.BleachBypassShader);//I make clone of uniforms but, for puspose, I don't write here.
postRenderer.addPass( renderPass );
postRenderer.addPass( bleachPass );
postRenderer.addPass( bokehPass );
postRenderer.addPass( copyPass );
...
function render(){
postRenderer.render( 0.1 );
}
...
The bleachPass work fine but not bokehPass in this order.
If I try : renderPass -> bleachPass -> bokehPass, bleachPass doesnt work.
Then I try : renderPass -> bleachPass -> copyPass -> bokehPass, but it give me some weird result.
Someone know how to mix multiple passes with bokeh?
Thanks!
Old question but for future reference here's the answer by #Mugen87:
https://github.com/mrdoob/three.js/issues/18634
BokehPass set needsSwap to false. That means the result of the buffer is not available in the read buffer for the subsequent post processing pass. This is done for performance reasons since usually this DOF pass is used on its own or at the end of the pass chain. So adding the following line of code should solve the issue:
bokehPass.needsSwap = true;
Updated fiddle: https://jsfiddle.net/5nxy0tqp/
Maybe it could still help people: I think you forgot the copyPass.renderToScreen = true (because it is your last shader to be addPass)
I have a house model in my game, and I have some materials for the house geometry. There is a material for the wall of the house, and I have a texture-map-image to show the bricks.
var mat = new THREE.MeshPhongMaterial( {
ambient: 0x969696,
map: THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' ),
overdraw: true,combine: THREE.MultiplyOperation
} );
In this way above, the texture map appears like GL_CLAMP I want it to show like GL_REPEAT.
What should I do?
If you can not see the images check this.
I have posted a full working example at:
http://stemkoski.github.com/Three.js/Texture-Repeat.html
The relevant part of the code example is:
// for example, texture repeated twice in each direction
var lavaTexture = THREE.ImageUtils.loadTexture( 'images/lava.jpg' );
lavaTexture.wrapS = lavaTexture.wrapT = THREE.RepeatWrapping;
lavaTexture.repeat.set( 2, 2 );
var lavaMaterial = new THREE.MeshBasicMaterial( { map: lavaTexture } );
var lavaBall = new THREE.Mesh( THREE.GeometryUtils.clone(sphereGeom), lavaMaterial );
scene.add( lavaBall );
It's called THREE.RepeatWrapping there. The loadTexture defaults to THREE.ClampToEdgeWrapping (see ctor function from previous link). Don't know if you can use the callback (because this in JS is a bit weird (looks like it points to the created Image, not the created Texture)). Signature:
loadTexture: function ( path, mapping, callback ) {
Better you just name the texture locally and set the wrap modes manually:
var t = THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' );
t.wrapS = t.wrapT = THREE.RepeatWrapping;
Looks like you're not going far with threejs without looking at the actual code...
Image must be 8x8, 16x16, 32x32, 128x128, 256x256, 512x512 etc.
And all be working.
=)