I can't get my RenderPass to write into a MaskPass. If I try doing the passes seperately (like only a TexturePass; or TexturePass + OutputPass) it works but I can't get my stencil buffer to work.
http://signaturefloors.dev.flooradvisor.com.au/productapp/floor_align.php
I just want to render the main "scene" 2 or 3 times into different stencils (which are then combined) but I can't even get a single MaskPass working if I also use a RenderPass. Mask + Texture pass seems to work, it's the RenderPass causing me issues.
Basically if I do MaskPass then RenderPass nothing is displayed. It SHOULD simply show me a masked plane.
// Composer
var texture1 = new THREE.TextureLoader().load( 'textures/2294472375_24a3b8ef46_o.jpg' );
var texturePass1 = new THREE.TexturePass( texture1 );
var clearMask = new THREE.ClearMaskPass();
var renderMask = new THREE.MaskPass( this.scene, this.camera );
var renderMaskInverse = new THREE.MaskPass( this.scene, this.camera );
renderMaskInverse.inverse = true;
var viewScene = new THREE.RenderPass( this.scene, this.camera );
// Composition pass
var outputPass = new THREE.ShaderPass( THREE.CopyShader );
outputPass.renderToScreen = true;
var renderTargetParameters = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
stencilBuffer: true
};
// Setup render target
var renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
this.composer = new THREE.EffectComposer(this.renderer, renderTarget);
var renderPass = new THREE.RenderPass(this.scene, this.camera);
//renderPass.renderToScreen = true;
this.composer.addPass( texturePass1 );
//this.composer.addPass( viewMask );
this.composer.addPass( renderMask );
this.composer.addPass( viewScene );
this.composer.addPass( clearMask );
this.composer.addPass( outputPass );
I've been looking for a solution to this for a day or so and fell over quite a few questions like yours. None with a useable answer, but I think I found a solution:
To enable masking of a RenderPass you need to set clear = false.
In your case:
var viewScene = new THREE.RenderPass( this.scene, this.camera );
viewscene.clear = false
This should do it! Here's a codepen: https://codepen.io/staus/pen/BJNNLq
Related
I have a model with some parts of it being metallic and others non-metallic. I have applied the environment map to get the correct reflections from the metallic parts of the model but the non metallic parts look equally reflective.
What should I do to make the non-metallic parts to appear less reflective and more rough as they are created. The model looks perfect in the Don Muccurdy’s gltf-viewer.
Please tell me what parameters do I need to change to get it right?
First is my rendered model and Second is the gltf viewer rendered model.
var rgbeLoader=new THREE.RGBELoader().setType( THREE.UnsignedByteType )
.setPath( 'textures/equirectangular/' )
.load( 'pedestrian_overpass_2k.hdr', function ( texture ) {
cubeGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 1024 } );
cubeGenerator.update( renderer );
pmremGenerator = new THREE.PMREMGenerator( cubeGenerator.renderTarget.texture );
pmremGenerator.update( renderer );
pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
pmremCubeUVPacker.update( renderer );
envMap = pmremCubeUVPacker.CubeUVRenderTarget.texture;
var loader = new THREE.GLTFLoader();
loader.load( 'tfsProject4.glb', function ( gltf ) {
scene.add(gltf.scene);
gltf.scene.traverse((e)=>{
e.material.envMap=envMap;
});
});
The following code is called from a function after loading all the assets including the model shown.
const scene = new THREE.Scene();
modalCamera = new THREE.PerspectiveCamera( 75, modalCanHolder.width() /
modalCanHolder.height(), 0.001, 100 );
var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
scene.add( light );
var light = new THREE.AmbientLight( 0x808080 );
scene.add( light );
var directionalLight = new THREE.DirectionalLight( 0xffffff, .3 );
directionalLight.position.set(0,10,10)
scene.add( directionalLight );
modalRenderer = new THREE.WebGLRenderer({antialias: true, alpha:true});
modalRenderer.gammaOutput = true;
modalRenderer.gammaFactor = 2.2;
modalRenderer.physicallyCorrectLights=true;
modalRenderer.outputEncoding = THREE.sRGBEncoding;
modalRenderer.physicallyCorrectLights = true;
modalRenderer.setSize( modalCanHolder.width(), modalCanHolder.height() );
modalRenderer.setPixelRatio( window.devicePixelRatio );
modalCanHolder.append( modalRenderer.domElement );
modalRenderer.domElement.id = 'modalCanvas';
cubeGenerator.update( modalRenderer );
pmremGenerator.update( modalRenderer );
pmremCubeUVPacker.update( modalRenderer );
var controls = new THREE.OrbitControls( modalCamera, modalRenderer.domElement );
var prod=products[id];
scene.add(prod);
controls.update();
const animate = function () {
subAnimation=requestAnimationFrame( animate );
controls.update();
modalRenderer.render( scene, modalCamera );
};
animate();
Please help me get the rendering right.
I've tried to add Bounding Box to my object but it seems to work only for the testObj, he does not work for my others objects with texture.
var testObj = new THREE.Mesh(
new THREE.CylinderGeometry( 1 , 1 , 4 , 8 ),
new THREE.MeshLambertMaterial({ color: 0xff00ff })
);
scene.add(testObj );
staticCollideMesh.push(testObj );
// PADDLE1
loaderTexture.load('http://localhost:8000/WoodTexture.jpg', function (texture ) {
var material = new THREE.MeshLambertMaterial( {
map: texture
});
var geometry = new THREE.BoxGeometry(PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_DEPTH );
paddle1 = new THREE.Mesh( geometry, material);
paddle1.castShadow = true;
paddle1.receiveShadow = true;
paddle1.name = "paddle1";
scene.add( paddle1 );
staticCollideMesh.push(paddle1);
}, undefined, function ( err ) {
console.error( 'WoodTexture1.jpg : An error happened.' );
}
);
This is how I add BBox and BoxHelper :
let constructCollisionBoxes = function() {
staticCollideMesh.forEach( function( mesh ){
mesh.BBox = new THREE.Box3().setFromObject( mesh );
mesh.BBoxHelper = new THREE.BoxHelper( mesh , 0xff0000 );
scene.add( mesh.BBoxHelper );
});
}
I don't know why the loop just apply for my cylinder ... I need help to understand why this is not working.
EDIT: thanks to #prisoner849 I just added the function in the loader
scene.add(paddle1);
staticCollideMesh.push(paddle1);
constructionCollisionMesh();
In case of using loaders, keep in mind, that loading is asynchronous, so when you call constructCollisionBoxes(), your box, whose creation relies on the moment of finishing of loading of the texture, is not in the staticCollideMesh array yet.
To fix it, you can do it this way:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));
var staticCollideMesh = [];
var PADDLE_WIDTH = 3,
PADDLE_HEIGHT = 3,
PADDLE_DEPTH = 2;
var testObj = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 4, 8),
new THREE.MeshLambertMaterial({
color: 0xff00ff
})
);
scene.add(testObj);
staticCollideMesh.push(testObj);
var texture = new THREE.TextureLoader().load(`https://threejs.org/examples/textures/uv_grid_opengl.jpg`);
// PADDLE1
var material = new THREE.MeshLambertMaterial({
map: texture
});
var geometry = new THREE.BoxGeometry(PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_DEPTH);
paddle1 = new THREE.Mesh(geometry, material);
paddle1.castShadow = true;
paddle1.receiveShadow = true;
paddle1.name = "paddle1";
scene.add(paddle1);
staticCollideMesh.push(paddle1);
let constructCollisionBoxes = function() {
staticCollideMesh.forEach(function(mesh) {
mesh.BBox = new THREE.Box3().setFromObject(mesh);
mesh.BBoxHelper = new THREE.BoxHelper(mesh, 0xff0000);
scene.add(mesh.BBoxHelper);
});
}
constructCollisionBoxes();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://unpkg.com/three#0.115.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.115.0/examples/js/controls/OrbitControls.js"></script>
I caeate outline according to this example https://threejs.org/examples/?q=out#webgl_postprocessing_outline.And this is the result.It is works well.But when i set scene.background=texture,it is not work.IAnd i check the three.js document about scene.background. (If not null, sets the background used when rendering the scene, and is always rendered first. Can be set to a Color which sets the clear color, a Texture covering the canvas, or a CubeTexture. Default is null).I want to find out why outline disappear.Here is the code.
var scene, camera, renderer;
var light, floor;
var WIDTH,HEIGHT;
var controls;
var composer;
var composer, effectFXAA, outlinePass;
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
init();
animation()
function init () {
scene = new THREE.Scene();
var textureLoader = new THREE.TextureLoader();
textureLoader.load('img/bg.png', function(texture){
scene.background = texture;
});
camera = new THREE.PerspectiveCamera(45, WIDTH/HEIGHT, 0.1, 800);
camera.position.set(0,150,150);
scene.add(camera);
scene.add(new THREE.AmbientLight(0xffffff));
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
controls = new OrbitControls(camera);
var shape = new THREE.Shape();
shape.moveTo(0,4);
shape.lineTo(0,96);
shape.lineTo(4,100);
shape.lineTo(96,100);
shape.lineTo(100,96);
shape.lineTo(100,4);
shape.lineTo(96, 0 );
shape.lineTo(84,0);
shape.lineTo(80,4);
shape.lineTo(20, 4);
shape.lineTo(16, 0);
shape.lineTo(4, 0 );
shape.lineTo(0, 4);
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var material = new THREE.MeshLambertMaterial( { color: 0x0E2350 } );
mesh = new THREE.Mesh( geometry, material ) ;
mesh.rotation.x = -Math.PI/2;
mesh.translateX(-50);
mesh.translateY(-50);
scene.add(mesh);
composer = new THREE.EffectComposer( renderer );
var renderPass = new THREE.RenderPass( scene, camera );
composer.addPass( renderPass );
outlinePass = new THREE.OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera );
outlinePass.edgeStrength = 3;
outlinePass.edgeGlow = 3.0;
outlinePass.edgeThickness = 0.1;
outlinePass.visibleEdgeColor.setHex(0x19C0EE);
composer.addPass( outlinePass );
effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
effectFXAA.renderToScreen = true;
composer.addPass( effectFXAA );
outlinePass.selectedObjects = [mesh];
}
function animation() {
requestAnimationFrame(animation);
composer.render();
render();
controls.update();
};
function render () {
renderer.render(scene, camera)
};
I am trying to use the OutlinePass after SSAA postprocessing but my outline does not show up if I call SSAA after OutlinePass. How can I apply SSAA to my outline? I know FXAA will work but I want to use SSAA.
I have something like:
var composer = new THREE.EffectComposer( renderer );
outlinePass = new THREE.OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera );
composer.addPass( outlinePass );
outlinePass.visibleEdgeColor.set('#ffffff');
outlinePass.hiddenEdgeColor.set( '#190a05' );
outlinePass.edgeThickness = 5.0;
outlinePass.edgeStrength = 5.0;
outlinePass.edgeGlow = 0.0;
outlinePass.pulsePeriod = 0;
outlinePass.rotate = false;
outlinePass.usePatternTexture = false;
outlinePass.selectedObjects = [cube];
let ssaaRenderPass = new THREE.SSAARenderPass( scene, camera );
ssaaRenderPass.sampleLevel = 2;
composer.addPass( ssaaRenderPass );
copyPass = new THREE.ShaderPass( THREE.CopyShader );
copyPass.renderToScreen = true;
composer.addPass( copyPass );
Nevermind, I just applied FXAA to the outline and it looks OK.
So I did SSAA, outlinePass, then FXAA. The FXAA smooth out the shape in the outline.
The code
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: false,depthBuffer:false },
renderTargetOcl = new THREE.WebGLRenderTarget( SCREEN_WIDTH/4, SCREEN_HEIGHT/4, renderTargetParameters );
var effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] );
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCREEN_WIDTH, 1 / SCREEN_HEIGHT );
let hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
let vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );
var bluriness = 2;
hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH*2;
vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT*2;
var renderModel = new THREE.RenderPass( this.scene, this.camera );
var renderModelOcl = new THREE.RenderPass( this.oclscene, this.oclcamera );
let grPass = new THREE.ShaderPass( THREE.ShaderExtras['Godrays'] );
grPass.needsSwap = true;
grPass.renderToScreen = false;
var finalPass = new THREE.ShaderPass( THREE.ShaderExtras['Additive'] );
finalPass.needsSwap = true;
finalPass.renderToScreen = true;
let oclcomposer = new THREE.EffectComposer( this.renderer, renderTargetOcl );
oclcomposer.addPass( renderModelOcl );
oclcomposer.addPass( hblur );
oclcomposer.addPass( vblur );
oclcomposer.addPass( hblur );
oclcomposer.addPass( vblur );
oclcomposer.addPass( grPass );
let renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
let finalcomposer = new THREE.EffectComposer( this.renderer, renderTarget );
finalcomposer.addPass( renderModel );
// finalcomposer.addPass( effectFXAA );
finalcomposer.addPass( finalPass );
finalPass.uniforms[ 'tAdd' ].value = oclcomposer.renderTarget1.texture;
I'm trying to make light scrattring.
When set grPass.renderToScreen = true; and finalPass.renderToScreen = false; i got right result.That means the first composer works well.
While i use the oclcomposer as texture to a plane material ,it get wrong result:the light keeps shinning and has green and yellow ring aroud it.
The result i want is like:,not shinning all the time and only has blue color.The wrong result disappears once i cut the screen.
From above,i think that's from the rendertarget which get wrong result,has no idea what it changes the texture
Oh,when i set grPass.needsSwap = false it works.Seem like an version change.