Bare minimum UsdImagingGLEngine Code

Hello!

I’m working on a hobby project and I was wondering if anyone has the bare minimum pxr::UsdImagingGLEngine that I could learn and understand! I tried following the stageView.py but I seem to be stuck with the same diagnostic errors but that’s off topic, I would love to see a working OpenGL UsdImagingGLEngine example if possible!

Thank you,
Michal B

I pulled this out of my project and removed extraneous stuff. Initialise the View class and then call render.

Did not see if it compiles but should be easy to get something working from this example code.

If the USD stage does not specify a camera, a hardcoded one will be used.

#include "pxr/imaging/hgi/tokens.h"
#include "pxr/imaging/hdSt/renderDelegate.h"
#include "pxr/usd/sdf/layer.h"
#include "pxr/usd/usd/stage.h"
#include <cstdint>
#include <iostream>
#include <pxr/base/gf/declare.h>
#include <pxr/base/gf/frustum.h>
#include <pxr/base/gf/matrix4d.h>
#include <pxr/base/gf/quatd.h>
#include <pxr/base/gf/rotation.h>
#include <pxr/base/vt/array.h>
#include <pxr/base/vt/value.h>
#include <pxr/imaging/garch/glDebugWindow.h>
#include <pxr/imaging/glf/drawTarget.h>
#include <pxr/imaging/hd/driver.h>
#include <pxr/imaging/hd/pluginRenderDelegateUniqueHandle.h>
#include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/imaging/hd/sceneIndex.h>
#include <pxr/imaging/hdSt/drawTarget.h>
#include <pxr/imaging/hdx/taskController.h>
#include <pxr/imaging/hgi/hgi.h>
#include <pxr/imaging/hgiInterop/hgiInterop.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/common.h>
#include <pxr/usd/usd/timeCode.h>
#include <pxr/usd/usdSkel/animQuery.h>
#include <pxr/usd/usdSkel/animation.h>
#include <pxr/usd/usdSkel/binding.h>
#include <pxr/usd/usdSkel/cache.h>
#include <pxr/usd/usdSkel/skeletonQuery.h>
#include <pxr/usdImaging/usdImaging/sceneIndices.h>
#include <pxr/usdImaging/usdImaging/stageSceneIndex.h>
#include <pxr/imaging/hd/engine.h>
#include <pxr/imaging/hdx/taskController.h>
#include <pxr/imaging/hd/cameraSchema.h>
#include <pxr/imaging/hd/xformSchema.h>
#include <pxr/base/gf/camera.h>
#include <pxr/usdImaging/usdImaging/delegate.h>
#include <pxr/usd/usdSkel/skeleton.h>
#include <pxr/usd/usdSkel/bindingAPI.h>

using namespace pxr;

class View {
    public:

    uint32_t framebufferWidth;
    uint32_t framebufferHeight;
    GfMatrix4d camView, camProj;
    HgiInterop _interop;
    GlfDrawTargetRefPtr _drawTarget;
    UsdStageRefPtr _stage;
    HgiUniquePtr hgi;
    HdDriver driver;
    HdStRenderDelegate* renderDelegate;
    HdRenderIndex* index;
    UsdImagingStageSceneIndexRefPtr sceneIndex;
    std::unique_ptr<UsdImagingDelegate> delegate;
    HdEngine engine;
    HdxTaskController* taskController;

    void Render() {
        delegate->SetTime(UsdTimeCode(0));
        delegate->ApplyPendingUpdates();
        delegate->SyncAll(true);

        _drawTarget->Bind();

        HdTaskSharedPtrVector tasks = taskController->GetRenderingTasks();
        engine.Execute(index, &tasks);

        _drawTarget->Unbind();

        VtValue aov;
        HgiTextureHandle aovTexture;

        if (engine.GetTaskContextData(HdAovTokens->color, &aov)) {
            if (aov.IsHolding<HgiTextureHandle>()) {
                aovTexture = aov.Get<HgiTextureHandle>();
            }
        }

        uint32_t framebuffer = 0;
        _interop.TransferToApp(hgi.get(), aovTexture,
                                /*srcDepth*/ HgiTextureHandle(), HgiTokens->OpenGL,
                                VtValue(framebuffer),
                                GfVec4i(0, 0, framebufferWidth, framebufferHeight));
    }

