mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-05 21:22:07 +02:00
wip redo stencil work
This commit is contained in:
parent
78256fb5bb
commit
c730e51d1e
21 changed files with 288 additions and 66 deletions
4
cmake/externals/LibOVR/CMakeLists.txt
vendored
4
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -17,8 +17,8 @@ if (WIN32)
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://public.highfidelity.com/dependencies/ovr_sdk_win_1.26.0_public.zip
|
||||
URL_MD5 06804ff9727b910dcd04a37c800053b5
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.35.0.zip
|
||||
URL_MD5 1e3e8b2101387af07ff9c841d0ea285e
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
|
||||
LOG_DOWNLOAD 1
|
||||
|
|
|
@ -6725,6 +6725,11 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
appRenderArgs._renderArgs._stencilMaskMode = getActiveDisplayPlugin()->getStencilMaskMode();
|
||||
if (appRenderArgs._renderArgs._stencilMaskMode == StencilMaskMode::MESH) {
|
||||
appRenderArgs._renderArgs._stencilMaskOperator = getActiveDisplayPlugin()->getStencilMaskMeshOperator();
|
||||
}
|
||||
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_myCamera.loadViewFrustum(_displayViewFrustum);
|
||||
|
@ -8412,11 +8417,20 @@ void Application::loadAvatarBrowser() const {
|
|||
DependencyManager::get<HMDScriptingInterface>()->openTablet();
|
||||
}
|
||||
|
||||
void Application::addSnapshotOperator(const SnapshotOperator& snapshotOperator) {
|
||||
std::lock_guard<std::mutex> lock(_snapshotMutex);
|
||||
_snapshotOperators.push(snapshotOperator);
|
||||
}
|
||||
|
||||
bool Application::takeSnapshotOperators(std::queue<SnapshotOperator>& snapshotOperators) {
|
||||
std::lock_guard<std::mutex> lock(_snapshotMutex);
|
||||
_snapshotOperators.swap(snapshotOperators);
|
||||
return !snapshotOperators.empty();
|
||||
}
|
||||
|
||||
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
|
||||
postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] {
|
||||
// Get a screenshot and save it
|
||||
QString path = DependencyManager::get<Snapshot>()->saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename,
|
||||
TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||
addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) {
|
||||
QString path = DependencyManager::get<Snapshot>()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||
|
||||
// If we're not doing an animated snapshot as well...
|
||||
if (!includeAnimated) {
|
||||
|
@ -8428,7 +8442,7 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa
|
|||
// Get an animated GIF snapshot and save it
|
||||
SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, qApp, DependencyManager::get<WindowScriptingInterface>());
|
||||
}
|
||||
});
|
||||
}, aspectRatio });
|
||||
}
|
||||
|
||||
void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) {
|
||||
|
|
|
@ -344,6 +344,10 @@ public:
|
|||
void toggleAwayMode();
|
||||
#endif
|
||||
|
||||
using SnapshotOperator = std::pair<std::function<void(const QImage&)>, float>;
|
||||
void addSnapshotOperator(const SnapshotOperator& snapshotOperator);
|
||||
bool takeSnapshotOperators(std::queue<SnapshotOperator>& snapshotOperators);
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -788,6 +792,8 @@ private:
|
|||
AudioInjectorPointer _snapshotSoundInjector;
|
||||
SharedSoundPointer _snapshotSound;
|
||||
SharedSoundPointer _sampleSound;
|
||||
std::mutex _snapshotMutex;
|
||||
std::queue<SnapshotOperator> _snapshotOperators;
|
||||
|
||||
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
|
||||
QString _autoSwitchDisplayModeSupportedHMDPluginName;
|
||||
|
|
|
@ -152,10 +152,12 @@ public:
|
|||
_cachedArgsPointer->_viewport = args->_viewport;
|
||||
_cachedArgsPointer->_displayMode = args->_displayMode;
|
||||
_cachedArgsPointer->_renderMode = args->_renderMode;
|
||||
_cachedArgsPointer->_stencilMaskMode = args->_stencilMaskMode;
|
||||
args->_blitFramebuffer = destFramebuffer;
|
||||
args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight());
|
||||
args->_displayMode = RenderArgs::MONO;
|
||||
args->_renderMode = RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE;
|
||||
args->_stencilMaskMode = StencilMaskMode::NONE;
|
||||
|
||||
gpu::doInBatch("SecondaryCameraJob::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.disableContextStereo();
|
||||
|
@ -255,10 +257,11 @@ public:
|
|||
void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) {
|
||||
auto args = renderContext->args;
|
||||
if (cachedArgs) {
|
||||
args->_blitFramebuffer = cachedArgs->_blitFramebuffer;
|
||||
args->_viewport = cachedArgs->_viewport;
|
||||
args->_displayMode = cachedArgs->_displayMode;
|
||||
args->_renderMode = cachedArgs->_renderMode;
|
||||
args->_blitFramebuffer = cachedArgs->_blitFramebuffer;
|
||||
args->_viewport = cachedArgs->_viewport;
|
||||
args->_displayMode = cachedArgs->_displayMode;
|
||||
args->_renderMode = cachedArgs->_renderMode;
|
||||
args->_stencilMaskMode = cachedArgs->_stencilMaskMode;
|
||||
}
|
||||
args->popViewFrustum();
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@ void GraphicsEngine::render_performFrame() {
|
|||
finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
}
|
||||
|
||||
std::queue<Application::SnapshotOperator> snapshotOperators;
|
||||
if (!_programsCompiled.load()) {
|
||||
gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) {
|
||||
batch.setFramebuffer(finalFramebuffer);
|
||||
|
@ -271,11 +272,13 @@ void GraphicsEngine::render_performFrame() {
|
|||
PROFILE_RANGE(render, "/runRenderFrame");
|
||||
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||
renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture();
|
||||
renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators);
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
render_runRenderFrame(&renderArgs);
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "boop" << renderArgs._takingSnapshot << snapshotOperators.size();
|
||||
auto frame = getGPUContext()->endFrame();
|
||||
frame->frameIndex = _renderFrameCount;
|
||||
frame->framebuffer = finalFramebuffer;
|
||||
|
@ -285,6 +288,7 @@ void GraphicsEngine::render_performFrame() {
|
|||
frameBufferCache->releaseFramebuffer(framebuffer);
|
||||
}
|
||||
};
|
||||
frame->snapshotOperators = snapshotOperators;
|
||||
// deliver final scene rendering commands to the display plugin
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginOutput");
|
||||
|
|
|
@ -62,44 +62,45 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio
|
|||
|
||||
void SnapshotAnimated::captureFrames() {
|
||||
if (SnapshotAnimated::snapshotAnimatedTimerRunning) {
|
||||
// Get a screenshot from the display, then scale the screenshot down,
|
||||
// then convert it to the image format the GIF library needs,
|
||||
// then save all that to the QImage named "frame"
|
||||
QImage frame(SnapshotAnimated::app->getActiveDisplayPlugin()->getScreenshot(SnapshotAnimated::aspectRatio));
|
||||
frame = frame.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH);
|
||||
SnapshotAnimated::snapshotAnimatedFrameVector.append(frame);
|
||||
SnapshotAnimated::app->addSnapshotOperator({ [](const QImage& snapshot) {
|
||||
// Get a screenshot from the display, then scale the screenshot down,
|
||||
// then convert it to the image format the GIF library needs,
|
||||
// then save all that to the QImage named "frame"
|
||||
QImage frame = snapshot.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH);
|
||||
SnapshotAnimated::snapshotAnimatedFrameVector.append(frame);
|
||||
|
||||
// If that was the first frame...
|
||||
if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) {
|
||||
// Record the current frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
// Record the first frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = SnapshotAnimated::snapshotAnimatedTimestamp;
|
||||
SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10);
|
||||
// If this is an intermediate or the final frame...
|
||||
} else {
|
||||
// Push the current frame delay onto the vector
|
||||
SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(round(((float)(QDateTime::currentMSecsSinceEpoch() - SnapshotAnimated::snapshotAnimatedTimestamp)) / 10));
|
||||
// Record the current frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
// If that was the first frame...
|
||||
if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) {
|
||||
// Record the current frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
// Record the first frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = SnapshotAnimated::snapshotAnimatedTimestamp;
|
||||
SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10);
|
||||
// If this is an intermediate or the final frame...
|
||||
} else {
|
||||
// Push the current frame delay onto the vector
|
||||
SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(round(((float)(QDateTime::currentMSecsSinceEpoch() - SnapshotAnimated::snapshotAnimatedTimestamp)) / 10));
|
||||
// Record the current frame timestamp
|
||||
SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// If that was the last frame...
|
||||
if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) {
|
||||
SnapshotAnimated::snapshotAnimatedTimerRunning = false;
|
||||
// If that was the last frame...
|
||||
if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) {
|
||||
SnapshotAnimated::snapshotAnimatedTimerRunning = false;
|
||||
|
||||
// Notify the user that we're processing the snapshot
|
||||
// This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called.
|
||||
emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath);
|
||||
// Notify the user that we're processing the snapshot
|
||||
// This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called.
|
||||
emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath);
|
||||
|
||||
// Kick off the thread that'll pack the frames into the GIF
|
||||
QtConcurrent::run(processFrames);
|
||||
// Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE
|
||||
// that the slot will not be called again in the future.
|
||||
// See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html
|
||||
SnapshotAnimated::snapshotAnimatedTimer->stop();
|
||||
delete SnapshotAnimated::snapshotAnimatedTimer;
|
||||
// Kick off the thread that'll pack the frames into the GIF
|
||||
QtConcurrent::run(processFrames);
|
||||
// Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE
|
||||
// that the slot will not be called again in the future.
|
||||
// See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html
|
||||
SnapshotAnimated::snapshotAnimatedTimer->stop();
|
||||
delete SnapshotAnimated::snapshotAnimatedTimer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, SnapshotAnimated::aspectRatio });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -723,6 +723,15 @@ void OpenGLDisplayPlugin::present() {
|
|||
compositeLayers();
|
||||
}
|
||||
|
||||
{ // If we have any snapshots this frame, handle them
|
||||
PROFILE_RANGE_EX(render, "snapshotOperators", 0xffff00ff, frameId)
|
||||
while (!_currentFrame->snapshotOperators.empty()) {
|
||||
auto& snapshotOperator = _currentFrame->snapshotOperators.front();
|
||||
snapshotOperator.first(getScreenshot(snapshotOperator.second));
|
||||
_currentFrame->snapshotOperators.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Take the composite framebuffer and send it to the output device
|
||||
{
|
||||
PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId)
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
void pluginUpdate() override {};
|
||||
|
||||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; }
|
||||
|
||||
signals:
|
||||
void hmdMountedChanged();
|
||||
void hmdVisibleChanged(bool visible);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#define hifi_gpu_Frame_h
|
||||
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
#include "Forward.h"
|
||||
#include "Batch.h"
|
||||
|
@ -41,6 +42,8 @@ namespace gpu {
|
|||
/// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE
|
||||
FramebufferRecycler framebufferRecycler;
|
||||
|
||||
std::queue<std::pair<std::function<void(const QImage&)>, float>> snapshotOperators;
|
||||
|
||||
protected:
|
||||
friend class Deserializer;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <SimpleMovingAverage.h>
|
||||
#include <gpu/Forward.h>
|
||||
#include "Plugin.h"
|
||||
#include "StencilMaskMode.h"
|
||||
|
||||
class QOpenGLFramebufferObject;
|
||||
|
||||
|
@ -221,6 +222,10 @@ public:
|
|||
// for updating plugin-related commands. Mimics the input plugin.
|
||||
virtual void pluginUpdate() = 0;
|
||||
|
||||
virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; }
|
||||
using StencilMaskMeshOperator = std::function<void(gpu::Batch&)>;
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; }
|
||||
|
||||
signals:
|
||||
void recommendedFramebufferSizeChanged(const QSize& size);
|
||||
void resetSensorsRequested();
|
||||
|
|
|
@ -19,7 +19,6 @@ using namespace render;
|
|||
|
||||
void PrepareStencil::configure(const Config& config) {
|
||||
_maskMode = config.maskMode;
|
||||
_forceDraw = config.forceDraw;
|
||||
}
|
||||
|
||||
graphics::MeshPointer PrepareStencil::getMesh() {
|
||||
|
@ -43,6 +42,7 @@ gpu::PipelinePointer PrepareStencil::getMeshStencilPipeline() {
|
|||
auto state = std::make_shared<gpu::State>();
|
||||
drawMask(*state);
|
||||
state->setColorWriteMask(gpu::State::WRITE_NONE);
|
||||
state->setCullMode(gpu::State::CullMode::CULL_NONE);
|
||||
|
||||
_meshStencilPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
@ -64,8 +64,28 @@ gpu::PipelinePointer PrepareStencil::getPaintStencilPipeline() {
|
|||
void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
// Only draw the stencil mask if in HMD mode or not forced.
|
||||
if (!_forceDraw && (args->_displayMode != RenderArgs::STEREO_HMD)) {
|
||||
if (args->_takingSnapshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
StencilMaskMode maskMode = _maskMode;
|
||||
std::function<void(gpu::Batch&)> maskOperator = [this](gpu::Batch& batch) {
|
||||
auto mesh = getMesh();
|
||||
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||
batch.setInputFormat((mesh->getVertexFormat()));
|
||||
batch.setInputStream(0, mesh->getVertexStream());
|
||||
|
||||
// Draw
|
||||
auto part = mesh->getPartBuffer().get<graphics::Mesh::Part>(0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
|
||||
};
|
||||
|
||||
if (maskMode == StencilMaskMode::NONE) {
|
||||
maskMode = args->_stencilMaskMode;
|
||||
maskOperator = args->_stencilMaskOperator;
|
||||
}
|
||||
|
||||
if (maskMode == StencilMaskMode::NONE || (maskMode == StencilMaskMode::MESH && !maskOperator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,20 +94,12 @@ void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::F
|
|||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
if (_maskMode < 0) {
|
||||
batch.setPipeline(getMeshStencilPipeline());
|
||||
|
||||
auto mesh = getMesh();
|
||||
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||
batch.setInputFormat((mesh->getVertexFormat()));
|
||||
batch.setInputStream(0, mesh->getVertexStream());
|
||||
|
||||
// Draw
|
||||
auto part = mesh->getPartBuffer().get<graphics::Mesh::Part>(0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
|
||||
} else {
|
||||
if (maskMode == StencilMaskMode::PAINT) {
|
||||
batch.setPipeline(getPaintStencilPipeline());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
} else if (maskMode == StencilMaskMode::MESH) {
|
||||
batch.setPipeline(getMeshStencilPipeline());
|
||||
maskOperator(batch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,17 +15,19 @@
|
|||
#include <render/Engine.h>
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <graphics/Geometry.h>
|
||||
#include <StencilMaskMode.h>
|
||||
|
||||
class PrepareStencilConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int maskMode MEMBER maskMode NOTIFY dirty)
|
||||
Q_PROPERTY(bool forceDraw MEMBER forceDraw NOTIFY dirty)
|
||||
Q_PROPERTY(StencilMaskMode maskMode MEMBER maskMode NOTIFY dirty)
|
||||
|
||||
public:
|
||||
PrepareStencilConfig(bool enabled = true) : JobConfig(enabled) {}
|
||||
|
||||
int maskMode { 0 };
|
||||
bool forceDraw { false };
|
||||
// -1 -> don't force drawing (fallback to render args mode)
|
||||
// 0 -> force draw without mesh
|
||||
// 1 -> force draw with mesh
|
||||
StencilMaskMode maskMode { StencilMaskMode::NONE };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
@ -66,8 +68,7 @@ private:
|
|||
graphics::MeshPointer _mesh;
|
||||
graphics::MeshPointer getMesh();
|
||||
|
||||
int _maskMode { 0 };
|
||||
bool _forceDraw { false };
|
||||
StencilMaskMode _maskMode { StencilMaskMode::NONE };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <GLMHelpers.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <StencilMaskMode.h>
|
||||
|
||||
#include <gpu/Forward.h>
|
||||
#include "Forward.h"
|
||||
|
@ -133,6 +134,10 @@ namespace render {
|
|||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> _hudOperator;
|
||||
gpu::TexturePointer _hudTexture;
|
||||
|
||||
bool _takingSnapshot { false };
|
||||
StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE };
|
||||
std::function<void(gpu::Batch&)> _stencilMaskOperator;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
|
|||
int socketErrorMetaTypeId = qRegisterMetaType<QAbstractSocket::SocketError>();
|
||||
int voidLambdaType = qRegisterMetaType<std::function<void()>>();
|
||||
int variantLambdaType = qRegisterMetaType<std::function<QVariant()>>();
|
||||
int stencilModeMetaTypeId = qRegisterMetaType<StencilMaskMode>();
|
||||
|
||||
void registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, vec2ToScriptValue, vec2FromScriptValue);
|
||||
|
@ -64,6 +65,8 @@ void registerMetaTypes(QScriptEngine* engine) {
|
|||
qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, aaCubeToScriptValue, aaCubeFromScriptValue);
|
||||
|
||||
qScriptRegisterMetaType(engine, stencilMaskModeToScriptValue, stencilMaskModeFromScriptValue);
|
||||
}
|
||||
|
||||
QScriptValue vec2ToScriptValue(QScriptEngine* engine, const glm::vec2& vec2) {
|
||||
|
@ -1283,4 +1286,12 @@ QVariantMap parseTexturesToMap(QString newTextures, const QVariantMap& defaultTe
|
|||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
QScriptValue stencilMaskModeToScriptValue(QScriptEngine* engine, const StencilMaskMode& stencilMode) {
|
||||
return engine->newVariant((int)stencilMode);
|
||||
}
|
||||
|
||||
void stencilMaskModeFromScriptValue(const QScriptValue& object, StencilMaskMode& stencilMode) {
|
||||
stencilMode = StencilMaskMode(object.toVariant().toInt());
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
#include "shared/Bilateral.h"
|
||||
#include "Transform.h"
|
||||
#include "PhysicsCollisionGroups.h"
|
||||
#include "StencilMaskMode.h"
|
||||
|
||||
class QColor;
|
||||
class QUrl;
|
||||
|
@ -729,5 +730,8 @@ void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>
|
|||
|
||||
QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures);
|
||||
|
||||
Q_DECLARE_METATYPE(StencilMaskMode)
|
||||
QScriptValue stencilMaskModeToScriptValue(QScriptEngine* engine, const StencilMaskMode& stencilMode);
|
||||
void stencilMaskModeFromScriptValue(const QScriptValue& object, StencilMaskMode& stencilMode);
|
||||
|
||||
#endif // hifi_RegisteredMetaTypes_h
|
||||
|
|
18
libraries/shared/src/StencilMaskMode.h
Normal file
18
libraries/shared/src/StencilMaskMode.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 3/26/19.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_StencilMaskMode_h
|
||||
#define hifi_StencilMaskMode_h
|
||||
|
||||
enum class StencilMaskMode {
|
||||
NONE = -1, // for legacy reasons, this is -1
|
||||
PAINT = 0,
|
||||
MESH = 1
|
||||
};
|
||||
|
||||
#endif // hifi_StencilMaskMode_h
|
|
@ -18,7 +18,7 @@ if (WIN32 AND (NOT USE_GLES))
|
|||
link_hifi_libraries(
|
||||
shared task gl shaders gpu ${PLATFORM_GL_BACKEND} controllers ui qml
|
||||
plugins ui-plugins display-plugins input-plugins
|
||||
audio-client networking render-utils
|
||||
audio-client networking render-utils graphics
|
||||
${PLATFORM_GL_BACKEND}
|
||||
)
|
||||
include_hifi_library_headers(octree)
|
||||
|
|
|
@ -227,3 +227,66 @@ QVector<glm::vec3> OculusBaseDisplayPlugin::getSensorPositions() {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
DisplayPlugin::StencilMaskMeshOperator OculusBaseDisplayPlugin::getStencilMaskMeshOperator() {
|
||||
if (_session) {
|
||||
if (!_stencilMeshesInitialized) {
|
||||
_stencilMeshesInitialized = true;
|
||||
ovr::for_each_eye([&](ovrEyeType eye) {
|
||||
ovrFovStencilDesc stencilDesc = {
|
||||
ovrFovStencil_HiddenArea, 0, eye,
|
||||
_eyeRenderDescs[eye].Fov, _eyeRenderDescs[eye].HmdToEyePose.Orientation
|
||||
};
|
||||
// First we get the size of the buffer we need
|
||||
ovrFovStencilMeshBuffer buffer = { 0, 0, nullptr, 0, 0, nullptr };
|
||||
ovrResult result = ovr_GetFovStencil(_session, &stencilDesc, &buffer);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
_stencilMeshesInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<ovrVector2f> ovrVertices(buffer.UsedVertexCount);
|
||||
std::vector<uint16_t> ovrIndices(buffer.UsedIndexCount);
|
||||
|
||||
// Now we populate the actual buffer
|
||||
buffer = { (int)ovrVertices.size(), 0, ovrVertices.data(), (int)ovrIndices.size(), 0, ovrIndices.data() };
|
||||
result = ovr_GetFovStencil(_session, &stencilDesc, &buffer);
|
||||
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
_stencilMeshesInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<glm::vec3> vertices;
|
||||
vertices.reserve(ovrVertices.size());
|
||||
for (auto& ovrVertex : ovrVertices) {
|
||||
// We need the vertices in clip space
|
||||
vertices.emplace_back(ovrVertex.x - (1.0f - (float)eye), 2.0f * ovrVertex.y - 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> indices;
|
||||
indices.reserve(ovrIndices.size());
|
||||
for (auto& ovrIndex : ovrIndices) {
|
||||
indices.push_back(ovrIndex);
|
||||
}
|
||||
|
||||
_stencilMeshes[eye] = graphics::Mesh::createIndexedTriangles_P3F((uint32_t)vertices.size(), (uint32_t)indices.size(), vertices.data(), indices.data());
|
||||
});
|
||||
}
|
||||
|
||||
if (_stencilMeshesInitialized) {
|
||||
return [&](gpu::Batch& batch) {
|
||||
for (auto& mesh : _stencilMeshes) {
|
||||
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||
batch.setInputFormat((mesh->getVertexFormat()));
|
||||
batch.setInputStream(0, mesh->getVertexStream());
|
||||
|
||||
// Draw
|
||||
auto part = mesh->getPartBuffer().get<graphics::Mesh::Part>(0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
#define OVRPL_DISABLED
|
||||
#include <OVR_Platform.h>
|
||||
|
||||
#include <graphics/Geometry.h>
|
||||
|
||||
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
|
@ -34,6 +36,9 @@ public:
|
|||
QRectF getPlayAreaRect() override;
|
||||
QVector<glm::vec3> getSensorPositions() override;
|
||||
|
||||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; }
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override;
|
||||
|
||||
protected:
|
||||
void customizeContext() override;
|
||||
void uncustomizeContext() override;
|
||||
|
@ -52,4 +57,7 @@ protected:
|
|||
// ovrLayerEyeFovDepth _depthLayer;
|
||||
bool _hmdMounted { false };
|
||||
bool _visible { true };
|
||||
|
||||
std::array<graphics::MeshPointer, 2> _stencilMeshes;
|
||||
bool _stencilMeshesInitialized { false };
|
||||
};
|
||||
|
|
|
@ -784,3 +784,48 @@ QRectF OpenVrDisplayPlugin::getPlayAreaRect() {
|
|||
|
||||
return QRectF(center.x, center.y, dimensions.x, dimensions.y);
|
||||
}
|
||||
|
||||
DisplayPlugin::StencilMaskMeshOperator OpenVrDisplayPlugin::getStencilMaskMeshOperator() {
|
||||
if (_system) {
|
||||
if (!_stencilMeshesInitialized) {
|
||||
_stencilMeshesInitialized = true;
|
||||
for (auto eye : VR_EYES) {
|
||||
vr::HiddenAreaMesh_t stencilMesh = _system->GetHiddenAreaMesh(eye);
|
||||
if (stencilMesh.pVertexData && stencilMesh.unTriangleCount > 0) {
|
||||
std::vector<glm::vec3> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
const int NUM_INDICES_PER_TRIANGLE = 3;
|
||||
int numIndices = stencilMesh.unTriangleCount * NUM_INDICES_PER_TRIANGLE;
|
||||
vertices.reserve(numIndices);
|
||||
indices.reserve(numIndices);
|
||||
for (int i = 0; i < numIndices; i++) {
|
||||
vr::HmdVector2_t vertex2D = stencilMesh.pVertexData[i];
|
||||
// We need the vertices in clip space
|
||||
vertices.emplace_back(vertex2D.v[0] - (1.0f - (float)eye), 2.0f * vertex2D.v[1] - 1.0f, 0.0f);
|
||||
indices.push_back(i);
|
||||
}
|
||||
|
||||
_stencilMeshes[eye] = graphics::Mesh::createIndexedTriangles_P3F((uint32_t)vertices.size(), (uint32_t)indices.size(), vertices.data(), indices.data());
|
||||
} else {
|
||||
_stencilMeshesInitialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_stencilMeshesInitialized) {
|
||||
return [&](gpu::Batch& batch) {
|
||||
for (auto& mesh : _stencilMeshes) {
|
||||
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||
batch.setInputFormat((mesh->getVertexFormat()));
|
||||
batch.setInputStream(0, mesh->getVertexStream());
|
||||
|
||||
// Draw
|
||||
auto part = mesh->getPartBuffer().get<graphics::Mesh::Part>(0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||
|
||||
#include <graphics/Geometry.h>
|
||||
|
||||
const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only.
|
||||
|
||||
namespace gl {
|
||||
|
@ -67,6 +69,9 @@ public:
|
|||
|
||||
QRectF getPlayAreaRect() override;
|
||||
|
||||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; }
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override;
|
||||
|
||||
protected:
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
|
@ -94,4 +99,7 @@ private:
|
|||
bool _asyncReprojectionActive { false };
|
||||
|
||||
bool _hmdMounted { false };
|
||||
|
||||
std::array<graphics::MeshPointer, 2> _stencilMeshes;
|
||||
bool _stencilMeshesInitialized { false };
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue