silx-kit / h5web

React components for data visualization and exploration
https://h5web.panosc.eu/
MIT License
165 stars 17 forks source link

z-range is only -3..3 #1626

Closed vallsv closed 2 months ago

vallsv commented 2 months ago

Is your feature request related to a problem?

I use a lot the z-index.

But i saw that the range is clamped to something quite small like 0..3 or -3...3

Outside, a component is hidden.

I have to use a lot of layers for my use cases.

Sure i still can divide 0..3 by an infinite amount of values. But i feel like more easy to deal with integer.

Requested solution or feature

Use a bigger range for the z-buffer, maybe something like 0..1000 or -1000..1000, i don't know.

Alternatives you've considered

Rescale the z-depth on my side.

Additional context

I use @h5web/lib": "7.0.2-beta.0

axelboc commented 2 months ago

Stacking has been sorted out in v7.1.0 with some additional bug fixes in later versions. I recommend you upgrade first then check out the Stacking documentation page. If you're still stuck at that point, let me know and we'll try to figure it out.

vallsv commented 2 months ago

Hi, thanks for the answer.

But i only talk about the opengl canvas z-buffer.

In fact i don't use any SVG components.

axelboc commented 2 months ago

Can you make a basic repro? Because, you're not giving us much to go on here. 😅 You can use this sandbox as a base and replace one of the visualizations with a Canvas with some R3F/ThreeJS children.

vallsv commented 2 months ago

Here is an example.

As you can see the violet and the red are not visible because outside of the z-index.

So the visible z-range is in fact [-995...4].

import React from "react";
import { VisCanvas } from "@h5web/lib";

export default function App() {
  const width = 1000;
  const height = 1000;

  const stuffs = [
    {color:"#FF0018", z:-996, size:6},
    {color:"#FFA52C", z:-995, size:5},
    {color:"#FFFF41", z:-1, size:4},
    {color:"#008018", z:1, size:3},
    {color:"#0000F9", z:4, size:2},
    {color:"#86007D", z:5, size:1},
  ]

  return (
      <VisCanvas
        abscissaConfig={{
          visDomain: [-width, width],
          label: "x (px)",
        }}
        ordinateConfig={{
          visDomain: [-height * 0.6, height * 0.6],
          label: "y (px)",
        }}
        aspect="equal"
        showAxes
      >
        {stuffs.map((stuff, index)=> (
          <mesh key={`m${index}`} position-z={stuff.z}>
            <ambientLight />
            <planeGeometry attach="geometry" args={[stuff.size*50, stuff.size*50, 1, 1]} />
            <meshBasicMaterial
              attach="material"
              transparent={true}
              color={stuff.color}
              opacity={1}
            />
          </mesh>
        ))}
      </VisCanvas>
  );

image

axelboc commented 2 months ago

Thanks! Okay, so this seems to match the far setting of R3F's default orthographic camera: 1000. The camera itself seems to be positioned at a z coordinate of 5, which explains why the range is [-995 5[.

We could maybe move the camera to a z coordinate of 1000 to make things easier?

vallsv commented 2 months ago

You could use 500, so the range would be synetric -500, 500.

But if there possibility to setup the camera, i think it's even better to setup something like {near: -1000, far: 1000, position: [0, 0, 0]}. Maybe @t20100 would have a better feedback than me here.

axelboc commented 2 months ago

near must be within [0 far], so I can do { near: 0, far: 2000, position: [0, 0, 1000] } to allow for a z coordinate range of [-1000 1000]?

axelboc commented 2 months ago

... or [-1000 1000[ with the default near: 0.1.

axelboc commented 2 months ago

Turns out the range [-1000 1000[ is incompatible with the technique we use to hide points with NaN or infinite coordinates.


Currently:

The difference in z position between valid and invalid points was great enough, and the hidden portion of this range great enough, that the lines between them appeared to not be rendered. In reality, the lines were only cut off, leading to visual glitches at high-enough zoom levels:

image


With the following proposal:

Since "valid" points are still rendered at z=0, lines are no longer hidden at all. That's because the hidden portions of the lines are very small (visible: [0 999.9]; hidden: [999.9 1000]).

image

Two ways to fix this:

  1. Render invalid points at an arbitrarily large positive or negative z coordinate. This will always render visual glitches, unfortunately, since there will always be a visible portion in [0 999.9] or [-1000 0].
  2. Render valid points exactly on the near or far plane of the camera's frustrum, so at z=-1000 or z=999.9.

The second solution fixes the visual glitches but is obviously not ideal, since it's much more convenient in the code to just render "valid" points at z=0 instead of always referring to a constant.


For this reason, I propose the following camera configuration: { near: 0, far: 1000, position: [0, 0, 1000] }. This gives a visible range of [0 1000] and allows "valid" points rendered at z=0 to end up right on the far plane; and by rendering "invalid" points just a bit further (e.g. at z=-1), we ensure that the lines between valid and invalid points are completely hidden and that we even get rid of the visual glitches:

image

loichuder commented 2 months ago

Two ways to fix this:

Heh. There is a third one: use line segments instead of a single line and do no render the segments with an invalid point to avoid dealing with them in the display :smile_cat:

For this reason, I propose the following camera configuration: { near: 0, far: 1000, position: [0, 0, 1000] }

Sounds ok to me 👍

axelboc commented 2 months ago

Heh. There is a third one: use line segments instead of a single line and do no render the segments with an invalid point to avoid dealing with them in the display 😸

Haha yes, indeed. Downside of course is larger geometry buffers and more complicated code with look-ahead or look-behind logic.

vallsv commented 2 months ago

is incompatible with the technique we use to hide points with NaN or infinite coordinates.

If you use the z buffer to hide stuffs, i think it's a very bad idea.

axelboc commented 2 months ago

Thanks for your input.

t20100 commented 2 months ago

threejs logs some errors for NaN & Inf, so this is not a neat way, IMO using the z-buffer nicely workaround this and sparses using segments and indices.

+1 for [0, 1000] z-range (and anyway it's configurable)