osgx is a small, compiled C++20 utility layer on top of OpenSceneGraph. It modernizes common OSG idioms (concepts, ranges, spans, lambdas) and adds four optional, explicitly-included subsystems:
Note
The x in osgx just means "eXtras"; it has nothing to do with X11 or
anything else Xorg-centric (osgx::platform's X11/XRandr window helpers notwithstanding).
osgx::debug—GL_KHR_debugintegration (driver message callback, KHR debug-group annotations) plus a two-phase GPU/CPU per-drawable profiler.osgx::imgui— a Dear ImGui overlay (Widget/Panel) with pluggable sections and a built-in GPU-profiler, OSG-stats, and scene-texture browser.osgx::platform— X11/XRandr window helpers (alwaysOnTop,listMonitors,moveWindow), EGL- and GBM/DRM-backedGraphicsWindowfactories for driving a window without GLX or X11 at all, andPointerCapturefor hide+warp+accumulate mouse capture (turntable/FPS-style look controls).osgx::gltf— a glTF 2.0 loader (osgdb_gltf), plus an optionalosgx::gltf::pbribladapter that renders it using the genericosgx::pbr/osgx::iblfacilities. Merged in from the formerly separateosgGLTFrepo.
All four live under osgx/ and use the osgx namespace, but none of them is included by the
osgx.hpp umbrella header — pulling in GL_KHR_debug, Dear ImGui, X11/EGL/GBM, or the glTF loader
is always an explicit opt-in (#include "osgx/Debug.hpp" / #include "osgx/ImGui.hpp" / #include "osgx/Linux.hpp" / #include "osgx/gltf/Reader.hpp"), never something a consumer gets for free
just by including the umbrella.
osgx can be consumed directly from its source tree or as an installed CMake package. In either case, link the imported-style target and its OpenSceneGraph include and link requirements will be propagated to your target.
To embed the source tree in another project:
add_subdirectory(path/to/osgx EXCLUDE_FROM_ALL)
target_link_libraries(my_target PRIVATE osgx::osgx)When embedded, examples, utilities, the Python module, and installation rules are disabled by
default. They can be enabled individually with OSGX_BUILD_EXAMPLES, OSGX_BUILD_UTILS,
OSGX_BUILD_PYTHON, and OSGX_INSTALL.
To install osgx and consume it as a package, first install an already-configured build tree:
cmake --install BUILD --prefix /path/to/prefixThen use the installed package from the consuming project:
find_package(osgx CONFIG REQUIRED)
target_link_libraries(my_target PRIVATE osgx::osgx)Pass -DCMAKE_PREFIX_PATH=/path/to/prefix when configuring the consuming project if the chosen
prefix is not already in CMake's search path.
The same build tree can remove exactly the files recorded by its most recent install:
cmake --build BUILD --target uninstallThis uses CMake's generated install_manifest.txt; keep the build tree until the installation is
no longer needed.
Use osgx::core for the low-level, header-only facilities (Core.hpp, Array.hpp,
Callbacks.hpp, Shader.hpp, Visitors.hpp, Warnings.hpp) or osgx::osgx for the complete
utility layer, including osgx::debug/osgx::imgui/osgx::platform. osgx::osgx is the compiled
libosgx library and includes osgx::core.
osgx::gltf (the glTF loader) and osgx::ktx2 (the KTX2 reader/writer) are separate optional
static libraries, each gated behind its own OSGX_BUILD_GLTF/OSGX_BUILD_KTX2 option (default ON
at the top level, OFF when embedded). They used to live in a separate osgGLTF repo; both were
folded directly into this tree since they were never meaningfully independent of osgx::core/
osgx::osgx to begin with. See osgx::gltf below.
osgx.hpp is the umbrella header for the always-available utility layer. It keeps common setup
code shorter and adds modern range/span/lambda-friendly wrappers. Its public headers are organized
by concern:
osgx/Core.hpp— smart-pointer helpers, timing, ring buffers,findDataFile(), and theObjectPath/vec_t/literal utilities.osgx/Visitors.hpp— scene-graph visitors, event handlers, andFilterNotifyHandler.osgx/Array.hpp—Array<BaseArray>/DrawElements<BaseElements>wrappers.osgx/Callbacks.hpp— callback-group and lambda-callback adapters.osgx/Picking.hpp— object-ID picking cameras, readback, and hover/click handlers.osgx/Manipulators.hpp—Ortho2DManipulator,OrbitAxisManipulator, andMultiCameraManipulator.osgx/Grid.hpp— procedurally generated, antialiased grid overlay/ground-plane geometry.osgx/Shader.hpp— generic, line-oriented GLSL library expansion.osgx/PBR.hpp— PBR BRDF snippets andOrbitLightRig.osgx/IBL.hpp— environment-map loading, BRDF-LUT baking (including the process-widesharedBRDFLUT()cache), SH9/Lambertian diffuse irradiance, and cubemap readback helpers (readCubeMapFaces(),BRDFLUTReadback).osgx/CaptureCubeMap.hpp—CaptureCubeMapScene, the low-level frame-driven reflection-probe primitive (six ordered FBO cameras capturing a caller-owned scene into a radiance cubemap).osgx/GGXPrefilter.hpp— GPU GGX prefilter scene construction, rebaking, and readback.osgx/LambertianBake.hpp— frame-driven GPU Lambertian/diffuse cubemap baking and readback (LambertianBakeScene,LambertianCubeReadback).osgx.hpp— convenience umbrella that includes all of the above (but notosgx::debugorosgx::imgui— see below).osgx/Version.hpp—OSGX_VERSION_MAJOR/MINOR/PATCHand theOSGX_VERSIONstring, generated from the CMake project version.
Note
If you want to avoid having to make install before testing locally, you can
use a command like the following: export OSG_LIBRARY_PATH="$PWD/plugins/gltf:$PWD/plugins/ktx2${OSG_LIBRARY_PATH:+:$OSG_LIBRARY_PATH}"
This will ensure your local build's osgdb_{ktx2,gltf} files are used
instead.
osgx/Shader.hpp provides a reusable GLSL-snippet catalog rather than a project-specific
search-and-replace pass. Register one or more catalogs, then expand pragmas in shader source:
osgx::pbr::registerShaderLibs();
osgx::ibl::registerShaderLibs();
const osgx::ShaderLib appLibs[] = {
{"common", {}, COMMON_GLSL},
{"lighting", "appLighting", LIGHTING_GLSL}
};
osgx::registerShaderLibs("myApp", appLibs);
auto glsl = osgx::resolveShaderLibs(R"GLSL(
#pragma myApp common, lighting
#pragma osgx::pbr F_SCHLICK, IBL_SPECULAR
#pragma osgx::ibl *
)GLSL");Registered namespace and library names are case-insensitive. A pragma accepts comma-separated
library names, optional GLSL-function aliases, and * to expand the entire catalog in
registration order. Unknown names in a registered namespace fail immediately; unrelated pragmas
are left intact for other shader tooling or the GLSL compiler.
OSGX_DISABLE_WARNINGS/OSGX_ENABLE_WARNINGSsilence noisy OSG headers with compiler-specific diagnostic push/pop macros.ObjectPathis a simple dotted path accumulator used by scene-description visitors.vec_tand the_v,_sz,_zliterals provide compact OSG scalar and size literals.OSGReferenced,OSGArray, andOSGDrawElementsare concepts that constrain helpers to the expected OSG base types.make_ref<T>()andmake_nref<T>(name, ...)createosg::ref_ptrobjects, optionally naming the object immediately.tickandcall()provide lightweightosg::Timer-based timing around arbitrary callables.getFirstParent<T>()walks an OSG parent chain and returns the first parent matching a requested type.ring_buffer<T, N>andaring_buffer<T, N>keep fixed-size recent samples, with the arithmetic version adding averages.findDataFile()wraps theosgDBfile utils, letting you specify multiple paths/suffixes in one call.LambdaVisitor,IndexedVisitor,NameVisitor, andDescribeSceneVisitormake common scene-graph traversal, naming, and tree-printing tasks less boilerplate-heavy.VisitorEventHandlerruns a visitor against the viewer scene root when a key is released.LambdaKeyHandlerbinds one or more key presses to a lambda with optional access to the pressed key.FilterNotifyHandlerfilters known-noisy OSG notify messages with regexes before writing the rest to stderr.Array<BaseArray>wraps OSG array types with initializer/range constructors, append helpers,std::span, and range views; aliases includeVec2Array,Vec3Array,Vec4Array, andFloatArray.DrawElements<BaseElements>wraps indexed primitive sets with modern constructors, append helpers, primitive factories, bounds-checked pushes, spans, and views; aliases cover UByte, UShort, and UInt indices.WriteTextureCallbacklets a camera draw callback write a texture to disk on demand.CallbacksGroupand its camera/node/drawable aliases fan out one OSG callback slot to multiple callbacks.CameraDrawLambdaCallbackandNodeLambdaCallbackadapt lambdas to common OSG callback types.- The object-ID picking helpers create pick cameras, encode/decode 32-bit IDs, choose IDs from pick regions, and support sync or PBO-backed async readback.
PickCameraSync,PickHoverCallback, andPickHandlerwire pick cameras and readback state into viewer camera updates, hover transitions, and mouse input.MultiCameraManipulatorroutes input to one active manipulator while letting each target drive either the main viewer camera or its own camera, useful for RTT and multi-view tools.Ortho2DManipulatoris an orthographic 2D camera manipulator with pan, geometric zoom, pixel-nudge zoom, optional Ctrl-drag 3D tilt, and automatic near/far projection setup. Its unrotated plane is configurable throughsetPlaneNormal()andsetScreenUp()(default: XY with +Z normal).OrbitAxisManipulatoris a "turntable" model-viewer camera manipulator: it orbits a fixed guide line through the model's bounds, always looking level, with mouse move/drag always active (no button needed) and dolly zoom clamped by viewport coverage. Its orientation is configurable throughsetUpAxis()andsetHomeDirection()(default: Z-up, from -Y).orbitByDelta(dx, dy)applies a pre-computed delta directly, andsetLiveOrbitEnabled(false)disables its own raw-cursor tracking -- together the hooks for composing with an external mouse-capture scheme likeosgx::platform::PointerCapture(seeexamples/osgx-manipulator.cpp'sOrbitCaptureBridge) without giving the manipulator a dependency onosgx::platform.Griddraws a procedurally generated, antialiased grid as either a screen-space overlay or a perspective ground plane.osgx::pbrprovides reusable BRDF GLSL snippets andOrbitLightRigfor direct-light uniforms.osgx::iblprovides reusable IBL GLSL snippets plus helpers for BRDF-LUT baking (sharedBRDFLUT()), GPU GGX-prefiltered/Lambertian environment baking (GGXPrefilterScene,LambertianBakeScene), a generic reflection-probe primitive (CaptureCubeMapScene), and SH9 diffuse irradiance.
glTF-specific material and rendering integration lives with the loader in osgx::gltf (see below).
Generic osgx does not depend on or duplicate its public shader interface.
osgx/Debug.hpp provides three independent systems that can be used together or separately. It is
not included by osgx.hpp; opt in explicitly with #include "osgx/Debug.hpp".
For a Dear ImGui front-end, see osgx/ImGui.hpp / osgx::imgui::Widget below — it is a sibling of
osgx::debug, not nested under it, since most of it (sliders, Panel, texture/stats browsers) has
nothing to do with GL_KHR_debug specifically; only its ProfilerSection reaches into
osgx::debug.
glDebugMessageCallback is the GL driver speaking to you. When the driver detects
an error, a performance warning, or a shader issue, it calls your registered function.
This is a completely separate pipe from the other two systems — no queries, no groups,
just the driver reporting what it observed.
osgx::debug::initialize(gc)— resolves allGL_KHR_debugextension pointers for a context.osgx::debug::installDefaultCallback()— registers a callback that writes driver messages toosg::notify.osgx::debug::setCallback(fn)/clearCallback()— install or remove a custom callback.osgx::debug::enableDebugOutput()/disableDebugOutput()— toggleGL_DEBUG_OUTPUT[_SYNCHRONOUS].osgx::debug::GraphicsOperation— asetRealizeOperation()helper that callsinitialize()once the context exists.
glPushDebugGroup / glPopDebugGroup are you speaking to the GL driver — and by
extension to tools like apitrace and RenderDoc that intercept those calls. Annotations
appear as named, nested regions in a trace, making it immediately clear which draw calls
belong to which logical pass.
Critical rule: all calls require a current GL context. Never call pushGroup or
messageInsert from application-side C++ code (e.g. from main() or a viewer loop);
always use the camera callback objects, which fire while the context is guaranteed current.
Annotations are camera-scoped. A PRE_DRAW / FINAL_DRAW callback pair brackets
everything that camera renders — not individual nodes or groups within the scene graph.
Sub-groups of a single camera's scene cannot be individually annotated this way; for
per-group bracketing, each group needs its own RTT camera. For per-drawable bracketing,
use ProfilerCallback instead.
osgx::debug::Scoped— use this by default. RAII push/pop; construct on the stack inside anydrawImplementationor draw callback. Begin and end are in the same scope.osgx::debug::AnnotationGroup— use only when begin and end must live in separate callback objects. Its sole purpose is to share push/pop state acrossAnnotationBeginCallback(PRE_DRAW) andAnnotationEndCallback(FINAL_DRAW) so the group remains matched across the camera's frame boundary. Not a general-purpose annotation type.osgx::debug::AnnotationBeginCallback/AnnotationEndCallback— install anAnnotationGroupon a camera'sPRE_DRAWorFINAL_DRAWslot so it fires at the correct time.osgx::debug::appendCameraDrawCallback()/prependCameraDrawCallback()— safely add callbacks to an existing slot without clobbering others.
Groups nest naturally. FrameByFrameViewer installs a single Frame group on its
camera automatically. Any other object with its own RTT camera (e.g. an osgSlug::Atlas)
can install its own AnnotationBeginCallback / AnnotationEndCallback and it will
appear nested inside the viewer's group in the trace:
Frame
Atlas: glyph-cache
[draw calls]
Atlas: labels
[draw calls]
/Frame
glQueryCounter wraps each drawable in a pair of GPU timestamp queries so you can
measure actual GPU cost per draw call, averaged over a ring buffer of recent frames.
This is a two-phase design to avoid stalling the GPU pipeline mid-submission.
Phase 1 — submit (ProfilerCallback, per drawable):
glQueryCounter(begin) → draw → glQueryCounter(end) → push to FrameAccumulator
Never blocks. Install with ProfilerVisitor or attach ProfilerCallback directly.
Phase 2 — drain (ProfilerFinalCallback, per camera):
after all draws: read GL_QUERY_RESULT → update ring buffers → print/report
Blocks only on the last outstanding query. Install on the camera's FINAL_DRAW slot.
osgx::debug::ProfilerCallback<N>— drawable wrapper; issues timestamp queries and measures CPU time.osgx::debug::ProfilerVisitor<N>— walks the scene graph and installsProfilerCallbackon every drawable.osgx::debug::ProfilerFinalCallback<N>— camera callback that drainsFrameAccumulatorresults.QueryMode::SYNC(default) — blocks per-query; suitable for step-by-step viewers.QueryMode::ASYNC— drains the previous frame's results with zero meaningful stall; use for continuous renderers.
GL driver ──glDebugMessageCallback──► your callback (errors, warnings)
you ──AnnotationBegin/EndCallback──► GL driver ──► apitrace / RenderDoc
ProfilerCallback ──► FrameAccumulator ──► ProfilerFinalCallback ──► osg::notify (or osgx::imgui::Widget)
FrameByFrameViewer::requestRender() ◄── 'n' key (or an osgx::imgui button)
The three flows are independent. Annotations never need to know the profiler exists, and the driver callback has nothing to do with either.
A single, consolidated osgViewer::Viewer subclass for apitrace-friendly debugging.
Press n to advance one frame; the viewer idles between keystrokes so a capture
session does not flood with unintended frames. On first render it automatically installs
Frame / Render annotation groups on the camera (System 2). Combine with
ProfilerVisitor + ProfilerFinalCallback (System 3) and installDefaultCallback()
(System 1) for a fully instrumented scene.
osgx/ImGui.hpp (gated behind OSGX_IMGUI, requiring Dear ImGui via pkg-config; set via the
OSGX_WITH_IMGUI CMake option, which compiles it into libosgx when Dear ImGui is found)
provides
osgx::imgui::Widget, a self-contained Dear ImGui overlay with pluggable sections
(addStatsSection(), addProfilerSection(), addTextureSection(), or a custom
addSection(label, fn)), and osgx::imgui::Panel, the same section machinery for an
application that already owns its own ImGui context/frame/window.
osgx/Linux.hpp provides X11/XRandr window helpers that are always compiled into libosgx (X11
is already a hard dependency of osgViewer's GLX backend on Linux, so this carries no more risk
than the existing OpenGL dependency):
alwaysOnTop(viewer, enabled=true)— pins the viewer's X11 window above other windows via the EWMH_NET_WM_STATEClientMessage protocol.Monitor/listMonitors()— the real XRandR monitor layout (position/size in root-window coordinates; monitors are not assumed to be flush/adjacent).moveWindow(viewer, x, y, width=-1, height=-1)— repositions (and optionally resizes) an already-realized X11 window, keeping OSG's own viewport/camera bookkeeping in sync.
osgx/GraphicsWindowEGL.hpp and osgx/GraphicsWindowGBM.hpp (gated behind OSGX_EGL/OSGX_GBM,
requiring EGL and GBM+libdrm respectively via pkg-config; set via the OSGX_WITH_EGL/
OSGX_WITH_GBM CMake options, which auto-detect and compile into libosgx when found — same
pattern as OSGX_WITH_IMGUI) provide two experimental osgViewer::GraphicsWindow factories:
createEGLWindow(traits)— an ordinary X11 window driven by EGL instead of GLX. Skeleton/proof-of-concept: no input/resize handling, but does watchWM_DELETE_WINDOWso closing the window shuts the viewer down cleanly.createGBMWindow(traits)— direct-scanout DRM/KMS + GBM, no X11 or window manager at all (kiosk/embedded-style). Requires exclusive DRM master access, so it fails under a running X server or Wayland compositor.
osgx/Cursor.hpp provides mouse capture built purely on portable osgGA/osgViewer virtuals
(GraphicsWindow::useCursor(), View::requestWarpPointer()) — no X11 dependency of its own, but
grouped under osgx::platform since that's where the motivating need already lived:
setCursorVisible(view, visible=true)/warpPointer(view, x, y)— small standalone action helpers (not a get/set pair — OSG'sGraphicsWindowhas no visibility getter of its own).PointerCapture— aGUIEventHandlerimplementing the standard hide+warp+accumulate trick for turntable/FPS-style relative-motion look controls: whilesetCaptured(true), hides the cursor and re-centers it on every move, accumulating the delta forconsume()to poll once per update traversal. Not true OS-level pointer confinement (nothing stops the cursor visibly darting to the screen edge for one frame between warps on some window managers) — that needs realXGrabPointerwork, tracked inTODO.md.
Migrated from OpenSceneGraph.py's pyosg/linux/ (it was never actually OSG.py-specific); see
examples/osgx-platform.cpp for a worked example of all of the above, including both alternate
window backends.
Basic glTF 2.0 mesh/texture support for OpenSceneGraph. As of the last full Khronos sample sweep, works for all of the Khronos samples.
The screenshot compares this renderer's PBR/IBL output against BabylonJS using the same model and environment lighting. The goal is not pixel-perfect matching, but matching the material response closely enough that reflections, roughness, and HDR environment lighting behave like a modern glTF renderer should.
This code started as a patched version of the
osgEarth reference
implementation, but has since evolved into something entirely different — more features and
Khronos parity, but not (yet) exporting state that matches the osgEarth shader pipeline. It defines
both a "contract" (for custom renderers, via osgx/gltf/Shader.hpp) and a "ready-to-use" set of
helper functions (osgx::gltf::pbribl).
osgx::gltf and its optional osgx::gltf::pbribl adapter were merged in from the formerly separate
osgGLTF repo — same reasoning as osgx::ktx2 above, just a larger piece: the loader already
depended on osgx::core, and the PBR/IBL adapter already depended on the full osgx::osgx layer,
so keeping them in a separate repo bought nothing but cross-repo build/version friction.
Be sure to call osgDB::Registry::instance()->addFileExtensionAlias("glb", "gltf"); if you want to
support GLB loading through the same plugin registration path as .gltf.
OSGX_BUILD_GLTF (default ON at the top level, OFF when embedded) gates two static-library
targets, plus the osgdb_gltf osgDB plugin:
osgx::gltf— the loader itself. Depends only onosgx::coreand the vendoredext/tinygltfsubmodule. This is whatosgdb_gltflinks, so loading a.gltf/.glbthrough genericosgDB::readNodeFile()never drags in the rest ofosgx::osgx(X11, ImGui, the debug profiler, etc.) just to parse geometry.osgx::gltf_pbribl— the optional PBR/IBL adapter (osgx/gltf/PBRIBL.hpp). Linksosgx::gltfplus the fullosgx::osgxPBR/IBL layer. Only an explicit consumer pays for this.
find_package(osgx CONFIG REQUIRED)
target_link_libraries(my_target PRIVATE osgx::gltf) # loader only
target_link_libraries(my_viewer PRIVATE osgx::gltf_pbribl) # + PBR/IBL renderer#include <osgx/gltf/Reader.hpp>
osgx::gltf::Reader reader;
auto result = reader.read(path, isBinary, options);osgdb_gltf and the Python module both link the same osgx::gltf target; neither recompiles the
reader implementation or instantiates its own copy of tinygltf/STB source.
osgx::gltf loads geometry and materials without imposing a particular renderer. The public
osgx/gltf/Shader.hpp header defines the attribute locations, buffer bindings, texture units,
uniform names, and canonical GLSL material declaration populated by the loader.
Custom renderers can use the GLSL declaration directly and apply the matching program setup:
#include <osgx/gltf/Shader.hpp>
auto program = new osg::Program();
auto stateSet = model->getOrCreateStateSet();
// Add shaders using osgx::gltf::shader::MATERIAL_INPUTS as part of the fragment source.
osgx::gltf::shader::configureProgram(*program);
osgx::gltf::shader::configureStateSet(*stateSet);
stateSet->setAttributeAndModes(program);configureProgram() maps the tangent and skinning inputs to the locations used by the loader.
configureStateSet() maps the material samplers to the loader's base-color, normal, ORM, and
emissive texture units. These helpers are optional; the named constants in the same header can be
used when an application needs different program or StateSet ownership.
The Python bindings expose the same constants, GLSL source, and helpers under osgx.gltf.shader.
osgx::gltf::pbribl applies osgx::gltf's material interface using the generic facilities in
osgx::pbr and osgx::ibl. The loader target remains shader-agnostic; applications opt into this
renderer explicitly via osgx::gltf_pbribl (see CMake above):
#include <osgx/gltf/PBRIBL.hpp>
auto environment = osgx::gltf::pbribl::loadPBRIBLEnvironment("papermill.gltf");
auto scene = osgx::gltf::pbribl::createPBRIBLScene(model, environment);
if(environment.valid() && scene.valid()) {
if(environment.root) root->addChild(environment.root);
root->addChild(scene.node);
}The material GLSL helpers are registered under #pragma osgx::gltf ..., and their canonical
uniform/attribute names use the osgx_gltf_* prefix (for example, osgx_gltf_Material and
osgx_gltf_textures). Their canonical material declaration comes directly from
osgx/gltf/Shader.hpp. Python exposes the same API under
osgx.gltf.pbribl. utils/osgx-gltf-viewer is the corresponding complete C++ consumer.
utils/osgx-pbribl turns one HDR equirectangular image into a complete
osgx_pbribl environment bundle consumable by utils/osgx-gltf-viewer --env:
utils/osgx-pbribl input.hdr environments/studio
utils/osgx-gltf-viewer --env environments/studio.gltf model.gltfThe command writes studio-specular.ktx2, studio-diffuse.ktx2, and studio.gltf. The manifest
refers to its two KTX2 files by basename, so keep them beside the generated .gltf file (or move
the whole bundle together).
The specular and diffuse cubemaps are derived from the HDR. The manifest identifies the built-in
split-sum GGX BRDF LUT and its size instead of writing an HDR-independent LUT file; the renderer
caches and bakes that LUT once per process. Existing manifests that provide a BRDF-LUT uri remain
supported.
Optional quality controls are --prefilter-size, --samples, --diffuse-cube-size,
--diffuse-samples, and --lut-size.
| Output | osgx-pbribl default |
Khronos Sample Viewer reference default |
|---|---|---|
GGX specular cubemap base size (--prefilter-size) |
128 | 256 |
GGX samples per texel (--samples) |
1024 | 1024 |
Lambertian diffuse cubemap size (--diffuse-cube-size) |
256 | 256 |
Lambertian samples per texel (--diffuse-samples) |
2048 | 2048 |
BRDF LUT size (--lut-size) |
1024 | 1024 |
| BRDF LUT integration samples | 512 (fixed) | 512 |
osgx-pbribl emits the full specular mip chain down to 1×1. The Khronos reference environment
uses an eight-level GGX chain; this mainly affects the roughest lookup levels.
- GL_KHR_debug
- GL_ARB_debug_output
- GL_EXT_debug_marker
- GL_EXT_debug_label
- GL_AMD_debug_output
export LSAN_OPTIONS=suppressions=/home/cubicool/dev/osgdebug/OSG/lsan.supp
export OSG_GL_CONTEXT_VERSION=3.0
osgx-ibl is the generic visual laboratory for IBL outputs. It currently bakes a Lambertian
diffuse cubemap directly from an HDR panorama, then displays it either as a Z-up skybox or a
literal six-face GL cubemap cross:
./examples/osgx-ibl Cannon_Exterior.hdr --mode lambertian --size 256 --samples 2048Press c to switch between the diffuse skybox and cross views, or p to inspect the original
tone-mapped equirectangular HDR panorama. Future generic source/GGX/LUT modes belong in this tool
rather than in glTF-specific examples.
osgx-callback, osgx-notifyfilter, and osgx-viewer demonstrate the osgx::debug systems
above (FrameByFrameViewer, ProfilerVisitor/ProfilerFinalCallback, DescribeSceneVisitor).
osgx-imgui and osgx-imgui-external demonstrate osgx::imgui::Widget and the app-owned
osgx::imgui::Panel pattern, respectively. osgx-drawables (in utils/) attaches
ProfilerCallback via ProfilerVisitor to a loaded model from the command line.
osgx-platform demonstrates osgx::platform: prints the real XRandR monitor layout, moves and
pins the (default GLX) window via moveWindow()/alwaysOnTop(), and, when built with
OSGX_WITH_EGL/OSGX_WITH_GBM, drives the same scene through --egl or --gbm instead.
osgx-ktx2-skybox (in examples/) loads a KTX2 cubemap and displays it as a skybox, stepping
through the mip chain interactively — useful for verifying a generated specular or diffuse cube.
utils/osgx-gltf-viewer is the full glTF PBR/IBL reference viewer (osgx::gltf::pbribl);
utils/osgx-pbribl generates its static osgx_pbribl environment bundles.
