Why can I see CSS2DObject after the camera is behind CSS2DObject? - three.js

I added CSS2DObject to the scene.
self.labelDiv = document.createElement( 'div' );
self.labelDiv.className = 'label';
self.labelDiv.innerHTML = textshow;
self.label = new THREE.CSS2DObject( self.labelDiv );
self.label.position.set(obj.x, obj.y, obj.z);
this.scene.add(lab);
The effect is as follows:
label1
I moved the camera forward until I couldn't see the model, but the label was displayed again.
label2
What is the reason? How to avoid it?
Thanks.

CSS Renderer can't do clipping like the WebGL renderer so it relies on frustum culling to get rid of objects...
Check if any errors /warnings are showing in console?
Check you're using the latest THREE.js?
Make sure frustumCulling is not disabled on your objects?
Make sure your css objects have some kind of boundingbox or boundingsphere perhaps?

Related

SpriteMaterial without sizeAttenuation in Three.js

i need a (nameplate) sprite without sizeAttenuation in Three.js and it should looks like this example:
//load image with 256x128px 32bit png
var spriteMap = new THREE.TextureLoader().load("tex/plates/mytest.png");
var spriteMat = new THREE.SpriteMaterial({map:spriteMap, transparent:true, sizeAttenuation:false});
var sprite = new THREE.Sprite(spriteMat);
...
spriteMat.map.minFilter = THREE.NearestFilter;
The result is not blurry, but its not correctly and hav some artefacts what i dont want:
Here is my second try with (THREE.LinearFilter), also not what i want cos its too blurry:
Renderer size: 1200x800px (not full window)
So, i dont know if its a problem with the filter, position or scaling. The first example seems like a bitmap text, but i really dont know how i can solve this problem. I also dont need a 2d sprite in screenspace. I need the nameplate in 3d worldspace behind other objects. I have really no idea how i can solve this, pls anyone can help me with this problem?

Rescale Scene or Mesh after loading with Sceneloader

I'm not sure why I cannot rescale my scene after loading with sceneLoader.
I have a simple box that I created and exported from blender as js file.
I tried rescaling the entire result scene before and after. I even looped over the mesh objects and tried rescaling but the scale.set has no affect.
var callbackFinished = function ( result ) {
result.scene.scale.set(10,10,10)
scene.add(result.scene);
}
loader.load( "box.js", callbackFinished );
Thanks,
Jim
Nevermind, I managed to solve it. When loading my model with SceneLoader, the verticesNeedUpdate property is set to false. So I had to set all the mesh verticesNeedUpdate to true for the scale to work.

Outline object (normal scale + stencil mask) three.js

For some time, I've been trying to figure out how to do an object selection outline in my game. (So the player can see the object over everything else, on mouse-over)
This is how the result should look:
The solution I would like to use goes like this:
Layer 1: Draw model in regular shading.
Layer 2: Draw a copy in red color, scaled along normals using vertex shader.
Mask: Draw a black/white flat color of the model to use it as a stencil mask for the second layer, to hide insides and show layer 1.
And here comes the problem. I can't really find any good learning materials about masks. Can I subtract the insides from the outline shape? What am I doing wrong?
I can't figure out how to stack my render passes to make the mask work. :(
Here's a jsfiddle demo
renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters)
composer = new THREE.EffectComposer(renderer, renderTarget)
// composer = new THREE.EffectComposer(renderer)
normal = new THREE.RenderPass(scene, camera)
outline = new THREE.RenderPass(outScene, camera)
mask = new THREE.MaskPass(maskScene, camera)
// mask.inverse = true
clearMask = new THREE.ClearMaskPass
copyPass = new THREE.ShaderPass(THREE.CopyShader)
copyPass.renderToScreen = true
composer.addPass(normal)
composer.addPass(outline)
composer.addPass(mask)
composer.addPass(clearMask)
composer.addPass(copyPass)
Also I have no idea whether to use render target or renderer for the source of the composer. :( Should I have the first pass in the composer at all? Why do I need the copy pass? So many questions, I know. But there are just not enough resources to learn from, I've been googling for days.
Thanks for any advice!
Here's a js fiddle with working solution. You're welcome. :)
http://jsfiddle.net/Eskel/g593q/6/
Update with only two render passes (credit to WestLangley):
http://jsfiddle.net/Eskel/g593q/9/
The pieces missing were these:
composer.renderTarget1.stencilBuffer = true
composer.renderTarget2.stencilBuffer = true
outline.clear = false
Now I think I've found a bit simpler solution, from the THREEx library. It pre-scales the mesh so you dont need a realtime shader for it.
http://jeromeetienne.github.io/threex.geometricglow/examples/geometricglowmesh.html

Unable to get a DirectionalLight shadow to update correctly

I have a DirectionalLight in my scene. When I first create the light the shadow covers the intended area. When the viewport is resized (canvas size) I update the shadowCamera parameters (right,left,top,bottom), and the light's position and target, but the shadow only covers the area before the update.
What flag do I have to set to get the shadow properly updated to reflect the new settings?
Here is the pattern you need to follow to update a shadow camera on-the-fly:
light.shadowCameraLeft = -100;
light.shadowCameraRight = 100;
light.shadowCamera.left = light.shadowCameraLeft;
light.shadowCamera.right = light.shadowCameraRight;
...
light.shadowCamera.updateProjectionMatrix();
three.js r.64

Super sample antialiasing with threejs

I want to render my scene at twice the resolution of my canvas and then downscale it before displaying it. How would I do that using threejs?
for me the best way to have a perfect AA with not too much work (see the code below)
ps :if you increase more than 2 its start to be too sharpen
renderer = new THREE.WebGLRenderer({antialiasing:true});
renderer.setPixelRatio( window.devicePixelRatio * 1.5 );
This is my solution. The source comments should explain what's going on. Setup (init):
var renderer;
var composer;
var renderModel;
var effectCopy;
renderer = new THREE.WebGLRenderer({canvas: canvas});
// Disable autoclear, we do this manually in our animation loop.
renderer.autoClear = false;
// Double resolution (twice the size of the canvas)
var sampleRatio = 2;
// This render pass will render the big result.
renderModel = new THREE.RenderPass(scene, camera);
// Shader to copy result from renderModel to the canvas
effectCopy = new THREE.ShaderPass(THREE.CopyShader);
effectCopy.renderToScreen = true;
// The composer will compose a result for the actual drawing canvas.
composer = new THREE.EffectComposer(renderer);
composer.setSize(canvasWidth * sampleRatio, canvasHeight * sampleRatio);
// Add passes to the composer.
composer.addPass(renderModel);
composer.addPass(effectCopy);
Change your animation loop to:
// Manually clear you canvas.
renderer.clear();
// Tell the composer to produce an image for us. It will provide our renderer with the result.
composer.render();
Note: EffectComposer, RenderPass, ShaderPass and CopyShader are not part of the default three.js file. You have to include them in addition to three.js. At the time of writing they can be found in the threejs project under the examples folder:
/examples/js/postprocessing/EffectComposer.js
/examples/js/postprocessing/RenderPass.js
/examples/js/postprocessing/ShaderPass.js
/examples/js/shaders/CopyShader.js
Here's how you might be able to work it out: In your three.js initialization code, when you create your renderer, make it double the dimensions of your primary canvas, and set it to render to a secondary, hidden canvas element that is twice as large as your primary canvas. Perform the necessary image manipulation on the secondary canvas, and then display the result on the primary canvas.

Resources