Written and maintained by CASRAI Editorial Board
Last updated
To make a 3D plot in R, pick the package by the output you need: scatterplot3d draws a static 3D point cloud that stays inside base R graphics, rgl draws a rotatable OpenGL scene, and persp() in base R draws a surface from a grid of z values. This guide gives the install route, a working call for each, and the decision rule for choosing between them.
Which R 3D tool fits which output
The three tools below answer different questions.
| Tool | What it draws | Output | What it returns |
|---|---|---|---|
scatterplot3d (CRAN package) |
A 3D point cloud, with optional lines or vertical drop lines | Static plot in the active R graphics device | A list of helper functions, including xyz.convert, points3d, plane3d, box3d, contour3d |
rgl (CRAN package, “3D Visualization Using OpenGL”) |
3D scatterplots and other 3D scenes via plot3d() |
On screen, or saved to WebGL, PLY, OBJ, STL (3D) or PNG, PostScript, SVG, PGF (2D) | Object IDs |
persp() (base R graphics) |
A perspective surface from x, y and a z matrix | Static plot | A 4×4 viewing transformation matrix, usable with trans3d() |
For a journal figure that must be a fixed image, the static tools are the direct route. For exploring a point cloud by rotating it, or for exporting a 3D model file, rgl is the one of the three that lists those outputs.
What 3D plots in R are used for in research
A 3D plot shows three numeric variables at once: three measured columns for each observation (a point cloud), or one response over a grid of two inputs (a surface). Typical uses are inspecting how a response depends on two predictors before fitting a model, checking cluster separation in three dimensions, and showing a fitted function. Because a 3D plot is projected onto a flat page, read values from a 2D panel or a table where precision matters; see designing effective scientific figures for how to pair views. If you only need two variables, scatterplots in R is the simpler route.
Install or access (CRAN only)
All three tools come from the R project. Install the two packages from CRAN inside R, then load them:
install.packages("scatterplot3d")
install.packages("rgl")
library(scatterplot3d)
library(rgl)
Versions listed on CRAN on 2026-10-29: scatterplot3d 0.3-45 (published 2026-02-23, depends on R 2.7.0 or later) and rgl 1.3.36 (published 2026-03-06, depends on R 3.6.0 or later). persp() ships with R and needs no install.
The rgl CRAN page states that OpenGL and GLU are needed for on-screen display, and that this is not needed if only browser displays using rglwidget() are wanted. Optional system libraries are zlib, libpng (1.2.9 or later) and FreeType.
Step-by-step: a 3D scatter, then a fitted plane, then a surface
1. A static 3D scatter with scatterplot3d
This example is the first one in the package’s reference manual:
z <- seq(-10, 10, 0.01)
x <- cos(z)
y <- sin(z)
scatterplot3d(x, y, z, highlight.3d = TRUE, col.axis = "blue",
col.grid = "lightblue", main = "scatterplot3d - 1",
pch = 20, mar = c(0, 0, 0, 0))
Arguments worth knowing, from the manual: angle sets the angle between the x and y axes (default 40); type is “p” for points, “l” for lines or “h” for vertical lines to the x-y plane; scale.y scales the y axis relative to x and z; highlight.3d = TRUE colours points by their y coordinate.
2. Add a fitted plane
Save the plot object, then call its plane3d helper. The manual says plane3d accepts an intercept with coefficients, a 3-vector, or an lm object. This example uses R’s built-in trees data set:
fit <- lm(Volume ~ Girth + Height, data = trees)
s3d <- scatterplot3d(trees$Girth, trees$Height, trees$Volume,
xlab = "Girth", ylab = "Height", zlab = "Volume",
pch = 16)
s3d$plane3d(fit)
The response goes on the z axis and the two predictors on x and y, which matches the model formula.
3. An interactive scatter with rgl
This is the example from the plot3d reference page:
open3d()
x <- sort(rnorm(1000))
y <- rnorm(1000)
z <- rnorm(1000) + atan2(x, y)
plot3d(x, y, z, col = rainbow(1000))
The usage line is plot3d(x, y, z, xlab, ylab, zlab, type = "p", col, size, lwd, radius, add = FALSE, ...). Missing values (NA) are skipped, the default size is 3, and the function returns object IDs. Drag in the window to rotate the scene.
4. A surface with persp()
The base R documentation example draws the sinc function:
x <- seq(-10, 10, length.out = 30)
y <- x
f <- function(x, y) { r <- sqrt(x^2 + y^2); 10 * sin(r) / r }
z <- outer(x, y, f)
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")
Add lighting and readable axes by extending the call, as the same page does:
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue",
ltheta = 120, shade = 0.75, ticktype = "detailed",
xlab = "X", ylab = "Y", zlab = "Sinc( r )")
5. Overlay points on a surface
Store the value persp() returns and pass it to trans3d(), which converts 3D coordinates into the 2D coordinates of that view:
res <- persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")
points(trans3d(0, 0, 10, pmat = res), pch = 16, col = "red")
Output and how to read it
- Viewing angle. In
persp(),thetais the azimuth andphithe colatitude; the defaults are 0 and 15. Inscatterplot3d,angleis the angle between the x and y axes (default 40), and the manual notes the result depends on scaling. Change one angle at a time. - Colour by y. With
highlight.3d = TRUEpoints are coloured by their y coordinate, and thecolorargument is ignored. The colour is therefore not an extra variable. - Axis values.
persp()defaults toticktype = "simple", which draws an arrow only;"detailed"draws ordinary ticks so values can be read. - Shading. In
persp(),shadebetween about 0.5 and 0.75 approximates daylight, per the documentation. - Perspective distortion. A 3D plot is a projection onto a flat page, so one view can hide depth. State the viewing angle in the figure caption and consider a 2D companion panel.
Troubleshooting
- The rgl window does not open. On-screen display needs OpenGL and GLU. If you only need output in a browser, the CRAN page says those are not needed when using
rglwidget(). - Points are missing from an rgl plot.
plot3d()skips NA values; checksum(is.na(x))for each of x, y and z. - persp() errors about z.
persp()expects z as a matrix, and with default arguments x and y have lengthsnrow(z)andncol(z), in ascending order; build it withouter()as in step 4. - scatterplot3d colours ignore my col setting. That is expected when
highlight.3d = TRUE. - The plot looks squashed or stretched. Adjust
scale.yinscatterplot3d, orexpandandscaleinpersp().
Free alternatives
All three tools above are free R components; this table summarises the choice.
| Need | Use | Source basis |
|---|---|---|
| Static 3D point cloud inside base R graphics | scatterplot3d |
CRAN package page and manual |
| Fitted plane or projection helpers on that cloud | scatterplot3d helpers (plane3d, xyz.convert) |
Package manual |
| Rotatable scene, or STL/OBJ/PLY/WebGL export | rgl |
CRAN package page |
| Surface from a z grid, no extra package | persp() |
Base R graphics documentation |
Add points to a persp() surface |
trans3d() with the returned matrix |
Base R graphics documentation |
If you are comparing R with other analysis environments for plotting work, see R vs Stata for statistical analysis and what MATLAB is used for. For a related view of high-dimensional data in 2D, see UMAP vs t-SNE.
FAQ
What does “r 3d” mean?
In this guide it means drawing 3D plots in R: point clouds with scatterplot3d or rgl, and surfaces with persp().
Which package makes an interactive 3D plot in R?
rgl. Its plot3d() draws a 3D scatterplot in an OpenGL window, and its CRAN page lists WebGL among the formats it can save to.
Can I save a 3D plot as a file?
rgl lists WebGL, PLY, OBJ and STL for 3D output and PNG, PostScript, SVG and PGF for 2D output. The static tools draw to whichever R graphics device is open, so use the device you would use for any other base R plot.
How do I add a regression plane?
Save the scatterplot3d result and call plane3d() on it with an lm object, as in step 2.
Sources
- CRAN, scatterplot3d: 3D Scatter Plot, version 0.3-45 (checked 2026-10-29)
- CRAN, scatterplot3d reference manual (checked 2026-10-29)
- CRAN, rgl: 3D Visualization Using OpenGL, version 1.3.36 (checked 2026-10-29)
- rgl documentation, plot3d reference (development version, read 2026-10-29)
- R documentation, persp: Perspective Plots (checked 2026-10-29)








