dmurdoch / rgl

rgl is a 3D visualization system based on OpenGL. It provides a medium to high level interface for use in R, currently modelled on classic R graphics, with extensions to allow for interaction.
https://dmurdoch.github.io/rgl/
GNU General Public License v2.0
86 stars 21 forks source link

The `persp3d()` function returns a blank plot #432

Closed AndreySamokhin closed 1 month ago

AndreySamokhin commented 2 months ago

Hello! I encountered an issue with the persp3d() function, where it returns a blank plot.

rgl::persp3d(volcano, col = "green")

fig01

The plot3d() function works as expected.

rgl::plot3d(sort(rnorm(1000)), rnorm(1000), rnorm(1000), col = rainbow(1000))

fig02

I have updated the GPU driver, R and all R packages, but the issue persists. I have not found any similar problems in the issues on GitHub. If you could provide any advice, I would be grateful.

fig04 fig03

dmurdoch commented 2 months ago

I don't see that. You could try the Github version of rgl and it might give different results, but I suspect it won't. Another thing to try is to use options(rgl.useNULL = TRUE) before starting rgl, then run rglwidget() after creating the plot. That will create a WebGL plot and ask your web browser to display it. If rglwidget() works, there are ways to make that display automatic in RStudio and maybe in other front ends.

AndreySamokhin commented 2 months ago

Thank you for your quick response and efforts to help! I tried two versions of the rgl package: 1.3.1 (from CRAN) and 1.3.10 (from GitHub). As you expected, the results were the same.

Also, the kludge that you suggested works.

options(rgl.useNULL = TRUE)
rgl::persp3d(volcano, col = "green")
rgl::rglwidget()

fig05

Here are a few additional examples that might help you identify the source of the problem. Could you suggest ways to narrow down the list of potential issues, given that the problem only occurs with surfaces and front lines?

options(rgl.useNULL = TRUE)
rgl::persp3d(volcano, col = "green", front = "lines")
rgl::rglwidget()

fig06

rgl::persp3d(volcano, col = "green", front = "lines")

fig07

rgl::persp3d(volcano, col = "green", back = "lines")

fig08

dmurdoch commented 2 months ago

When you ask for front = "lines", you are also implicitly asking for back = "fill". It may be that your graphics driver has issues when front and back are different. (Or it may be an rgl bug, but I think that would show up on my Mac too.)

Similarly, back = "lines" asks for front = "fill", so your rgl::persp3d(volcano, col = "green", back = "lines") example should really look like the first plot: none of the back should be visible, because the front should hide it.

You might be able to get what you intended by avoiding mixing "lines" with "fill". Either specify both front and back to be "lines", or draw the surface twice, once with front = "lines", back = "cull" and then again with front = "cull", back = "fill", add = TRUE if that's really what you wanted.

AndreySamokhin commented 2 months ago

Thanks again for the response. I am just wondering why surfaces do not render on my machine, resulting in blank plots. As I mentioned before, I have performed some basic actions (updating the GPU driver, R, RStudio, all packages), but, unfortunately, it did not help. If I manage to find a solution (or at least identify the source of the problem), I will describe it here.

Here are the results of applying various options:

Arguments Result
default blank plot
front = "lines" blank plot
back = "lines" see fig
front = "lines", back = "lines" see fig
front = "filled" blank plot
back = "filled" blank plot
front = "filled", back = "filled" blank plot
front = "points" blank plot
back = "points" see fig
front = "points", back = "points" see fig
front = "cull", back = "filled" blank plot
front = "cull", back = "points" see fig
front = "cull", back = "lines" see fig

fig09

dmurdoch commented 2 months ago

The display that rgl uses is based on the very old version 1.2 of OpenGL. It's likely that more recent implementations are simulating it based on DirectX or a more recent OpenGL version, and it seems possible that your graphics driver isn't doing it properly.

About a year ago I started on an update to OpenGL 3 (which is still old), but it stalled because the text-drawing library I use isn't supported any more, so I'd have to update it myself, or switch to another one. I may try that this year, but not for a few months at least.

AndreySamokhin commented 2 months ago

Changing the core of the package is a significant undertaking. Good luck with it! Your initial suggestion about rglwidget() works in my case. I will use it for a while. If I accidentally uncover the source of the problem, I will leave a message here. Thanks again for your help!

aitap commented 1 month ago

Perhaps rgl could work better on your computer with Mesa3D for Windows, which renders the scene on the CPU instead of relying on the video card and its drivers? Placing opengl32.dll (most likely 64-bit) in R-x.y.z\bin\x64 (for stand-alone R) or RStudio\resources\app\bin (for RStudio) should switch OpenGL to software rendering for the whole R process (potentially breaking something else if it also relies on OpenGL). Putting opengl32.dll in rgl\libs\x64, near rgl.dll, doesn't work, presumably because R loads rgl.dll by full path.

If a similar problem is encountered on Linux, it might be worked around using LIBGL_ALWAYS_SOFTWARE=true, unless using a non-Mesa (nVidia?) GL stack.

AndreySamokhin commented 1 month ago

@aitap, thank you for the provided solution! I have tested it, and it works perfectly in both stand-alone R and RStudio IDE, so I will close this issue. Thanks again for your help!