Hydra render engine #104712
|
@ -50,6 +50,8 @@ set(SRC
|
|||
engine.cpp
|
||||
finalEngine.h
|
||||
finalEngine.cpp
|
||||
finalEngineGL.h
|
||||
finalEngineGL.cpp
|
||||
viewportEngine.h
|
||||
viewportEngine.cpp
|
||||
|
||||
|
|
|
@ -37,12 +37,14 @@ class HydraRenderEngine(bpy.types.RenderEngine):
|
|||
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
|
||||
log("update", self, engine_type)
|
||||
|
||||
def render(self, depsgraph):
|
||||
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
|
||||
log("render", self, engine_type)
|
||||
|
||||
self.engine_ptr = _usdhydra.engine.create(self.as_pointer(), engine_type, self.delegate_id)
|
||||
delegate_settings = self.get_delegate_settings(engine_type)
|
||||
_usdhydra.engine.sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings)
|
||||
|
||||
def render(self, depsgraph):
|
||||
log("render", self)
|
||||
_usdhydra.engine.sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings)
|
||||
_usdhydra.engine.render(self.engine_ptr, depsgraph.as_pointer())
|
||||
|
||||
# viewport render
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "engine.h"
|
||||
#include "finalEngine.h"
|
||||
#include "finalEngineGL.h"
|
||||
#include "viewportEngine.h"
|
||||
|
||||
using namespace pxr;
|
||||
|
@ -41,6 +42,8 @@ Engine::Engine(BL::RenderEngine &b_engine, const std::string &delegateId)
|
|||
renderIndex.get(), SdfPath::AbsoluteRootPath().AppendElementString("freeCamera"));
|
||||
renderTaskDelegate = std::make_unique<RenderTaskDelegate>(
|
||||
renderIndex.get(), SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
||||
|
||||
engine = std::make_unique<HdEngine>();
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
|
@ -50,6 +53,8 @@ Engine::~Engine()
|
|||
freeCameraDelegate = nullptr;
|
||||
renderIndex = nullptr;
|
||||
renderDelegate = nullptr;
|
||||
engine = nullptr;
|
||||
hgi = nullptr;
|
||||
}
|
||||
|
||||
float Engine::getRendererPercentDone()
|
||||
|
@ -85,7 +90,12 @@ static PyObject *create_func(PyObject * /*self*/, PyObject *args)
|
|||
engine = new ViewportEngine(b_engine, delegateId);
|
||||
}
|
||||
else {
|
||||
engine = new FinalEngine(b_engine, delegateId);
|
||||
if (b_engine.bl_use_gpu_context()) {
|
||||
engine = new FinalEngineGL(b_engine, delegateId);
|
||||
}
|
||||
else {
|
||||
engine = new FinalEngine(b_engine, delegateId);
|
||||
}
|
||||
}
|
||||
|
||||
return PyLong_FromVoidPtr(engine);
|
||||
|
|
|
@ -39,7 +39,7 @@ protected:
|
|||
std::unique_ptr<BlenderSceneDelegate> sceneDelegate;
|
||||
std::unique_ptr<RenderTaskDelegate> renderTaskDelegate;
|
||||
std::unique_ptr<HdxFreeCameraSceneDelegate> freeCameraDelegate;
|
||||
HdEngine engine;
|
||||
std::unique_ptr<HdEngine> engine;
|
||||
|
||||
HgiUniquePtr hgi;
|
||||
// Similar for HdDriver.
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace usdhydra {
|
|||
void FinalEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, pxr::HdRenderSettingsMap &renderSettings)
|
||||
{
|
||||
sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(),
|
||||
SdfPath::AbsoluteRootPath().AppendElementString("blenderScene"), b_depsgraph);
|
||||
SdfPath::AbsoluteRootPath().AppendElementString("scene"), b_depsgraph);
|
||||
sceneDelegate->Populate();
|
||||
|
||||
for (auto const& setting : renderSettings) {
|
||||
|
@ -55,7 +55,7 @@ void FinalEngine::render(BL::Depsgraph &b_depsgraph)
|
|||
{
|
||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
||||
TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||
engine.Execute(renderIndex.get(), &tasks);
|
||||
engine->Execute(renderIndex.get(), &tasks);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
|
|
@ -13,12 +13,15 @@ class FinalEngine : public Engine {
|
|||
public:
|
||||
using Engine::Engine;
|
||||
void sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, pxr::HdRenderSettingsMap &renderSettings) override;
|
||||
void render(BL::Depsgraph &b_depsgraph);
|
||||
virtual void render(BL::Depsgraph &b_depsgraph);
|
||||
|
||||
private:
|
||||
protected:
|
||||
void getResolution(BL::RenderSettings b_render, int &width, int &height);
|
||||
void updateRenderResult(std::map<std::string, std::vector<float>> &render_images, const std::string &layerName, int width, int height);
|
||||
void notifyStatus(float progress, const std::string &title, const std::string &info);
|
||||
|
||||
protected:
|
||||
HdRenderSettingsMap renderSettings;
|
||||
};
|
||||
|
||||
} // namespace usdhydra
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <pxr/imaging/hd/engine.h>
|
||||
#include <pxr/imaging/hdx/freeCameraSceneDelegate.h>
|
||||
#include <pxr/imaging/glf/drawTarget.h>
|
||||
#include <pxr/usdImaging/usdAppUtils/camera.h>
|
||||
|
||||
#include "glog/logging.h"
|
||||
|
||||
#include "finalEngineGL.h"
|
||||
#include "utils.h"
|
||||
#include "sceneDelegate/scene.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace pxr;
|
||||
|
||||
namespace usdhydra {
|
||||
|
||||
void FinalEngineGL::render(BL::Depsgraph& b_depsgraph)
|
||||
{
|
||||
SceneExport sceneExport(b_depsgraph);
|
||||
auto resolution = sceneExport.resolution();
|
||||
int width = resolution.first, height = resolution.second;
|
||||
|
||||
GfCamera gfCamera = sceneExport.gfCamera();
|
||||
freeCameraDelegate->SetCamera(gfCamera);
|
||||
renderTaskDelegate->SetCameraAndViewport(freeCameraDelegate->GetCameraId(), GfVec4d(0, 0, width, height));
|
||||
|
||||
HdTaskSharedPtrVector tasks = renderTaskDelegate->GetTasks();
|
||||
|
||||
chrono::time_point<chrono::steady_clock> timeBegin = chrono::steady_clock::now(), timeCurrent;
|
||||
chrono::milliseconds elapsedTime;
|
||||
|
||||
float percentDone = 0.0;
|
||||
string sceneName = sceneExport.sceneName(), layerName = sceneExport.layerName();
|
||||
|
||||
map<string, vector<float>> renderImages{{"Combined", vector<float>(width * height * 4)}}; // 4 - number of channels
|
||||
vector<float> &pixels = renderImages["Combined"];
|
||||
|
||||
GLuint FramebufferName = 0;
|
||||
glGenFramebuffers(1, &FramebufferName);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
|
||||
|
||||
// The texture we're going to render to
|
||||
GLuint renderedTexture;
|
||||
glGenTextures(1, &renderedTexture);
|
||||
|
||||
// "Bind" the newly created texture : all future texture functions will modify this texture
|
||||
glBindTexture(GL_TEXTURE_2D, renderedTexture);
|
||||
|
||||
// Give an empty image to OpenGL ( the last "0" )
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
|
||||
// Poor filtering. Needed !
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// Set "renderedTexture" as our colour attachement #0
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
|
||||
|
||||
// Generate vertex array
|
||||
GLuint VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
{
|
||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
||||
TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||
engine->Execute(renderIndex.get(), &tasks);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (b_engine.test_break()) {
|
||||
break;
|
||||
}
|
||||
|
||||
percentDone = getRendererPercentDone();
|
||||
timeCurrent = chrono::steady_clock::now();
|
||||
elapsedTime = chrono::duration_cast<chrono::milliseconds>(timeCurrent - timeBegin);
|
||||
|
||||
notifyStatus(percentDone / 100.0, sceneName + ": " + layerName,
|
||||
"Render Time: " + formatDuration(elapsedTime) + " | Done: " + to_string(int(percentDone)) + "%");
|
||||
|
||||
if (renderTaskDelegate->IsConverged()) {
|
||||
break;
|
||||
}
|
||||
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pixels.data());
|
||||
updateRenderResult(renderImages, layerName, width, height);
|
||||
}
|
||||
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pixels.data());
|
||||
updateRenderResult(renderImages, layerName, width, height);
|
||||
}
|
||||
|
||||
} // namespace usdhydra
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "finalEngine.h"
|
||||
#include "finalEngineGL.h"
|
||||
|
||||
namespace usdhydra {
|
||||
|
||||
class FinalEngineGL : public FinalEngine {
|
||||
public:
|
||||
using FinalEngine::FinalEngine;
|
||||
void render(BL::Depsgraph& b_depsgraph) override;
|
||||
};
|
||||
|
||||
} // namespace usdhydra
|
|
@ -39,14 +39,21 @@ std::string MaterialExport::name()
|
|||
SdfAssetPath MaterialExport::exportMX()
|
||||
{
|
||||
PyObject *module, *dict, *func, *params, *result;
|
||||
module = PyImport_Import(PyUnicode_FromString("usdhydra.matx"));
|
||||
PyGILState_STATE gstate;
|
||||
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
module = PyImport_ImportModule("usdhydra.matx");
|
||||
dict = PyModule_GetDict(module);
|
||||
func = PyDict_GetItemString(dict, "export");
|
||||
params = Py_BuildValue("(s)", name().c_str());
|
||||
result = PyObject_CallObject(func, params);
|
||||
|
||||
std::string path = PyUnicode_AsUTF8(result);
|
||||
return SdfAssetPath(path, path);
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
return SdfAssetPath(path, path);
|
||||
}
|
||||
|
||||
} // namespace usdhydra
|
||||
|
|
|
@ -544,7 +544,7 @@ void ViewportEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, px
|
|||
sceneDelegate = std::make_unique<BlenderSceneDelegate>(renderIndex.get(),
|
||||
SdfPath::AbsoluteRootPath().AppendElementString("scene"), b_depsgraph);
|
||||
}
|
||||
|
||||
|
||||
sceneDelegate->Populate();
|
||||
for (auto const& setting : renderSettings) {
|
||||
renderDelegate->SetRenderSetting(setting.first, setting.second);
|
||||
|
@ -580,14 +580,14 @@ void ViewportEngine::viewDraw(BL::Depsgraph &b_depsgraph, BL::Context &b_context
|
|||
{
|
||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
||||
TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||
engine.Execute(renderIndex.get(), &tasks);
|
||||
engine->Execute(renderIndex.get(), &tasks);
|
||||
|
||||
if (!b_engine.bl_use_gpu_context()) {
|
||||
texture.setBuffer(renderTaskDelegate->GetRendererAov(HdAovTokens->color));
|
||||
texture.draw((GLfloat)viewSettings.border[0][0], (GLfloat)viewSettings.border[0][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
b_engine.unbind_display_space_shader();
|
||||
|
||||
chrono::time_point<chrono::steady_clock> timeCurrent = chrono::steady_clock::now();
|
||||
|
|
Loading…
Reference in New Issue