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.
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.
Based on this example i try to create a scene where several objects get the bloom, and other objects dont.
The white cube in the middle is supposed to be just white (without the bloom)
I'm confused on how to get the result that i want. I tried for example adding a 2nd scene with the white cube but it seems i cant get the order right. Maybe my approch with different scenes is wrong?
Whats the "best" way to achieve this behaviour? I always end up just seeing one scene, just the white cube or the 4 colored ones. (example below shows everything atm)
myFiddle: https://jsfiddle.net/qwertasyx/8qw3ys4z/16/
var scene,scene2,camera, controls, pointLight, stats;
var composer, renderer, mixer;
var params = {
exposure: 1,
bloomStrength: 1.5,
bloomThreshold: 0,
bloomRadius: 0
};
var objects = [];
var clock = new THREE.Clock();
var container = document.getElementById( 'container' );
stats = new Stats();
//container.appendChild( stats.dom );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ReinhardToneMapping;
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
//scene2 = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2.5,2.5, 10 );
scene.add( camera );
// scene2.add( camera );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.maxPolarAngle = Math.PI * 0.5;
controls.minDistance = 1;
controls.maxDistance = 10;
controls.target.set(2.5,2.5,0)
controls.update()
// scene.add( new THREE.AmbientLight( 0x404040 ) );
pointLight = new THREE.PointLight( 0xffffff, 1 );
// camera.add( pointLight );
var renderScene = new THREE.RenderPass( scene, camera );
//var renderScene2 = new THREE.RenderPass( scene2, camera );
var bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.renderToScreen = true;
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
composer = new THREE.EffectComposer( renderer );
composer.setSize( window.innerWidth, window.innerHeight );
composer.addPass( renderScene );
composer.addPass( bloomPass );
//composer.addPass( renderScene2 );
//objects
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
scene.add( cube );
objects.push(cube)
// cube thats supposed to be not bloomy
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 2.5
cube.position.x += 2.5
scene.add( cube );
objects.push(cube)
var gui = new dat.GUI();
gui.add( params, 'exposure', 0.1, 2 ).onChange( function ( value ) {
renderer.toneMappingExposure = Math.pow( value, 4.0 );
} );
gui.add( params, 'bloomThreshold', 0.0, 1.0 ).onChange( function ( value ) {
bloomPass.threshold = Number( value );
} );
gui.add( params, 'bloomStrength', 0.0, 3.0 ).onChange( function ( value ) {
bloomPass.strength = Number( value );
} );
gui.add( params, 'bloomRadius', 0.0, 1.0 ).step( 0.01 ).onChange( function ( value ) {
bloomPass.radius = Number( value );
} );
window.onresize = function () {
var width = window.innerWidth;
var height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
composer.setSize( width, height );
};
function animate() {
requestAnimationFrame( animate );
objects.forEach(function(obj){
obj.rotation.z += obj.vrz;
});
stats.update();
composer.render();
}
animate();
I had a similar problem once. An example from this comment helped me.
Note that in that example there are 2 scenes and 2 composers (the final composer gets output of the previous composer as its input)
ppoFinal.blendPass.uniforms.tAdd.value = ppoRGB.composer.renderTarget2.texture;
and render() is called on both composers.
ppoRGB.composer.render();
ppoFinal.composer.render();
This pattern allows you to apply postprocessing effects selectively and it works well. The problem is the scalability of the method and probably performance. Because when you want to apply another object with yet different effect, you need to introduce 3rd scene and 3rd composer. For my little project in the past I ended up with 4 scenes and 4 composers...
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 have the following code to add a gui and the ability to click on objects.
When I set the controls as controls = new THREE.TrackballControls( camera, renderer.domElement); the GUI works but the Raycaster doesnt seem to work.
If I define the constrols as controls = new THREE.TrackballControls( camera); the raycaster works, however once I click the gui on the corner, then wherever I move the mouse the values of the gui change, while if I close it, the GUI resize with response to mouse movements
Can Anyone give me any hint how to fix this?
At the moment works but I'm able to unclick from the control by simultaneously left and right clicking
This link shows how far I have gone and give you an idea of the problem
http://subsurface.gr/joomla/threejs/StreamFnc_ws.html
Here is the full code:
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
// global variables
var camera, controls, scene, renderer;
var container, stats;
var raycaster, intersects;
var threshold = 0.05;
var mouse = new THREE.Vector2();
var cube;
// Parameters for GUI
var params = {
AAmin: 0.0,
AAmax: 1000.0
};
// main functions
init();
animate();
function init(){
container = document.createElement( 'div' );
document.body.appendChild( container );
//Setup Camera
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.name = 'camera';
camera.position.z = 20;
// Setup world
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
// Setup lights
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 1, 1, 1 );
scene.add( directionalLight );
directionalLight.name = 'directionalLight';
var directionalLight1 = new THREE.DirectionalLight( 0x002288 );
directionalLight1.position.set( -1, -1, -1 );
directionalLight1.name = 'directionalLight1';
scene.add( directionalLight1 );
var ambientLight = new THREE.AmbientLight( 0x222222 );
ambientLight.name = 'ambientLight';
scene.add( ambientLight );
raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = threshold;
// Main Scene
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube = new THREE.Mesh( geometry, material );
cube.name = 'mycube';
scene.add( cube );
// GUI parameter
var gui = new dat.GUI();
gui.add( params, 'AAmin', -1000, 500 );
gui.add( params, 'AAmax', 500, 2000 );
gui.open();
//renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//controls
controls = new THREE.TrackballControls( camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render);
stats = new Stats();
container.appendChild( stats.dom );
// events
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
function onDocumentMouseDown( event ){
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
intersects = raycaster.intersectObject( cube );
if ( intersects.length > 0 ){
console.log("You click a cube!");
}
}
If I understand correctly, the TrackballControls is stopping propagation of the mouseDown event (bound to the renderer.domElement) -- meaning your onDocumentMouseDown handler isn't being invoked. Try moving your document.addEventListener(...) to come before new THREE.TrackballControls(...).
Responding to your comment below:
I see the problem now. There appears to be an incompatibility between TrackballControls and Dat.GUI in that the TrackballControls mouseup events stops propagation of the event, which causes Dat.GUI to bug out and get stuck resizing the UI for some reason.
I believe you can solve this by disabling TrackballControls when clicking the GUI, and re-enabling TrackballControls on mouseup:
gui.domElement.addEventListener( 'mousedown', function(){ controls.enabled = false; }, false );
document.addEventListener( 'mouseup', function(){ controls.enabled = true; }, false );
I am trying to load a collada file using Threejs. All works well, but if I make the object spin I can see that the rendering is not right. Check the image:
Here is the code (which was partially stolen from another example):
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, .1, 10000 );
camera.position.x=50;
camera.position.y=50;
camera.position.z=50;
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
var ambientLight = new THREE.AmbientLight(0x000000);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(100,50,80).normalize();
scene.add(directionalLight);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true; // this rotates so it looks right
loader.load('models/VM.dae', function (result) {
cube = result.scene;
// cube.doubleSided = true;
// cube.flipSided = true;
console.log(cube);
cube.updateMatrix();
scene.add(result.scene);
animate();
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
cube.rotation.y += 0.01;
// plane.rotation.y = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
New update:
I changed the loader to a MTL+OBJ one. The result is exactly the same:
var loader = new THREE.OBJMTLLoader();
loader.addEventListener("load", function (event) {
cube = event.content;
cube.doubleSided = true;
console.log(event);
scene.add(cube);
animate();
});
loader.load ("models/VM.obj", "models/VM.mtl");
Fiddle: http://jsfiddle.net/qMqH7/
Your model is throwing errors in the Console, I would suggest you track them down.
What you are seeing is a known limitation of CanvasRenderer related to depth-sorting. It is made worse by your geometry which has several elongated faces. The model renders correctly with WebGLRenderer.
Also, object.doubleSided has been deprecated. It has been replaced by material.side = THREE.DoubleSide. It does not appear that flag is required in this case.
three.js r.58