
Qgis Impl 3d Visualization
- 8 installs
- 29 repo stars
- Updated July 8, 2026
- openaec-foundation/qgis-claude-skill-package
Helps with ai & agent building tasks.
About
qgis-impl-3d-visualization is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- qgis-impl-3d-visualization
- AI & Agent Building
- AI-coding skill
Qgis Impl 3d Visualization by the numbers
- 8 all-time installs (skills.sh)
- Ranked #12,321 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/qgis-claude-skill-package --skill qgis-impl-3d-visualizationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 29 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/qgis-claude-skill-package ↗ |
What it does
Helps with ai & agent building tasks.
Files
qgis-impl-3d-visualization
Quick Reference
Import Pattern
3D classes live in qgis._3d (underscore prefix because Python modules cannot start with a digit). Base classes live in qgis.core.
# 3D-specific classes: ALWAYS import from qgis._3d
from qgis._3d import (
Qgs3DMapSettings,
QgsVectorLayer3DRenderer,
QgsPolygon3DSymbol,
QgsLine3DSymbol,
QgsPoint3DSymbol,
QgsPhongMaterialSettings,
QgsGoochMaterialSettings,
QgsMetalRoughMaterialSettings,
QgsPointLightSettings,
QgsDirectionalLightSettings,
QgsCameraPose,
QgsPointCloudLayer3DRenderer,
QgsLayoutItem3DMap,
QgsFlatTerrainSettings,
QgsDemTerrainSettings,
)
# Base classes: ALWAYS import from qgis.core
from qgis.core import QgsAbstract3DSymbol, QgsAbstract3DRendererSymbol Construction Pattern
| Symbol Class | Construction | Notes |
|---|---|---|
QgsPolygon3DSymbol | QgsPolygon3DSymbol.create() | Factory method returns QgsAbstract3DSymbol |
QgsLine3DSymbol | QgsLine3DSymbol.create() | Factory method returns QgsAbstract3DSymbol |
QgsPoint3DSymbol | QgsPoint3DSymbol() | Regular constructor |
Material Types
| Material | Use Case | Since |
|---|---|---|
QgsPhongMaterialSettings | Standard Phong shading (default choice) | 3.0+ |
QgsGoochMaterialSettings | Non-photorealistic warm/cool rendering | 3.16+ |
QgsMetalRoughMaterialSettings | PBR metallic-roughness | 3.36+ |
Terrain Providers
| Provider | Class | Use Case |
|---|---|---|
| Flat | QgsFlatTerrainSettings | Flat plane at a fixed elevation |
| DEM | QgsDemTerrainSettings | Raster elevation model terrain |
| Mesh | QgsMeshTerrainSettings | Mesh layer as terrain |
---
Critical Warnings
NEVER use setMaterial() on 3D symbols — it is DEPRECATED and removed. ALWAYS use setMaterialSettings() instead. Old code examples referencing setMaterial() will fail.
NEVER import 3D classes from qgis.core — they live in qgis._3d. The ONLY exceptions are QgsAbstract3DSymbol and QgsAbstract3DRenderer, which live in qgis.core.
NEVER construct QgsPolygon3DSymbol or QgsLine3DSymbol with a regular constructor — ALWAYS use the create() factory method. QgsPoint3DSymbol is the exception and uses a regular constructor.
ALWAYS treat all qgis._3d classes as tech preview / unstable API. Method signatures MAY change between QGIS minor versions. ALWAYS verify against the API docs for your specific QGIS version.
ALWAYS use setExtent() on Qgs3DMapSettings before other configuration — it auto-sets the origin to the extent center, which other coordinate-dependent settings rely on.
NEVER call deprecated terrain methods on Qgs3DMapSettings (setTerrainVerticalScale(), setMaxTerrainScreenError(), setMapTileResolution()) — ALWAYS configure these through the terrain settings object instead.
---
Decision Tree
Which symbol class do I need?
Geometry type?
├── Point → QgsPoint3DSymbol()
├── Line → QgsLine3DSymbol.create()
├── Polygon → QgsPolygon3DSymbol.create()
└── Point Cloud → QgsPointCloudLayer3DRenderer + QgsPointCloud3DSymbol subclassWhich material do I need?
Visual effect needed?
├── Standard shading (most cases) → QgsPhongMaterialSettings
├── Non-photorealistic / technical drawing → QgsGoochMaterialSettings (3.16+)
└── Physically-based rendering → QgsMetalRoughMaterialSettings (3.36+)Which terrain provider do I need?
Terrain data available?
├── No elevation data → QgsFlatTerrainSettings
├── Raster DEM layer → QgsDemTerrainSettings
├── Mesh layer → QgsMeshTerrainSettings
└── Project elevation properties → settings.configureTerrainFromProject()---
Essential Patterns
Pattern 1: Configure a 3D Scene
from qgis._3d import Qgs3DMapSettings, QgsFlatTerrainSettings
from qgis.core import QgsCoordinateReferenceSystem, QgsRectangle, QgsProject
from qgis.PyQt.QtGui import QColor
settings = Qgs3DMapSettings()
settings.setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))
settings.setExtent(QgsRectangle(1000000, 6000000, 2000000, 7000000))
settings.setBackgroundColor(QColor(135, 206, 235))
settings.setSelectionColor(QColor(255, 255, 0))
# Flat terrain
terrain = QgsFlatTerrainSettings()
terrain.setElevation(0.0)
settings.setTerrainSettings(terrain)
# Add layers
settings.setLayers(QgsProject.instance().mapLayers().values())Pattern 2: DEM Terrain
from qgis._3d import QgsDemTerrainSettings
terrain = QgsDemTerrainSettings()
terrain.setLayer(dem_raster_layer)
terrain.setResolution(16)
terrain.setSkirtHeight(10.0)
settings.setTerrainSettings(terrain)
# Terrain rendering options
settings.setTerrainRenderingEnabled(True)
settings.setTerrainShadingEnabled(True)
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(180, 160, 120))
settings.setTerrainShadingMaterial(material)Pattern 3: Extruded Building Polygons
from qgis._3d import (
QgsVectorLayer3DRenderer,
QgsPolygon3DSymbol,
QgsPhongMaterialSettings,
)
from qgis.PyQt.QtGui import QColor
material = QgsPhongMaterialSettings()
material.setAmbient(QColor(100, 100, 100))
material.setDiffuse(QColor(180, 180, 160))
material.setSpecular(QColor(255, 255, 255))
material.setShininess(50.0)
symbol = QgsPolygon3DSymbol.create()
symbol.setExtrusionHeight(15.0)
symbol.setMaterialSettings(material)
symbol.setEdgesEnabled(True)
symbol.setEdgeColor(QColor(0, 0, 0))
symbol.setEdgeWidth(1.0)
renderer = QgsVectorLayer3DRenderer(symbol)
building_layer.setRenderer3D(renderer)Pattern 4: 3D Point Symbols
from qgis._3d import QgsVectorLayer3DRenderer, QgsPoint3DSymbol, QgsPhongMaterialSettings
from qgis.PyQt.QtGui import QColor
from qgis.core import Qgis
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(255, 0, 0))
material.setShininess(100.0)
symbol = QgsPoint3DSymbol()
symbol.setShape(Qgis.Point3DShape.Sphere)
symbol.setShapeProperties({"radius": 5.0})
symbol.setMaterialSettings(material)
renderer = QgsVectorLayer3DRenderer(symbol)
point_layer.setRenderer3D(renderer)Pattern 5: 3D Line Symbols
from qgis._3d import QgsVectorLayer3DRenderer, QgsLine3DSymbol, QgsPhongMaterialSettings
from qgis.PyQt.QtGui import QColor
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(0, 100, 200))
symbol = QgsLine3DSymbol.create()
symbol.setWidth(3.0)
symbol.setExtrusionHeight(10.0)
symbol.setMaterialSettings(material)
renderer = QgsVectorLayer3DRenderer(symbol)
line_layer.setRenderer3D(renderer)Pattern 6: Lighting Configuration
from qgis._3d import QgsPointLightSettings, QgsDirectionalLightSettings
from qgis.core import QgsVector3D
from qgis.PyQt.QtGui import QColor
# Point light: illuminates from a specific position
point_light = QgsPointLightSettings()
point_light.setPosition(QgsVector3D(0, 1000, 0))
point_light.setColor(QColor(255, 255, 255))
point_light.setIntensity(1.0)
point_light.setConstantAttenuation(1.0)
point_light.setLinearAttenuation(0.0)
point_light.setQuadraticAttenuation(0.0)
# Directional light: simulates sunlight
dir_light = QgsDirectionalLightSettings()
dir_light.setDirection(QgsVector3D(0.5, -1.0, 0.5))
dir_light.setColor(QColor(255, 255, 230))
dir_light.setIntensity(0.8)
settings.setLightSources([point_light, dir_light])Pattern 7: Camera Pose
from qgis._3d import QgsCameraPose
from qgis.core import QgsVector3D
camera = QgsCameraPose()
camera.setCenterPoint(QgsVector3D(1500000, 6500000, 0))
camera.setDistanceFromCenterPoint(500)
camera.setPitchAngle(45.0) # 0 = top-down, 90 = horizontal
camera.setHeadingAngle(0.0) # North-facingPattern 8: Eye Dome Lighting (Point Clouds)
# Enhances depth perception: especially useful for point clouds
settings.setEyeDomeLightingEnabled(True)
settings.setEyeDomeLightingStrength(1000.0)
settings.setEyeDomeLightingDistance(1)Pattern 9: 3D Map in Print Layout
from qgis.core import QgsProject, QgsLayout, QgsLayoutSize, QgsLayoutPoint, QgsUnitTypes
from qgis._3d import QgsLayoutItem3DMap, QgsCameraPose
from qgis.core import QgsVector3D
project = QgsProject.instance()
layout = QgsLayout(project)
map_3d = QgsLayoutItem3DMap(layout)
camera = QgsCameraPose()
camera.setCenterPoint(QgsVector3D(0, 0, 0))
camera.setDistanceFromCenterPoint(500)
camera.setPitchAngle(45.0)
camera.setHeadingAngle(0.0)
map_3d.setCameraPose(camera)
# map_3d.setMapSettings(configured_3d_settings)
map_3d.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters))
map_3d.attemptMove(QgsLayoutPoint(10, 10, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(map_3d)---
Common Operations
Altitude Clamping Modes
Control how features relate to terrain elevation:
from qgis.core import Qgis
# Absolute: Z values are absolute heights (ignore terrain)
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Absolute)
# Relative: Z values are added to terrain elevation
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Relative)
# Terrain: features are draped onto terrain (Z values ignored)
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Terrain)Altitude Binding (Polygons/Lines)
# Vertex: each vertex clamped individually (follows terrain closely)
symbol.setAltitudeBinding(Qgis.AltitudeBinding.Vertex)
# Centroid: entire feature clamped by centroid height (flat placement)
symbol.setAltitudeBinding(Qgis.AltitudeBinding.Centroid)Coordinate Conversion
from qgis.core import QgsVector3D
# Map CRS coordinates to 3D world coordinates (applies x, -z, y swap)
world = settings.mapToWorldCoordinates(QgsVector3D(x_map, y_map, z_map))
# 3D world coordinates back to map CRS
map_coords = settings.worldToMapCoordinates(QgsVector3D(x_world, y_world, z_world))Serialize / Restore 3D Settings
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import QgsReadWriteContext, QgsProject
# Save
doc = QDomDocument()
elem = settings.writeXml(doc, QgsReadWriteContext())
doc.appendChild(elem)
# Restore
settings2 = Qgs3DMapSettings()
settings2.readXml(elem, QgsReadWriteContext())
settings2.resolveReferences(QgsProject.instance())Point Cloud 3D Rendering
from qgis._3d import (
QgsPointCloudLayer3DRenderer,
QgsRgbPointCloud3DSymbol,
QgsSingleColorPointCloud3DSymbol,
QgsClassificationPointCloud3DSymbol,
QgsColorRampPointCloud3DSymbol,
)
# RGB point cloud
symbol = QgsRgbPointCloud3DSymbol()
renderer = QgsPointCloudLayer3DRenderer()
renderer.setSymbol(symbol)
point_cloud_layer.setRenderer3D(renderer)PBR Material (QGIS 3.36+)
from qgis._3d import QgsMetalRoughMaterialSettings
from qgis.PyQt.QtGui import QColor
material = QgsMetalRoughMaterialSettings()
material.setBaseColor(QColor(200, 200, 200))
material.setMetalness(0.8) # 0.0 = dielectric, 1.0 = metal
material.setRoughness(0.3) # 0.0 = mirror, 1.0 = matteGooch Material (QGIS 3.16+)
from qgis._3d import QgsGoochMaterialSettings
from qgis.PyQt.QtGui import QColor
material = QgsGoochMaterialSettings()
material.setWarm(QColor(255, 200, 100))
material.setCool(QColor(100, 150, 255))
material.setDiffuse(QColor(200, 200, 200))
material.setSpecular(QColor(255, 255, 255))
material.setShininess(50.0)
material.setAlpha(0.25)
material.setBeta(0.5)---
Version Compatibility
| Feature | Minimum QGIS Version |
|---|---|
| Basic 3D (symbols, Phong material) | 3.0 |
| QgsLayoutItem3DMap | 3.4 |
| Camera field of view | 3.8 |
| Directional lights, Gooch material | 3.16 |
| Shadows (QgsShadowSettings) | 3.16 |
| Eye Dome Lighting, camera navigation mode | 3.18 |
| Light sources list API | 3.26 |
| Material opacity | 3.26 |
| PBR material (MetalRough) | 3.36 |
| Material coefficients (ambient/diffuse/specular) | 3.36 |
| Terrain settings API (setTerrainSettings) | 3.42 |
---
Reference Links
- references/methods.md -- Complete API signatures for all 3D classes
- references/examples.md -- Full working code examples
- references/anti-patterns.md -- Common mistakes and how to avoid them
Official Sources
- https://qgis.org/pyqgis/3.40/_3d/index.html
- https://qgis.org/pyqgis/master/_3d/Qgs3DMapSettings.html
- https://qgis.org/pyqgis/master/_3d/QgsPolygon3DSymbol.html
- https://qgis.org/pyqgis/master/_3d/QgsVectorLayer3DRenderer.html
qgis-impl-3d-visualization — Anti-Patterns
---
AP-1: Using setMaterial() Instead of setMaterialSettings()
Wrong:
symbol = QgsPolygon3DSymbol.create()
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(200, 100, 50))
symbol.setMaterial(material) # DEPRECATED / REMOVED — will raise AttributeErrorRight:
symbol = QgsPolygon3DSymbol.create()
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(200, 100, 50))
symbol.setMaterialSettings(material) # Correct method nameWhy: setMaterial() was replaced by setMaterialSettings() in a breaking API change. Old tutorials and plugins (including some CityJSON examples) still reference the old method. ALWAYS use setMaterialSettings().
---
AP-2: Importing 3D Classes from qgis.core
Wrong:
from qgis.core import QgsPolygon3DSymbol, QgsPhongMaterialSettings # ImportErrorRight:
from qgis._3d import QgsPolygon3DSymbol, QgsPhongMaterialSettingsWhy: All 3D-specific classes live in qgis._3d, not qgis.core. The underscore prefix exists because Python modules cannot start with a digit. The ONLY exceptions are the abstract base classes QgsAbstract3DSymbol and QgsAbstract3DRenderer, which live in qgis.core.
---
AP-3: Constructing Polygon/Line Symbols with Regular Constructor
Wrong:
symbol = QgsPolygon3DSymbol() # May not work — factory pattern required
symbol = QgsLine3DSymbol() # May not work — factory pattern requiredRight:
symbol = QgsPolygon3DSymbol.create() # Factory method
symbol = QgsLine3DSymbol.create() # Factory methodWhy: QgsPolygon3DSymbol and QgsLine3DSymbol use a factory pattern via create(). QgsPoint3DSymbol is the exception — it uses a regular constructor QgsPoint3DSymbol(). Mixing up the construction patterns leads to errors or unexpected behavior.
---
AP-4: Forgetting setExtent() Before Other Configuration
Wrong:
settings = Qgs3DMapSettings()
settings.setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))
settings.setLayers([layer])
# No setExtent() — origin defaults to (0,0), coordinates will be wrongRight:
settings = Qgs3DMapSettings()
settings.setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))
settings.setExtent(layer.extent()) # Auto-sets origin to extent center
settings.setLayers([layer])Why: setExtent() automatically sets the scene origin to the center of the extent. Without it, the origin defaults to (0,0) and all 3D world coordinates will be offset from the data, causing features to render far from the camera or not appear at all.
---
AP-5: Using Deprecated Terrain Methods on Qgs3DMapSettings
Wrong:
settings.setTerrainVerticalScale(2.0) # Deprecated
settings.setMaxTerrainScreenError(3.0) # Deprecated
settings.setMapTileResolution(512) # DeprecatedRight:
terrain = QgsDemTerrainSettings()
terrain.setLayer(dem_layer)
terrain.setResolution(16)
settings.setTerrainSettings(terrain)Why: Since QGIS 3.42, terrain configuration moved to dedicated terrain settings objects. The old methods on Qgs3DMapSettings are deprecated and may be removed in future versions. ALWAYS use setTerrainSettings() with the appropriate terrain settings class.
---
AP-6: Ignoring the Unstable API Warning
Wrong:
# Assuming 3D API is stable across QGIS versions
# Hardcoding method names without version checks
symbol.setExtrusionFaces(Qgis.ExtrusionFaces.Top) # Added in a specific versionRight:
# Document minimum version in comments
# Qgis.ExtrusionFaces requires QGIS 3.x+
symbol.setExtrusionFaces(Qgis.ExtrusionFaces.Top)
# For maximum compatibility, check QGIS version
from qgis.core import Qgis
if Qgis.versionInt() >= 34200:
settings.setTerrainSettings(terrain)Why: ALL classes in qgis._3d carry a "tech preview / unstable API" warning. Method signatures, class names, and enum values can change between QGIS minor versions. ALWAYS document the minimum QGIS version for each feature used, and add version checks when targeting multiple QGIS releases.
---
AP-7: Not Resolving References After readXml()
Wrong:
settings2 = Qgs3DMapSettings()
settings2.readXml(elem, QgsReadWriteContext())
# Immediately using settings2 — layer references are unresolvedRight:
settings2 = Qgs3DMapSettings()
settings2.readXml(elem, QgsReadWriteContext())
settings2.resolveReferences(QgsProject.instance()) # Resolve layer referencesWhy: After readXml(), layer references stored in the XML are just IDs. Without calling resolveReferences(), the settings object will have null layer references and terrain layers will not render.
---
AP-8: Point Light with Zero Attenuation
Wrong:
light = QgsPointLightSettings()
light.setPosition(QgsVector3D(0, 1000, 0))
light.setIntensity(1.0)
# Default attenuation may be 0,0,0 — light has infinite range, washes out sceneRight:
light = QgsPointLightSettings()
light.setPosition(QgsVector3D(0, 1000, 0))
light.setIntensity(1.0)
light.setConstantAttenuation(1.0)
light.setLinearAttenuation(0.0)
light.setQuadraticAttenuation(0.0)Why: ALWAYS explicitly set attenuation values for point lights. The attenuation formula is Total = A0 + A1*D + A2*D^2. With all values at zero, light intensity is undefined. Setting constantAttenuation to 1.0 with zero linear and quadratic values gives uniform light with no distance falloff.
---
AP-9: Missing Terrain Settings When Using DEM
Wrong:
terrain = QgsDemTerrainSettings()
terrain.setLayer(dem_layer)
settings.setTerrainSettings(terrain)
# Terrain renders with gaps between tilesRight:
terrain = QgsDemTerrainSettings()
terrain.setLayer(dem_layer)
terrain.setResolution(16)
terrain.setSkirtHeight(10.0) # Prevents gaps between terrain tiles
settings.setTerrainSettings(terrain)Why: Without setSkirtHeight(), terrain tiles can have visible gaps at their edges due to level-of-detail transitions. ALWAYS set a skirt height for DEM terrain to prevent visual artifacts.
---
AP-10: Using Absolute Altitude Clamping Without Z Values
Wrong:
# Layer has no Z coordinates
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Absolute)
# Features render at Z=0, flat on ground — no visible 3D effectRight:
# For 2D data, use Terrain clamping to drape on terrain
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Terrain)
# Or use Relative with an offset
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Relative)
symbol.setOffset(5.0) # 5 meters above terrainWhy: Absolute clamping uses the feature's Z values directly. If the data has no Z coordinates, all features render at Z=0 (ground level), making them invisible if terrain is also at ground level. For 2D data, ALWAYS use Terrain clamping (drape on surface) or Relative with an offset.
---
AP-11: Forgetting to Add Layer to 3D Scene
Wrong:
renderer = QgsVectorLayer3DRenderer(symbol)
layer.setRenderer3D(renderer)
# Layer has a 3D renderer but is not in settings.setLayers() — nothing rendersRight:
renderer = QgsVectorLayer3DRenderer(symbol)
layer.setRenderer3D(renderer)
settings.setLayers([layer]) # ALWAYS include the layer in the sceneWhy: Setting a 3D renderer on a layer configures HOW it renders in 3D, but Qgs3DMapSettings.setLayers() controls WHICH layers are included in the 3D scene. Both are required for a layer to appear in the 3D view.
qgis-impl-3d-visualization — Examples
All examples use [CONFIRMED] API methods from PyQGIS 3.40+. No official 3D cookbook exists,
so these are reconstructed from verified API signatures.
---
Example 1: Complete 3D Scene with Extruded Buildings
from qgis.core import (
QgsProject,
QgsCoordinateReferenceSystem,
QgsRectangle,
QgsVector3D,
)
from qgis._3d import (
Qgs3DMapSettings,
QgsFlatTerrainSettings,
QgsVectorLayer3DRenderer,
QgsPolygon3DSymbol,
QgsPhongMaterialSettings,
QgsPointLightSettings,
QgsDirectionalLightSettings,
)
from qgis.PyQt.QtGui import QColor
project = QgsProject.instance()
buildings = project.mapLayersByName("buildings")[0]
# --- Scene setup ---
settings = Qgs3DMapSettings()
settings.setCrs(QgsCoordinateReferenceSystem("EPSG:28992"))
settings.setExtent(buildings.extent())
settings.setBackgroundColor(QColor(200, 220, 240))
# Flat terrain
terrain = QgsFlatTerrainSettings()
terrain.setElevation(0.0)
settings.setTerrainSettings(terrain)
# --- Building material ---
material = QgsPhongMaterialSettings()
material.setAmbient(QColor(80, 80, 80))
material.setDiffuse(QColor(200, 190, 170))
material.setSpecular(QColor(255, 255, 255))
material.setShininess(80.0)
# --- 3D building symbol ---
symbol = QgsPolygon3DSymbol.create()
symbol.setExtrusionHeight(12.0)
symbol.setMaterialSettings(material)
symbol.setEdgesEnabled(True)
symbol.setEdgeColor(QColor(60, 60, 60))
symbol.setEdgeWidth(1.0)
# --- Assign renderer ---
renderer = QgsVectorLayer3DRenderer(symbol)
buildings.setRenderer3D(renderer)
# --- Lighting ---
sun = QgsDirectionalLightSettings()
sun.setDirection(QgsVector3D(0.5, -1.0, 0.5))
sun.setColor(QColor(255, 255, 230))
sun.setIntensity(0.8)
fill = QgsPointLightSettings()
fill.setPosition(QgsVector3D(0, 500, 0))
fill.setColor(QColor(200, 200, 255))
fill.setIntensity(0.3)
fill.setConstantAttenuation(1.0)
fill.setLinearAttenuation(0.0)
fill.setQuadraticAttenuation(0.0)
settings.setLightSources([sun, fill])
settings.setLayers([buildings])---
Example 2: DEM Terrain with Draped Roads
from qgis.core import QgsProject, QgsCoordinateReferenceSystem
from qgis._3d import (
Qgs3DMapSettings,
QgsDemTerrainSettings,
QgsVectorLayer3DRenderer,
QgsLine3DSymbol,
QgsPhongMaterialSettings,
)
from qgis.PyQt.QtGui import QColor
from qgis.core import Qgis
project = QgsProject.instance()
dem = project.mapLayersByName("elevation")[0]
roads = project.mapLayersByName("roads")[0]
# --- Scene ---
settings = Qgs3DMapSettings()
settings.setCrs(dem.crs())
settings.setExtent(dem.extent())
# --- DEM terrain ---
terrain = QgsDemTerrainSettings()
terrain.setLayer(dem)
terrain.setResolution(16)
terrain.setSkirtHeight(10.0)
settings.setTerrainSettings(terrain)
settings.setTerrainRenderingEnabled(True)
settings.setTerrainShadingEnabled(True)
terrain_material = QgsPhongMaterialSettings()
terrain_material.setDiffuse(QColor(160, 140, 100))
settings.setTerrainShadingMaterial(terrain_material)
# --- Roads draped on terrain ---
road_material = QgsPhongMaterialSettings()
road_material.setDiffuse(QColor(80, 80, 80))
road_symbol = QgsLine3DSymbol.create()
road_symbol.setWidth(5.0)
road_symbol.setAltitudeClamping(Qgis.AltitudeClamping.Terrain)
road_symbol.setMaterialSettings(road_material)
road_renderer = QgsVectorLayer3DRenderer(road_symbol)
roads.setRenderer3D(road_renderer)
settings.setLayers([dem, roads])---
Example 3: Point Cloud with Eye Dome Lighting
from qgis.core import QgsProject
from qgis._3d import (
Qgs3DMapSettings,
QgsFlatTerrainSettings,
QgsPointCloudLayer3DRenderer,
QgsRgbPointCloud3DSymbol,
)
from qgis.PyQt.QtGui import QColor
project = QgsProject.instance()
pc_layer = project.mapLayersByName("point_cloud")[0]
# --- Scene ---
settings = Qgs3DMapSettings()
settings.setCrs(pc_layer.crs())
settings.setExtent(pc_layer.extent())
settings.setBackgroundColor(QColor(30, 30, 30))
terrain = QgsFlatTerrainSettings()
settings.setTerrainSettings(terrain)
# --- Point cloud renderer ---
symbol = QgsRgbPointCloud3DSymbol()
renderer = QgsPointCloudLayer3DRenderer()
renderer.setSymbol(symbol)
pc_layer.setRenderer3D(renderer)
# --- Eye Dome Lighting for depth perception ---
settings.setEyeDomeLightingEnabled(True)
settings.setEyeDomeLightingStrength(1000.0)
settings.setEyeDomeLightingDistance(1)
settings.setLayers([pc_layer])---
Example 4: 3D Points as Colored Spheres
from qgis.core import QgsProject, Qgis
from qgis._3d import (
QgsVectorLayer3DRenderer,
QgsPoint3DSymbol,
QgsPhongMaterialSettings,
)
from qgis.PyQt.QtGui import QColor
layer = QgsProject.instance().mapLayersByName("sensors")[0]
material = QgsPhongMaterialSettings()
material.setDiffuse(QColor(255, 50, 50))
material.setSpecular(QColor(255, 255, 255))
material.setShininess(120.0)
symbol = QgsPoint3DSymbol()
symbol.setShape(Qgis.Point3DShape.Sphere)
symbol.setShapeProperties({"radius": 3.0})
symbol.setMaterialSettings(material)
symbol.setAltitudeClamping(Qgis.AltitudeClamping.Relative)
renderer = QgsVectorLayer3DRenderer(symbol)
layer.setRenderer3D(renderer)---
Example 5: 3D Map in Print Layout
from qgis.core import (
QgsProject,
QgsLayout,
QgsLayoutSize,
QgsLayoutPoint,
QgsUnitTypes,
QgsVector3D,
QgsCoordinateReferenceSystem,
QgsRectangle,
)
from qgis._3d import (
Qgs3DMapSettings,
QgsFlatTerrainSettings,
QgsLayoutItem3DMap,
QgsCameraPose,
)
from qgis.PyQt.QtGui import QColor
project = QgsProject.instance()
# --- Configure 3D settings ---
settings = Qgs3DMapSettings()
settings.setCrs(QgsCoordinateReferenceSystem("EPSG:28992"))
settings.setExtent(QgsRectangle(100000, 400000, 200000, 500000))
settings.setBackgroundColor(QColor(200, 220, 240))
terrain = QgsFlatTerrainSettings()
settings.setTerrainSettings(terrain)
settings.setLayers(list(project.mapLayers().values()))
# --- Create layout ---
layout = QgsLayout(project)
# --- Add 3D map item ---
map_3d = QgsLayoutItem3DMap(layout)
camera = QgsCameraPose()
camera.setCenterPoint(QgsVector3D(150000, 450000, 0))
camera.setDistanceFromCenterPoint(20000)
camera.setPitchAngle(45.0)
camera.setHeadingAngle(315.0)
map_3d.setCameraPose(camera)
map_3d.setMapSettings(settings)
map_3d.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters))
map_3d.attemptMove(QgsLayoutPoint(10, 10, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(map_3d)---
Example 6: PBR Material (QGIS 3.36+)
from qgis._3d import (
QgsVectorLayer3DRenderer,
QgsPolygon3DSymbol,
QgsMetalRoughMaterialSettings,
)
from qgis.PyQt.QtGui import QColor
# Metallic building facade
material = QgsMetalRoughMaterialSettings()
material.setBaseColor(QColor(180, 180, 190))
material.setMetalness(0.9)
material.setRoughness(0.2)
symbol = QgsPolygon3DSymbol.create()
symbol.setExtrusionHeight(30.0)
symbol.setMaterialSettings(material)
renderer = QgsVectorLayer3DRenderer(symbol)
building_layer.setRenderer3D(renderer)---
Example 7: Serialize and Restore 3D Settings
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import QgsReadWriteContext, QgsProject
from qgis._3d import Qgs3DMapSettings
# --- Save settings to XML ---
doc = QDomDocument()
elem = settings.writeXml(doc, QgsReadWriteContext())
doc.appendChild(elem)
xml_string = doc.toString()
# --- Restore settings from XML ---
doc2 = QDomDocument()
doc2.setContent(xml_string)
root = doc2.documentElement()
restored = Qgs3DMapSettings()
restored.readXml(root, QgsReadWriteContext())
restored.resolveReferences(QgsProject.instance())---
Example 8: Gooch Non-Photorealistic Material (QGIS 3.16+)
from qgis._3d import (
QgsVectorLayer3DRenderer,
QgsPolygon3DSymbol,
QgsGoochMaterialSettings,
)
from qgis.PyQt.QtGui import QColor
material = QgsGoochMaterialSettings()
material.setWarm(QColor(255, 200, 100))
material.setCool(QColor(100, 150, 255))
material.setDiffuse(QColor(200, 200, 200))
material.setSpecular(QColor(255, 255, 255))
material.setShininess(50.0)
material.setAlpha(0.25)
material.setBeta(0.5)
symbol = QgsPolygon3DSymbol.create()
symbol.setExtrusionHeight(20.0)
symbol.setMaterialSettings(material)
renderer = QgsVectorLayer3DRenderer(symbol)
layer.setRenderer3D(renderer)---
Example 9: Multiple Light Sources
from qgis._3d import QgsPointLightSettings, QgsDirectionalLightSettings
from qgis.core import QgsVector3D
from qgis.PyQt.QtGui import QColor
# Key light (directional — simulates sun)
key = QgsDirectionalLightSettings()
key.setDirection(QgsVector3D(0.3, -1.0, 0.4))
key.setColor(QColor(255, 250, 230))
key.setIntensity(1.0)
# Fill light (point — softens shadows)
fill = QgsPointLightSettings()
fill.setPosition(QgsVector3D(-500, 300, 200))
fill.setColor(QColor(180, 200, 255))
fill.setIntensity(0.4)
fill.setConstantAttenuation(1.0)
fill.setLinearAttenuation(0.001)
fill.setQuadraticAttenuation(0.0)
# Rim light (point — adds depth)
rim = QgsPointLightSettings()
rim.setPosition(QgsVector3D(0, 200, -500))
rim.setColor(QColor(255, 255, 255))
rim.setIntensity(0.3)
rim.setConstantAttenuation(1.0)
rim.setLinearAttenuation(0.001)
rim.setQuadraticAttenuation(0.0)
settings.setLightSources([key, fill, rim])qgis-impl-3d-visualization — Methods Reference
Qgs3DMapSettings
Central configuration class for 3D scenes. Import from qgis._3d.
Coordinate System and Extent
| Method | Signature | Notes |
|---|---|---|
setCrs | setCrs(crs: QgsCoordinateReferenceSystem) | Scene CRS |
crs | crs() -> QgsCoordinateReferenceSystem | |
setExtent | setExtent(extent: QgsRectangle) | Auto-sets origin to center |
extent | extent() -> QgsRectangle | |
setOrigin | setOrigin(origin: QgsVector3D) | World origin in map coords |
origin | origin() -> QgsVector3D | |
setTransformContext | setTransformContext(context: QgsCoordinateTransformContext) | |
transformContext | transformContext() -> QgsCoordinateTransformContext |
Coordinate Conversion
| Method | Signature | Notes |
|---|---|---|
mapToWorldCoordinates | mapToWorldCoordinates(mapCoords: QgsVector3D) -> QgsVector3D | Applies x, -z, y swap |
worldToMapCoordinates | worldToMapCoordinates(worldCoords: QgsVector3D) -> QgsVector3D | Inverse transformation |
Layers
| Method | Signature | Notes |
|---|---|---|
setLayers | setLayers(layers: Iterable[QgsMapLayer]) | Layers to render |
layers | layers() -> List[QgsMapLayer] |
Terrain
| Method | Signature | Notes |
|---|---|---|
setTerrainSettings | setTerrainSettings(settings: QgsAbstractTerrainSettings) | 3.42+ |
terrainSettings | terrainSettings() -> QgsAbstractTerrainSettings | 3.42+ |
setTerrainRenderingEnabled | setTerrainRenderingEnabled(enabled: bool) | |
terrainRenderingEnabled | terrainRenderingEnabled() -> bool | |
setTerrainShadingEnabled | setTerrainShadingEnabled(enabled: bool) | |
isTerrainShadingEnabled | isTerrainShadingEnabled() -> bool | |
setTerrainShadingMaterial | setTerrainShadingMaterial(material: QgsPhongMaterialSettings) | |
terrainShadingMaterial | terrainShadingMaterial() -> QgsPhongMaterialSettings | |
setTerrainMapTheme | setTerrainMapTheme(theme: str) | |
terrainMapTheme | terrainMapTheme() -> str | |
configureTerrainFromProject | configureTerrainFromProject(props, extent: QgsRectangle) |
Light Sources (3.26+)
| Method | Signature | Notes |
|---|---|---|
setLightSources | setLightSources(lights: Iterable[QgsLightSource]) | |
lightSources | lightSources() -> List[QgsLightSource] | |
setShowLightSourceOrigins | setShowLightSourceOrigins(show: bool) | Debug visualization |
Camera
| Method | Signature | Notes |
|---|---|---|
setFieldOfView | setFieldOfView(fov: float) | 3.8+ |
fieldOfView | fieldOfView() -> float | |
setCameraMovementSpeed | setCameraMovementSpeed(speed: float) | 3.18+ |
cameraMovementSpeed | cameraMovementSpeed() -> float |
Visual Settings
| Method | Signature | Notes |
|---|---|---|
setBackgroundColor | setBackgroundColor(color: QColor) | |
backgroundColor | backgroundColor() -> QColor | |
setSelectionColor | setSelectionColor(color: QColor) | |
selectionColor | selectionColor() -> QColor | |
setIsSkyboxEnabled | setIsSkyboxEnabled(enabled: bool) | |
isSkyboxEnabled | isSkyboxEnabled() -> bool | |
setShowLabels | setShowLabels(enabled: bool) | |
showLabels | showLabels() -> bool | |
setOutputDpi | setOutputDpi(dpi: int) | |
outputDpi | outputDpi() -> int |
Eye Dome Lighting (3.18+)
| Method | Signature | Notes |
|---|---|---|
setEyeDomeLightingEnabled | setEyeDomeLightingEnabled(enabled: bool) | |
eyeDomeLightingEnabled | eyeDomeLightingEnabled() -> bool | |
setEyeDomeLightingStrength | setEyeDomeLightingStrength(strength: float) | |
eyeDomeLightingStrength | eyeDomeLightingStrength() -> float | |
setEyeDomeLightingDistance | setEyeDomeLightingDistance(distance: int) | |
eyeDomeLightingDistance | eyeDomeLightingDistance() -> int |
Serialization
| Method | Signature | Notes |
|---|---|---|
writeXml | writeXml(doc: QDomDocument, context: QgsReadWriteContext) -> QDomElement | |
readXml | readXml(elem: QDomElement, context: QgsReadWriteContext) | |
resolveReferences | resolveReferences(project: QgsProject) | Call after readXml |
---
QgsPolygon3DSymbol
Factory: QgsPolygon3DSymbol.create() -> QgsAbstract3DSymbol. Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setAltitudeClamping | setAltitudeClamping(mode: Qgis.AltitudeClamping) | |
altitudeClamping | altitudeClamping() -> Qgis.AltitudeClamping | |
setAltitudeBinding | setAltitudeBinding(mode: Qgis.AltitudeBinding) | |
altitudeBinding | altitudeBinding() -> Qgis.AltitudeBinding | |
setOffset | setOffset(offset: float) | Vertical offset |
offset | offset() -> float | |
setExtrusionHeight | setExtrusionHeight(height: float) | Extrude upward |
extrusionHeight | extrusionHeight() -> float | |
setExtrusionFaces | setExtrusionFaces(faces: Qgis.ExtrusionFaces) | Which faces to render |
setMaterialSettings | setMaterialSettings(material: QgsAbstractMaterialSettings) | |
materialSettings | materialSettings() -> QgsAbstractMaterialSettings | |
setCullingMode | setCullingMode(mode: Qgs3DTypes.CullingMode) | |
cullingMode | cullingMode() -> Qgs3DTypes.CullingMode | |
setEdgesEnabled | setEdgesEnabled(enabled: bool) | |
edgesEnabled | edgesEnabled() -> bool | |
setEdgeWidth | setEdgeWidth(width: float) | |
edgeWidth | edgeWidth() -> float | |
setEdgeColor | setEdgeColor(color: QColor) | |
edgeColor | edgeColor() -> QColor |
---
QgsLine3DSymbol
Factory: QgsLine3DSymbol.create() -> QgsAbstract3DSymbol. Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setWidth | setWidth(width: float) | Width in map units |
width | width() -> float | |
setOffset | setOffset(offset: float) | Vertical offset |
offset | offset() -> float | |
setExtrusionHeight | setExtrusionHeight(height: float) | |
extrusionHeight | extrusionHeight() -> float | |
setAltitudeClamping | setAltitudeClamping(mode: Qgis.AltitudeClamping) | |
setAltitudeBinding | setAltitudeBinding(mode: Qgis.AltitudeBinding) | |
setRenderAsSimpleLines | setRenderAsSimpleLines(enabled: bool) | |
renderAsSimpleLines | renderAsSimpleLines() -> bool | |
setMaterialSettings | setMaterialSettings(material: QgsAbstractMaterialSettings) | |
materialSettings | materialSettings() -> QgsAbstractMaterialSettings |
---
QgsPoint3DSymbol
Constructor: QgsPoint3DSymbol(). Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setShape | setShape(shape: Qgis.Point3DShape) | Sphere, Cylinder, Cone, Cube, Torus, Plane, Billboard, Model |
shape | shape() -> Qgis.Point3DShape | |
setShapeProperties | setShapeProperties(props: Dict[str, Any]) | e.g. {"radius": 5.0} |
shapeProperties | shapeProperties() -> Dict[str, Any] | |
setMaterialSettings | setMaterialSettings(material: QgsAbstractMaterialSettings) | |
materialSettings | materialSettings() -> QgsAbstractMaterialSettings | |
setAltitudeClamping | setAltitudeClamping(mode: Qgis.AltitudeClamping) | |
setTransform | setTransform(matrix: QMatrix4x4) | Scale/rotation/translation |
transform | transform() -> QMatrix4x4 | |
setBillboardSymbol | setBillboardSymbol(symbol: QgsMarkerSymbol) | For billboard mode |
billboardSymbol | billboardSymbol() -> QgsMarkerSymbol |
Static helpers:
shapeFromString(str) -> Qgis.Point3DShapeshapeToString(Qgis.Point3DShape) -> str
---
QgsVectorLayer3DRenderer
Constructor: QgsVectorLayer3DRenderer(symbol: QgsAbstract3DSymbol | None = None). Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setSymbol | setSymbol(symbol: QgsAbstract3DSymbol) | Takes ownership |
symbol | symbol() -> QgsAbstract3DSymbol |
Apply to a layer: layer.setRenderer3D(renderer)
---
QgsPointCloudLayer3DRenderer
Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setSymbol | setSymbol(symbol: QgsPointCloud3DSymbol) | |
symbol | symbol() -> QgsPointCloud3DSymbol |
---
QgsPhongMaterialSettings
Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setAmbient | setAmbient(color: QColor) | |
ambient | ambient() -> QColor | |
setDiffuse | setDiffuse(color: QColor) | |
diffuse | diffuse() -> QColor | |
setSpecular | setSpecular(color: QColor) | |
specular | specular() -> QColor | |
setShininess | setShininess(shininess: float) | |
shininess | shininess() -> float | |
setOpacity | setOpacity(opacity: float) | 3.26+ |
opacity | opacity() -> float | |
setAmbientCoefficient | setAmbientCoefficient(coeff: float) | 3.36+ |
setDiffuseCoefficient | setDiffuseCoefficient(coeff: float) | 3.36+ |
setSpecularCoefficient | setSpecularCoefficient(coeff: float) | 3.36+ |
---
QgsGoochMaterialSettings (3.16+)
Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setWarm | setWarm(color: QColor) | Warm tone |
warm | warm() -> QColor | |
setCool | setCool(color: QColor) | Cool tone |
cool | cool() -> QColor | |
setDiffuse | setDiffuse(color: QColor) | |
setSpecular | setSpecular(color: QColor) | |
setShininess | setShininess(shininess: float) | |
setAlpha | setAlpha(alpha: float) | Warm/cool blend |
setBeta | setBeta(beta: float) | Diffuse blend |
---
QgsMetalRoughMaterialSettings (3.36+)
Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setBaseColor | setBaseColor(color: QColor) | |
baseColor | baseColor() -> QColor | |
setMetalness | setMetalness(metalness: float) | 0.0-1.0 |
metalness | metalness() -> float | |
setRoughness | setRoughness(roughness: float) | 0.0-1.0 |
roughness | roughness() -> float |
---
QgsPointLightSettings
Constructor: QgsPointLightSettings(). Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setPosition | setPosition(pos: QgsVector3D) | World coordinates |
position | position() -> QgsVector3D | |
setColor | setColor(color: QColor) | |
color | color() -> QColor | |
setIntensity | setIntensity(intensity: float) | |
intensity | intensity() -> float | |
setConstantAttenuation | setConstantAttenuation(a0: float) | |
setLinearAttenuation | setLinearAttenuation(a1: float) | |
setQuadraticAttenuation | setQuadraticAttenuation(a2: float) |
Attenuation formula: Total = A0 + A1*D + A2*D^2
---
QgsDirectionalLightSettings (3.16+)
Constructor: QgsDirectionalLightSettings(). Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setDirection | setDirection(direction: QgsVector3D) | Direction in degrees |
direction | direction() -> QgsVector3D | |
setColor | setColor(color: QColor) | |
color | color() -> QColor | |
setIntensity | setIntensity(intensity: float) | |
intensity | intensity() -> float |
---
QgsCameraPose
Constructor: QgsCameraPose(). Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setCenterPoint | setCenterPoint(point: QgsVector3D) | Focal point |
centerPoint | centerPoint() -> QgsVector3D | |
setDistanceFromCenterPoint | setDistanceFromCenterPoint(distance: float) | Camera distance |
distanceFromCenterPoint | distanceFromCenterPoint() -> float | |
setPitchAngle | setPitchAngle(angle: float) | 0=down, 90=horizontal |
pitchAngle | pitchAngle() -> float | |
setHeadingAngle | setHeadingAngle(angle: float) | Horizontal rotation |
headingAngle | headingAngle() -> float |
---
Terrain Settings Classes
QgsFlatTerrainSettings
| Method | Signature | Notes |
|---|---|---|
setElevation | setElevation(elevation: float) | Fixed height |
elevation | elevation() -> float |
QgsDemTerrainSettings
| Method | Signature | Notes |
|---|---|---|
setLayer | setLayer(layer: QgsRasterLayer) | DEM raster |
layer | layer() -> QgsRasterLayer | |
setResolution | setResolution(resolution: int) | Tile resolution |
resolution | resolution() -> int | |
setSkirtHeight | setSkirtHeight(height: float) | Prevent gaps |
skirtHeight | skirtHeight() -> float |
---
QgsLayoutItem3DMap (3.4+)
Import from qgis._3d.
| Method | Signature | Notes |
|---|---|---|
setMapSettings | setMapSettings(settings: Qgs3DMapSettings) | |
setCameraPose | setCameraPose(pose: QgsCameraPose) | |
cameraPose | cameraPose() -> QgsCameraPose |