--- title: "Experimental 3D, mesh, and surface WebGL layers" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Experimental 3D, mesh, and surface WebGL layers} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} ggwebgl_truthy <- function(x) { tolower(x) %in% c("1", "true", "yes", "y") } ggwebgl_ci_vars <- c( "CI", "GITHUB_ACTIONS", "GITLAB_CI", "BUILDKITE", "TRAVIS", "APPVEYOR", "CIRCLECI", "JENKINS_URL" ) ggwebgl_is_ci <- any(vapply(Sys.getenv(ggwebgl_ci_vars), ggwebgl_truthy, logical(1))) ggwebgl_is_check <- nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_")) ggwebgl_eval_code <- !ggwebgl_is_ci && !ggwebgl_is_check && ( ggwebgl_truthy(Sys.getenv("NOT_CRAN")) || ggwebgl_truthy(Sys.getenv("GGWEBGL_EVAL_COVERAGE_VIGNETTE")) ) ggwebgl_eval_widgets <- ggwebgl_eval_code && ggwebgl_truthy(Sys.getenv("GGWEBGL_EVAL_LIVE_WIDGETS")) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = ggwebgl_eval_code ) library(ggplot2) library(ggWebGL) ``` The 3D and indexed-geometry APIs are exported for browser-side WebGL rendering, but they remain experimental because camera, picking, and material behavior may still evolve. Evaluation is disabled during CRAN, package checks, and CI unless explicitly enabled with `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` or `NOT_CRAN=true`. Live WebGL widgets are additionally disabled unless `GGWEBGL_EVAL_LIVE_WIDGETS=true` is set. Rich local or pkgdown builds should set both `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` and `GGWEBGL_EVAL_LIVE_WIDGETS=true`. ```{r coverage-eval-note, echo = FALSE, results = "asis", eval = TRUE} if (!ggwebgl_eval_code) { cat( "> Example chunks are shown but not evaluated in this build. ", "Set `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` or `NOT_CRAN=true` ", "to evaluate them during a local non-CI render.\n", sep = "" ) } else if (!ggwebgl_eval_widgets) { cat( "> Non-widget code chunks may evaluate in this build, but live WebGL ", "widgets are skipped. Set `GGWEBGL_EVAL_LIVE_WIDGETS=true` as well ", "to render browser-side widgets locally.\n", sep = "" ) } ``` # Experimental 3D, Mesh, and Surface Layers Use `coord_webgl_3d()` to opt into a 3D camera path for grammar-style plots. The same scene contract can also be produced through renderer-ready mesh and surface helpers. ## Applet: 3D helix path ```{r three-d-helix-path, eval = ggwebgl_eval_widgets} helix_t <- seq(0, 4 * pi, length.out = 80) helix <- data.frame( x = cos(helix_t), y = sin(helix_t), z = helix_t / max(helix_t), time = helix_t, group = "helix" ) p <- ggplot(helix, aes(x, y, z = z, group = group, time = time)) + geom_path3d_webgl(colour = "#2563eb") + coord_webgl_3d() + labs(title = "3D helix path") ggplot_webgl(p, height = 420) ``` ## Applet: Structured surface Structured surfaces use a regular grid. ```{r structured-surface, eval = ggwebgl_eval_widgets} surface_grid <- expand.grid( x = seq(-1, 1, length.out = 12), y = seq(-1, 1, length.out = 12), KEEP.OUT.ATTRS = FALSE ) surface_grid$z <- with(surface_grid, exp(-(x^2 + y^2))) p <- ggplot(surface_grid, aes(x, y, z = z, fill = z)) + geom_surface_webgl(shading = "surface_height_colormap") + coord_webgl_3d() + labs(title = "Structured surface") ggplot_webgl(p, height = 420) ``` ## Applet: Unstructured mesh Unstructured meshes can be supplied with explicit vertices and triangle indices. ```{r unstructured-mesh, eval = ggwebgl_eval_widgets} mesh_vertices <- data.frame( x = c(0, 1, 0, 0), y = c(0, 0, 1, 0), z = c(0, 0, 0, 1), scalar = c(0, 1, 1, 0.5), i = c(1, 1, 1, 2), j = c(2, 2, 3, 3), k = c(3, 4, 4, 4) ) p <- ggplot(mesh_vertices, aes(x, y, z = z, i = i, j = j, k = k, scalar = scalar)) + geom_mesh_webgl(shading = "mesh_scalar_colormap") + coord_webgl_3d() + labs(title = "Unstructured mesh") ggplot_webgl(p, height = 420) ``` # 3D View and Camera Notes - `coord_webgl_3d()` requests a 3D coordinate system and an orbit-style camera. - Surface layers are structured-grid primitives; arbitrary triangle data belongs in mesh layers. - The 3D APIs are experimental and should be treated as browser-side rendering paths, not as native GPU preprocessing pipelines.