    View( int fw, int fh, std::string filename):
        framebufferWidth(fw),
        framebufferHeight(fh)
        {

        auto _rootLayer = SdfLayer::FindOrOpen(filename);

        _stage = UsdStage::Open(_rootLayer);

        hgi = Hgi::CreatePlatformDefaultHgi();
        driver = HdDriver{HgiTokens->renderDriver, VtValue(hgi.get())};

        // init draw target
        _drawTarget = GlfDrawTarget::New(GfVec2i(framebufferWidth, framebufferHeight));
        _drawTarget->Bind();
        _drawTarget->AddAttachment(HdAovTokens->color, GL_RGBA, GL_FLOAT, GL_RGBA);
        _drawTarget->AddAttachment(HdAovTokens->depth, GL_DEPTH_COMPONENT,
                                   GL_FLOAT, GL_DEPTH_COMPONENT);
        _drawTarget->Unbind();

        renderDelegate =  new HdStRenderDelegate();

        index = HdRenderIndex::New(renderDelegate, {&driver});

        TF_VERIFY(index != nullptr);

        sceneIndex = UsdImagingStageSceneIndex::New();

        sceneIndex->SetStage(_stage);

        SdfPath taskControllerId("/taskController");

        delegate = std::unique_ptr<UsdImagingDelegate>(new UsdImagingDelegate(index, _stage->GetPseudoRoot().GetPath()));

        delegate->Populate(_stage->GetPseudoRoot());

        taskController = new HdxTaskController(index, taskControllerId);

        HdxRenderTaskParams params;
        //params.viewport = GfVec4f(0, 0, width, height);
        params.enableLighting = true;
        taskController->SetRenderParams(params);

         // init collection
        auto collection = HdRprimCollection(HdTokens->geometry,
                                        HdReprSelector(HdReprTokens->smoothHull));
        taskController->SetCollection(collection);

        // init render tags
        taskController->SetRenderTags(TfTokenVector());

        // init AOVs
        TfTokenVector aovOutputs{HdAovTokens->color};
        taskController->SetRenderOutputs(aovOutputs);

        GfVec4f clearColor = GfVec4f(.2f, .2f, .2f, 1.0f);
        HdAovDescriptor colorAovDesc =
            taskController->GetRenderOutputSettings(HdAovTokens->color);
        if (colorAovDesc.format != HdFormatInvalid) {
            colorAovDesc.clearValue = VtValue(clearColor);
            taskController->SetRenderOutputSettings(HdAovTokens->color,
                                                     colorAovDesc);
        }

        taskController->SetEnableSelection(false);

        auto selTracker = std::make_shared<HdxSelectionTracker>();
        VtValue selectionValue(selTracker);
        engine.SetTaskContextData(HdxTokens->selectionState, VtValue(selTracker));

        taskController->SetOverrideWindowPolicy(CameraUtilFit);

        taskController->SetRenderViewport(GfVec4f(0, 0, framebufferWidth, framebufferHeight));
        taskController->SetRenderBufferSize(GfVec2i(framebufferWidth, framebufferHeight));

        _drawTarget->Bind();
        _drawTarget->SetSize(GfVec2i(framebufferWidth, framebufferHeight));
        _drawTarget->Unbind();

        // setup camera
        auto _up = GfVec3d::YAxis();

        HdSceneIndexPrim prim = sceneIndex->GetPrim(SdfPath("/camera1"));

        GfMatrix4d camView;
        GfMatrix4d camProj;

        if (prim.primType == HdPrimTypeTokens->camera) {
            GfFrustum frustum = _toGfCamera(prim);
            camView = frustum.ComputeViewMatrix();
            camProj = frustum.ComputeProjectionMatrix();
        } else {
            camView = defaultView();
            camProj = defaultProj(framebufferWidth, framebufferHeight);
        }

        // set a spot light to the camera position
        GfVec3d camPos = camView.GetInverse().ExtractTranslation();
        GlfSimpleLight l;
        l.SetAmbient(GfVec4f(0, 0, 0, 0));
        l.SetPosition(GfVec4f(camPos[0], camPos[1], camPos[2], 1));

        GlfSimpleMaterial material;
        material.SetAmbient(GfVec4f(2, 2, 2, 1.0));
        material.SetSpecular(GfVec4f(0.1, 0.1, 0.1, 1.0));
        material.SetShininess(32.0);

        GfVec4f sceneAmbient(0.01, 0.01, 0.01, 1.0);

        GlfSimpleLightingContextRefPtr lightingContextState = GlfSimpleLightingContext::New();

        lightingContextState->SetLights({l});
        lightingContextState->SetMaterial(material);
        lightingContextState->SetSceneAmbient(sceneAmbient);
        lightingContextState->SetUseLighting(true);

        taskController->SetLightingState(lightingContextState);

        taskController->SetFreeCameraMatrices(camView, camProj);

    }

