Skip to main content
v2026.11,858 entries · CC-BY 4.0

3D Plots in R: scatterplot3d, rgl and persp

How to make 3D plots in R with scatterplot3d, rgl and persp: which to choose, CRAN install, working code, fitted planes and how to read the angles.

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(), theta is the azimuth and phi the colatitude; the defaults are 0 and 15. In scatterplot3d, angle is 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 = TRUE points are coloured by their y coordinate, and the color argument is ignored. The colour is therefore not an extra variable.
  • Axis values. persp() defaults to ticktype = "simple", which draws an arrow only; "detailed" draws ordinary ticks so values can be read.
  • Shading. In persp(), shade between 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; check sum(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 lengths nrow(z) and ncol(z), in ascending order; build it with outer() 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.y in scatterplot3d, or expand and scale in persp().

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

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about 3D Plots in R: scatterplot3d, rgl and persp

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.