{
"title": "surf",
"category": "plotting",
"keywords": [
"surf",
"surface plot",
"3-D surface",
"height map",
"matlab surf",
"gpu surface rendering"
],
"summary": "Create shaded 3-D surface plots from grids or mesh coordinates with GPU-backed rendering and MATLAB `surf` semantics.",
"hero_image": "https://web.runmatstatic.com/builtin-image/runmat-matlab-plot-surf-damped-radial-ripple.webp",
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [
"single",
"double"
],
"broadcasting": "none",
"notes": "`surf` uses the shared surface pipeline. GPU-friendly inputs can stay resident through the rendering path when the plotting device is available."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 3,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::plotting::surf::tests",
"integration": "runmat-plot/tests/renderer_tests.rs"
},
"description": "`surf` creates shaded 3-D surface plots from either vector axes plus a height grid or meshgrid-style coordinate matrices. In RunMat it returns a surface handle, participates in the same graphics-object system as other plotting builtins, and uses the shared surface rendering path that also underpins image and composite surface workflows.",
"behaviors": [
"`surf(Z)` uses implicit axes, while `surf(X, Y, Z)` accepts either vector axes or meshgrid-style coordinate matrices, following MATLAB `surf` call forms.",
"The returned value is a surface handle that can be inspected and updated through `get` and `set`.",
"Surface plots naturally interact with `view`, `zlabel`, `colorbar`, `colormap`, and `shading` because they all operate on the same subplot-local axes state.",
"GPU-backed surface rendering is the preferred path when exported buffers and the shared plotting device are available; otherwise RunMat gathers once and renders the same surface semantics on the host path.",
"`surf` is the shaded/fill-oriented member of the surface family, while `mesh` emphasizes wireframe rendering and `surfc` adds contour overlays."
],
"examples": [
{
"description": "Create a shaded surface from a height grid",
"input": "[X, Y] = meshgrid(linspace(-2, 2, 80), linspace(-2, 2, 80));\nZ = sin(X.^2 + Y.^2) ./ (1 + X.^2 + Y.^2);\nsurf(X, Y, Z);"
},
{
"description": "Pair surf with colormap, shading, and colorbar",
"input": "[X, Y] = meshgrid(linspace(-3, 3, 100), linspace(-3, 3, 100));\nZ = cos(X) .* sin(Y);\nsurf(X, Y, Z);\ncolormap('jet');\nshading interp;\ncolorbar;"
},
{
"description": "Adjust camera state and z-axis labeling for a surface",
"input": "[X, Y] = meshgrid(linspace(-2, 2, 60), linspace(-2, 2, 60));\nZ = X .* exp(-X.^2 - Y.^2);\nh = surf(X, Y, Z);\nzlabel('Height');\nview(45, 30);\nget(h, 'Type')",
"output": "ans =\n 'surface'"
},
{
"description": "Damped radial ripple with interpolated shading",
"input": "[X, Y] = meshgrid(linspace(-4, 4, 200), linspace(-4, 4, 200));\nR = sqrt(X.^2 + Y.^2) + 0.01;\nZ = sin(3*R) ./ R;\n\nsurf(X, Y, Z);\nshading interp;\ncolormap('turbo');\ncolorbar;\ntitle('Damped Radial Wavefield');\nxlabel('x');\nylabel('y');\nzlabel('Amplitude');\nview(35, 25);",
"image_webp": "https://web.runmatstatic.com/builtin-image/runmat-matlab-plot-surf-damped-radial-ripple.webp"
}
],
"faqs": [
{
"question": "How do I change the colormap on a surf plot?",
"answer": "Call `colormap` after `surf` to swap the palette. The colormap applies to the current axes, so it works per-subplot.\n\n```matlab\nsurf(X, Y, Z);\ncolormap('turbo');\n```\n\nAny named colormap (`'parula'`, `'jet'`, `'hot'`, etc.) or an Nx3 matrix of RGB values works here."
},
{
"question": "How do I rotate or set the 3-D viewing angle?",
"answer": "Use `view(az, el)` where `az` is the azimuth in degrees and `el` is the elevation. For example, `view(45, 30)` gives you a 45-degree orbit at 30 degrees above the xy-plane. `view(3)` is a shortcut for the default 3-D perspective, and `view(2)` snaps to a top-down 2-D projection."
},
{
"question": "What's the difference between surf and mesh?",
"answer": "`surf` renders a shaded, filled surface where face colors come from the colormap. `mesh` draws only the wireframe grid lines with no face fill. Use `surf` when you want to visualize the shape as a solid surface, and `mesh` when you want to see through the geometry to understand the grid structure underneath."
}
],
"links": [
{
"label": "mesh",
"url": "./mesh"
},
{
"label": "surfc",
"url": "./surfc"
},
{
"label": "view",
"url": "./view"
},
{
"label": "zlabel",
"url": "./zlabel"
},
{
"label": "colormap",
"url": "./colormap"
},
{
"label": "shading",
"url": "./shading"
},
{
"label": "colorbar",
"url": "./colorbar"
},
{
"label": "Choosing the right plot type",
"url": "/docs/plotting/choosing-the-right-plot-type"
},
{
"label": "Styling plots and axes",
"url": "/docs/plotting/styling-plots-and-axes"
},
{
"label": "Plot replay and export",
"url": "/docs/plotting/plot-replay-and-export"
},
{
"label": "Complete plotting guide",
"url": "/blog/matlab-plotting-guide"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/plotting/ops/surf.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/plotting/ops/surf.rs"
},
"gpu_residency": "`surf` preserves GPU residency on the happy path through the shared surface rendering pipeline. When a direct GPU render path is not available for the active input combination, RunMat gathers once and builds the same surface plot semantics on the fallback path.",
"gpu_behavior": [
"The surface pipeline is shared across multiple plot families, which keeps `surf` aligned with image, contour-composite, and surface-style rendering behavior.",
"Surface color limits and subplot-local metadata stay consistent regardless of whether the geometry is emitted from GPU buffers or host tensors."
]
}