    GfFrustum _toGfCamera(HdSceneIndexPrim prim)
    {
        GfCamera cam;

        if (prim.primType != HdPrimTypeTokens->camera) {
            std::cout << "Camera failed to load" << std::endl;
            return cam.GetFrustum();
        }
        HdSampledDataSource::Time time(0);

        HdXformSchema xformSchema = HdXformSchema::GetFromParent(prim.dataSource);

        GfMatrix4d xform = xformSchema.GetMatrix()->GetValue(time).Get<GfMatrix4d>();
        HdCameraSchema camSchema = HdCameraSchema::GetFromParent(prim.dataSource);

        TfToken projection =
            camSchema.GetProjection()->GetValue(time).Get<TfToken>();
        float hAperture =
            camSchema.GetHorizontalAperture()->GetValue(time).Get<float>();
        float vAperture =
            camSchema.GetVerticalAperture()->GetValue(time).Get<float>();
        float hApertureOffest =
            camSchema.GetHorizontalApertureOffset()->GetValue(time).Get<float>();
        float vApertureOffest =
            camSchema.GetVerticalApertureOffset()->GetValue(time).Get<float>();
        float focalLength =
            camSchema.GetFocalLength()->GetValue(time).Get<float>();
        GfVec2f clippingRange =
            camSchema.GetClippingRange()->GetValue(time).Get<GfVec2f>();

        cam.SetTransform(xform);
        cam.SetProjection(projection == HdCameraSchemaTokens->orthographic
                              ? GfCamera::Orthographic
                              : GfCamera::Perspective);
        cam.SetHorizontalAperture(hAperture / GfCamera::APERTURE_UNIT);
        cam.SetVerticalAperture(vAperture / GfCamera::APERTURE_UNIT);
        cam.SetHorizontalApertureOffset(hApertureOffest / GfCamera::APERTURE_UNIT);
        cam.SetVerticalApertureOffset(vApertureOffest / GfCamera::APERTURE_UNIT);
        cam.SetFocalLength(focalLength / GfCamera::FOCAL_LENGTH_UNIT);
        cam.SetClippingRange(GfRange1f(clippingRange[0], clippingRange[1]));

        return cam.GetFrustum();
    }

    GfMatrix4d defaultProj(uint32_t framebufferWidth, uint32_t framebufferHeight ) {

        const float FREE_CAM_FOV = 45.f;
        const float FREE_CAM_NEAR = 0.1f;
        const float FREE_CAM_FAR = 10000.f;

        GfFrustum frustum;
        double aspectRatio = (double)framebufferWidth / (double)framebufferHeight;
        frustum.SetPerspective(FREE_CAM_FOV, true, aspectRatio, FREE_CAM_NEAR, FREE_CAM_FAR);

        return frustum.ComputeProjectionMatrix();
    }

    GfMatrix4d defaultView() {
        auto _eye = GfVec3d(275.0, -306.0, 211.4);
        auto _lookAt = GfVec3d(-52.8, 76.0, 74.0);
        auto _up = GfVec3d::ZAxis();

        GfMatrix4d view;
        view.SetLookAt(_eye, _lookAt, _up);

        return view;
    }
};

1 Like

Hello, I adjusted your code to work with Qt, I was hoping to get some pointers in what I may be doing wrong? I have sent the code bellow (I’m only allowed to send to files so I zipped the code, sorry), thanks!

Runtime Error: in GlfPostPendingGLErrors at line 67 of D:\Coding\OpenUSD\pxr\imaging\glf\diagnostic.cpp -- GL error: invalid enum, reported from void __cdecl pxrInternal_v0_24_11__pxrReserved__::GlfDrawTarget::Bind(void)
Runtime Error: in HgiGLPostPendingGLErrors at line 74 of D:\Coding\OpenUSD\pxr\imaging\hgiGL\diagnostic.cpp -- GL error: invalid enum, reported from __cdecl pxrInternal_v0_24_11__pxrReserved__::HgiGL_ScopedStateHolder::~HgiGL_ScopedStateHolder(void)
Runtime Error: in HgiGLPostPendingGLErrors at line 74 of D:\Coding\OpenUSD\pxr\imaging\hgiGL\diagnostic.cpp -- GL error: invalid enum, reported from __cdecl pxrInternal_v0_24_11__pxrReserved__::HgiGL_ScopedStateHolder::~HgiGL_ScopedStateHolder(void)
Coding Error: in CompositeToInterop at line 293 of D:\Coding\OpenUSD\pxr\imaging\hgiInterop\opengl.cpp -- Failed verification: ' glGetError() == GL_NO_ERROR '
Coding Error: in CompositeToInterop at line 293 of D:\Coding\OpenUSD\pxr\imaging\hgiInterop\opengl.cpp -- Failed verification: ' glGetError() == GL_NO_ERROR '

viewport.zip (4.5 KB)

I am not sure. The errors seem to linker/build related. Did you install openusd with OpenGL support and are you linking to it correctly?

can you try building and running this project ?GitHub - raph080/ImGuiHydraEditor: ImGui Hydra Editor is a USD editor written in c++ with the ImGui and OpenUSD frameworks.