Three.js: Raycast problem with SpriteMaterial.sizeAttenuation set to false

Created on 19 Sep 2018  路  6Comments  路  Source: mrdoob/three.js

Hi Friends!

SpriteMaterial.sizeAttenuation = false

seems not working as expected with rayCaster.
I doubt the sprite size(dimension) estimation may be a little bit off, ray is very hard to hit them after apply scale(), especially scale down.
I can upload a simplified code that regenerate this problem a bit later.

  • [x] r96
Browser
  • [x] All of them

Thanks!

Bug

All 6 comments

Right. This is a known limitation: raycasting does not work correctly when SpriteMaterial.sizeAttenuation is false.

/ping @06wj

@WestLangley Thanks, do you want me to mark this as duplicated issue or close it?

@Rubinhuang9239 Well, it was a known limitation to me. ;-)

Leave this open, please. Thanks for reporting.

The following pattern can be used as a workaround to prevent size attenuation, and still support raycasting. Leave sprite.sizeAttenuation = true;

// raycasting against sprites when using a perspective camera only works correctly when sizeAttanuation is true (r.97)
var onBeforeRender = function () {

    var v = new THREE.Vector3();
    var v1 = new THREE.Vector3();

    return function onBeforeRender( renderer, scene, camera ) {

        var factor = 0.05; // optional

        v.setFromMatrixPosition( this.matrixWorld );
        v1.setFromMatrixPosition( camera.matrixWorld );

        var f = v.sub( v1 ).length() * factor;
        this.scale.x = this.userData.originalScale.x * f;
        this.scale.y = this.userData.originalScale.y * f;

    }

}();

sprite.userData.originalScale = new THREE.Vector3().copy( sprite.scale ); // optional

sprite.onBeforeRender = onBeforeRender;

Modify this pattern to accommodate your use case.

Hello,

As @WestLangley's solution didn't fit my needs I thought I would share mine (and keep sizeAttenuation to false), which is basically using "gpu picking" instead of ray tracing:

  • Duplicate the sprite object, setup the material so that it renders in a specific color, and put it in a hidden layer (it also may be a good idea to have a texture designed for picking that covers a larger area).
  • When rendering the scene, also render the hidden layer for the previous step in a separate render target .
  • Read the render target at cursor position using WebGLRenderer.readRenderTargetPixels.
  • If the read color is different to the renderer clear color, then the cursor hovered the sprite.

This approach has the downside of not providing the 3D coordinates, but you can compute them back using the depth and projection matrix.

Should be solved via #16423

Was this page helpful?
0 / 5 - 0 ratings

Related issues

makc picture makc  路  3Comments

akshaysrin picture akshaysrin  路  3Comments

fuzihaofzh picture fuzihaofzh  路  3Comments

jlaquinte picture jlaquinte  路  3Comments

seep picture seep  路  3Comments