Skip to content

[Bug]: Axes3D does not respect distance from camera. #23392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kdbanman opened this issue Jul 6, 2022 · 9 comments
Closed

[Bug]: Axes3D does not respect distance from camera. #23392

kdbanman opened this issue Jul 6, 2022 · 9 comments

Comments

@kdbanman
Copy link

kdbanman commented Jul 6, 2022

Bug summary

When plotting a surface and scatter points with Axes3D, either none of the scatter points are occluded by the surface or all of them are occluded. Whether or not they are occluded appears to depend upon a numerical threshold. (Speculation: perhaps the occlusion of a single point?)

Code for reproduction

# On two separate plots, plot a surface and five lines via scatter3D.  
# The five lines are vertically offset by a constant.  
# The two separate plots differ by an imperceptible difference in offset.
# - The rendered difference is significant.
# - Neither is correct.

import numpy as np
import matplotlib.pyplot as plt

def surface(x, y):
  return np.sin(x) + 0.5 * y * np.cos(x)

def plot_surface_and_lines(vertical_line_offset):
  x, y = np.meshgrid(
    np.linspace(-5, 5, 100),
    np.linspace(-5, 5, 100),
  )

  fig = plt.figure(dpi=150)
  ax = fig.add_subplot(projection='3d')
  ax.set(
    xlabel='x',
    ylabel='y',
    zlim=(-3, 3),
    title=f'z offset = {vertical_line_offset}',
  )

  ax.plot_surface(x, y, surface(x, y))

  a, b = np.meshgrid(np.linspace(-5, 5, 5), np.linspace(-5, 5, 100))
  ax.scatter3D(a, b, surface(a, b) + vertical_line_offset, color='red')

  plt.show()


plot_surface_and_lines(0.253)
plot_surface_and_lines(0.254)

Actual outcome

Expected outcome

Both plots should look like this, with occlusion determined point-by-point.

(This was manually composited with an image editing tool, AFAICT this cannot be generated by matplotlib until the bug is fixed.)

image

Additional information

This global occlusion occurs with many combinations of plots, not exclusively .plot_surface and .scatter3D. The occluder or the occluded can be generated by any of

  • .plot_trisurf
  • .plot_surface
  • .scatter3D
  • .plot_wireframe
    and possibly others. I did not test to find the numerical edge of occlusion/non-occlusion with the other combinations.

Perhaps this is related to other github issues related to depth testing or the underlying z-buffer.

Operating system

Ubuntu 18.04.5 LTS, kernel 5.4.188+

Matplotlib Version

3.2.2

Matplotlib Backend

module://ipykernel.pylab.backend_inline

Python version

3.7.13

Jupyter version

5.3.1 (via google colab release 2022/6/10)

Installation

No response

@oscargus
Copy link
Member

oscargus commented Jul 6, 2022

FYI, in the current main branch they both look as the 0.253 case, so something has happened although it is still not as expected.

@jklymak
Copy link
Member

jklymak commented Jul 6, 2022

This is a duplicate of #12260 unfortunately Matplotlib cannot do proper 3D rendering.

@jklymak jklymak closed this as not planned Won't fix, can't repro, duplicate, stale Jul 6, 2022
@kdbanman
Copy link
Author

kdbanman commented Jul 6, 2022

@jklymak #12260 appears to be about some quite unrelated example code. Can you explain the relationship to this issue?

@tacaswell
Copy link
Member

This is a known issue, I suspect a typo the cross referencing. I'm not sure what issue Jody was aiming for though.

@kdbanman
Copy link
Author

kdbanman commented Jul 6, 2022

Thanks for the clarification @tacaswell! Upon further research, I see that the z-order of 3D objects with nontrivial occlusions is indeed a common issue.

Is it possible for me to contribute here? I have some experience with OpenGL. I notice this part of the current docs

3D plotting in Matplotlib is still not as mature as the 2D case. Please report any functions that do not behave as expected as a bug. In addition, help and patches would be greatly appreciated!

and this part as well

This problem will likely not be solved until OpenGL support is added to all of the backends (patches are greatly welcomed).

@jklymak
Copy link
Member

jklymak commented Jul 6, 2022

Sorry #12620!

It would be great to have proper rendering but that is a big project!

@dopplershift
Copy link
Contributor

@kdbanman The problem is that Matplotlib doesn't really have a 3D-capable renderer/rasterizer. To do this properly you'd need to do one of:

  1. Wrap OpenGL to handle the rendering to get "true" 3D
  2. Write a full software rasterizer that renders objects into fragments that include a depth component that can be used to draw the correct final fragments in the rendered scene.

@kdbanman
Copy link
Author

kdbanman commented Jul 6, 2022

@dopplershift thanks for the context. mplot3d's capabilities are impressive, considering it's not already wrapped OpenGL. I had assumed there was a wrapper in place which might just need patching.

Is there an existing example of wrapped renderer in matplotlib I could refer to?

I'm curious to see a rough example of architecture. Obviously OpenGL is a bit of a different animal - I'm guessing platform and backend portability would be big challenges.

@WeatherGod
Copy link
Member

WeatherGod commented Jul 7, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants