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;
}
};