I am looking to set sprites into a semi-opaque state when they’re behind a model.
I have (a very slow) method which compares the distance from the camera to each sprite in the scene vs the distance from the camera to the model intersection (using the raycaster) to change the opacity of the sprites. If the sprite distance is shorter than the model distance, the sprite stays fully visible, otherwise the sprite is made sightly transparent because the model is closer in the line-of-sight. This method takes up too much resource in the render loop and it’s not much better even if it’s run less frequently using a listener on the controls. Not to mention, the more sprites there are in the scene, the slower it gets . Overall the method isn’t great and I haven’t been able to figure an accurate method without raycasting.
I’d kindly appreciate any clues for a better method I could use. I’m new to Three.js/WebGL in general, but wonder if there’s some kind of option or available shader that could achieve this?
I should add: the concept behind wanting to do this is to make model viewing with annotations less visually cluttered. By making the sprites semi-opaque the user can still see and interact with the sprite while remaining relatively out of sight.
@PavelBoytchev nice trick! For more performance the same concept can be used with post processing and camera layers, but it’s definitely more complex than your example and probably an overkill.
This is genius. Thank you. I spent far too much energy thinking about how to calculate the solution, rather than just think of this as a layering problem.
On my end all I’ve needed to do is generate two sprites instead of one, each with their own material. With no noticeable impact on performance.
// generate texture, let spriteTexture = new THREE.Texture(canvas);
let material1 = new THREE.SpriteMaterial({
map: spriteTexture,
depthTest: false,
depthWrite: false,
sizeAttenuation: false,
opacity: 0.3,
transparent: true
});
let sprite1 = new THREE.Sprite(material1);
// then scale, position and add sprite 1 to scene
let material2 = new THREE.SpriteMaterial({
map: spriteTexture,
depthTest: true,
depthWrite: true,
sizeAttenuation: false,
opacity: 1,
transparent: true
});
let sprite2 = new THREE.Sprite(material2);
// then scale, position and add sprite 2 to scene