-
-
Notifications
You must be signed in to change notification settings - Fork 291
Migration Guide for PR 3220
This PR replaces the old generic VR renderer hook with a scene-compositor based architecture and adds an optional OpenXR runtime path. Existing non-VR projects should keep working without changes. Projects using the previous VR renderer or custom scene renderer APIs need the updates below.
OpenXR is opt-in:
-DAX_ENABLE_VR=ON
-DAX_ENABLE_OPENXR=ONAX_ENABLE_OPENXR depends on AX_ENABLE_VR and is not available for iOS or WebAssembly. When enabled, the build fetches and links the OpenXR loader from the Khronos OpenXR-SDK dependency.
If you use Vulkan for OpenXR, call registerVulkanInterop() in applicationWillLaunch() before any RHI driver or render view is created:
void AppDelegate::applicationWillLaunch()
{
#ifdef AX_ENABLE_OPENXR
registerVulkanInterop();
#endif
}registerVulkanInterop() injects an OpenXRVulkanInterop into GraphicsCore through the VulkanInterop abstract interface. The Vulkan backend queries the OpenXR runtime for required instance/device extensions and selects the runtime-compatible physical device through this interface, without any OpenXR headers in the core RHI.
The old VRGenericRenderer class has been removed. Use one of the new compositors:
-
VRPreviewSceneCompositor: stereo preview/debug rendering without an XR runtime. -
VRSceneCompositor: product VR rendering through OpenXR.
Before:
#include "axmol/vr/VRGenericRenderer.h"
auto vrRenderer = std::make_unique<ax::VRGenericRenderer>();
Director::getInstance()->setSceneRenderer(std::move(vrRenderer));After:
#include "axmol/vr/VRPreviewSceneCompositor.h"
#ifdef AX_ENABLE_OPENXR
#include "axmol/vr/VRSceneCompositor.h"
#endif
auto director = ax::Director::getInstance();
auto renderView = director->getRenderView();
#ifdef AX_ENABLE_OPENXR
renderView->setSceneCompositor(std::make_unique<ax::VRSceneCompositor>());
#else
renderView->setSceneCompositor(std::make_unique<ax::VRPreviewSceneCompositor>());
#endifPass nullptr to setSceneCompositor() to restore the default compositor:
renderView->setSceneCompositor(nullptr);SceneRenderer has been renamed and reframed as SceneCompositor.
If you had a custom subclass:
- Replace
#include "axmol/scene/SceneRenderer.h"with#include "axmol/scene/SceneCompositor.h". - Derive from
ax::SceneCompositor. - Install it on the
RenderViewCore, not onDirector. - Override
pollEvents()if your compositor must poll runtime events before scheduler update. - Keep overriding
renderScene(),onRenderViewChanged(),setScissorRect(), andgetScissorRect()as needed.
Before:
class MyRenderer : public ax::SceneRenderer
{
void renderScene(ax::Renderer* renderer, ax::Scene* scene) override;
};
Director::getInstance()->setSceneRenderer(std::make_unique<MyRenderer>());After:
class MyCompositor : public ax::SceneCompositor
{
void renderScene(ax::Renderer* renderer, ax::Scene* scene) override;
};
Director::getInstance()->getRenderView()->setSceneCompositor(std::make_unique<MyCompositor>());Code that queried Director::getSceneRenderer() should query the render view instead:
auto compositor = Director::getInstance()->getRenderView()->getSceneCompositor();Pointer events can now carry a controller ray and a hit result:
if (event->hasRay())
{
const auto& ray = event->getRay().value();
}
if (event->hasHitResult())
{
Vec3 worldPoint = event->getHitResult().worldPoint;
}For custom nodes, override Node::onPointerHitTest() and write world-space hit points to outHitPoint:
bool MyNode::onPointerHitTest(ax::PointerEvent* event,
const ax::Camera* camera,
ax::Vec3* outHitPoint)
{
if (event->hasRay())
{
// Ray-based 3D/controller picking.
}
else
{
// Traditional 2D pointer picking.
}
return hit;
}Terrain and UI widgets already support this path. If your old gameplay code manually rebuilt a camera ray in pointer callbacks, prefer the dispatcher-provided hit result when listening on the target node.
Before:
auto ray = camera->screenToRay(event->getScreenLocation());
Vec3 hit;
if (terrain->getIntersectionPoint(ray, hit))
{
movePlayerTo(hit);
}After:
if (event->hasHitResult())
{
movePlayerTo(event->getHitResult().worldPoint);
}Use XRInputEventListener for controller buttons, axes, and poses:
auto listener = ax::XRInputEventListener::create();
listener->onButton = [](ax::XRInputEvent* event) {
if (event->getInput() == ax::XRInputEvent::Input::Trigger &&
event->getPhase() == ax::XRInputEvent::Phase::Pressed)
{
// Trigger pressed.
}
};
listener->onAxis = [](ax::XRInputEvent* event) {
auto axis = event->getAxis();
};
listener->onPose = [](ax::XRInputEvent* event) {
if (event->hasAimRay())
{
const auto& ray = event->getAimRay().value();
}
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 1);Existing pointer listeners can still receive controller-ray interactions when the OpenXR compositor maps aim poses and trigger/thumbstick input into PointerEvent.
DriverContext has been renamed to GraphicsCore. The class now manages the VulkanInterop* interface instead of vendor-specific OpenXR compatibility flags. If your code references DriverContext directly, replace it with GraphicsCore.
- OpenXR runtime rendering currently targets D3D11, D3D12, Vulkan, and Android OpenGL ES bindings where supported by the runtime.
- Desktop OpenGL and Windows ANGLE GLES are not valid OpenXR graphics backends in this implementation.
- If the HMD/runtime is unavailable, the OpenXR path logs a warning and falls back to normal scene rendering.
- OpenXR APIs live in
ax::experimental. - Custom RHI backends must implement
createTextureFromNativeHandle()andsubmitCurrentFrameCommands()to support runtime-owned swapchain images.
- Cocos2d-x Migration Guide
- SpriteKit to Axmol Engine
- Update Guide to 2.3.0+ for Android
- Migration Guide for PR 3173: Refactor InputSystem