0

I wrote a custom shader for three.js so the points are rounded. The shader is the following:

new ShaderMaterial({
    transparent: true,
    depthWrite: false,
    uniforms: {
        size: { value: pointSize * canvasSize * 0.5 },
        color: { value: [...color, opacity ?? 1] },
    },
    vertexShader: `
        uniform float size;

        void main() {
            gl_PointSize = size;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `,
    fragmentShader: `
        uniform vec4 color;

            void main() {
            if (length(gl_PointCoord - vec2(0.5)) > 0.5) discard;

            gl_FragColor = color;
        }
    `
})

But I also need to increase the point size when the camera zoom in. How do I do that?


The current undesired behavior of zoom: enter image description here

Tiago Cavalcante
  • 161
  • 1
  • 10
  • The answer in [this post](https://stackoverflow.com/questions/51214088/three-js-increase-point-size-as-camera-gets-closer-to-point) doesn't respect the zoom, just the rotation. – Tiago Cavalcante Aug 03 '21 at 17:36
  • What do you mean you want to increase the point size as the camera zooms in? You mean you need just the standard distance-based scaling as it goes further back? Like [in this example](https://threejs.org/examples/#webgl_points_billboards)? – M - Aug 03 '21 at 18:15
  • @Marquizzo that doesn't respect the zoom too, using the same vertex shader as `PointsMaterial` (with a `#define USE_SIZEATTENUATION` in its top) don't respect the zoom. – Tiago Cavalcante Aug 04 '21 at 19:22

2 Answers2

0

To get how far away each point is from the camera, you can get the model-view-position by multiplying the original position * modelViewMatrix. Then use the .z component of that result to get its distance to the camera:

vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;

float depth = -mvPosition.z;

I'm not sure what you're trying to do, but from the GIF you posted it looks like you're using an orthographic camera, which doesn't have perspective scaling, AKA size-attenuation. If you want to force it, you'll have to manually change the point size with

gl_PointSize = size / depth;

M -
  • 26,908
  • 11
  • 49
  • 81
  • The camera is a perspective camera. I'll check if this works. – Tiago Cavalcante Aug 04 '21 at 19:38
  • It isn't working, the same behavior. From what I understand of GLSL that works when you change the camera position, but the zoom doesn't change the camera position, just the FOV (in my project at least). – Tiago Cavalcante Aug 04 '21 at 19:40
  • Oh! I see what you mean. You mean you're changing the `camera.zoom` parameter. You have 2 options here: You could change the field-of-view angle `.fov` instead, and then `updateProjectionMatrix()` each time. A zoom of 2 is the same as dividing `fov/2`. Or you could instead create a new `uniform` in your shader code with the zoom property, and use that to affect your point size. – M - Aug 04 '21 at 19:47
  • Marquizzo thanks by the help! About the `camera.fov`, I'm already using it. – Tiago Cavalcante Aug 04 '21 at 19:53
0

Oh, I have discovered the answer!

Acoording to this the FOV is projectionMatrix[0][0], so changing the point size to the following solves my problem:

gl_PointSize = size * projectionMatrix[0][0];
Tiago Cavalcante
  • 161
  • 1
  • 10