Billboard non-uniform scale handle

I want to achieve a fixed size sprite, for this I use a plane with shaderMaterial to achieve this requirement, and it needs to always face me like a sprite, but when I found that I used non-uniform scaling, it would produce strange phenomena at certain viewing angles

To make it always face me, I assign camera.absoluteRotation to the rotationQuaternion of this plane.

billboard vertex shader:

precision highp float;

attribute vec3 position;
attribute vec2 uv;

uniform mat4 world;
uniform mat4 view;
uniform mat4 projection;

uniform vec2 uResolution;

varying vec2 vUV;

void main() {
  vec4 worldPosition = world * vec4(position, 1.0);

  vec4 viewPosition = view * worldPosition;

  vec2 scale = vec2(
    length(vec3(world[0][0], world[1][0], world[2][0])), 
    length(vec3(world[0][1], world[1][1], world[2][1]))
    );

  vec2 vertex = position.xy * scale;

  vertex.x *= uResolution.y / uResolution.x;

  vec4 clipPosition = projection * viewPosition;

  clipPosition.xy += vertex * clipPosition.w;

  gl_Position = clipPosition;
  vUV = uv;

}

Here is the screenshot

Am I overlooking something? How can I fix it?

Why not using the billboardMode property of the plane mesh? It should take care of the world matrix calculation for you, even when using non uniform scaling.

The demo in the document does not meet my needs. My requirement is to keep a fixed size.

I’m not sure I understand. Could you reproduce the problem in the Playground so we can better see what you need?

Here is another demo without scaling, just a cube and a plane which always faces the camera - https://playground.babylonjs.com/#ANE052#44

okay i write a demo,You can use mouse wheel to zoom. It always maintains a fixed size, but when you rotate the view, you will see the phenomenon of squeezing.
billboard test

Thanks for your reply. I wrote a demo for your reference.

billboard test

I refer to this approach in the Unity forum.I made some changes but I’m not sure if they are correct.
reference:
https://discussions.unity.com/t/need-help-fixed-size-billboard/745529/2

How about this? - https://playground.babylonjs.com/#MZDRAY#4

When setting billboardMode to 7, you can see the deformation when mouse zoom. I think this is not what i expect.

here is unity forum’ way ,this ensures that the mouse will not deform and remain fixed in size when zooming or rotating, but the position is limited to 0,0,0
https://playground.babylonjs.com/#MZDRAY#5

I believe this is because of your shaderMaterial. Here is the example with StandardMaterial - https://playground.babylonjs.com/#MZDRAY#6

My goal is to keep an object at a constant size when the mouse is zoomed in and out, that is, it is not affected by the perspective matrix.

My modified approach will have problems with non-uniform scaling and small camera radius. This is a PG demo
https://playground.babylonjs.com/#MZDRAY#8

Not sure if that is what you are looking for - https://playground.babylonjs.com/#MZDRAY#11

    camera.onViewMatrixChangedObservable.add(() => {
        if (sphere) {
            const distance = BABYLON.Vector3.Distance(sphere.position, camera.position);
            const scaleFactor = distance * Math.tan(camera.fov / 2);
            sphere.scaling.set(scaleFactor, scaleFactor, scaleFactor);
        }
    });
1 Like

You should remove sphere.rotationQuaternion = camera.absoluteRotation when you set sphere.billboardMode = 7.

Yes, that’s the effect, but I want to achieve it in shader

But it will get smaller as the mouse wheel zooms in and out. I want it to be fixed in size and not get bigger or smaller as the mouse zooms in and out.

I have solved this problem. It is because there is a difference in accessing matrix elements in glsl and js, so according to the practice of the unity forum, I need to get the correct translation vector and scale vector in the world matrix.

Here is new PG,leave it for reference for people who want to use this method to implement billboard in the future

billboard

References:
opengl docs page 130

2 Likes