diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index ae4cf6320e..481753f7e0 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -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= PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" /CMakeLists.txt LOG_DOWNLOAD 1 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 147b5b79a6..b8eb216a87 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6709,6 +6709,11 @@ void Application::updateRenderArgs(float deltaTime) { // Configure the type of display / stereo appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR); } + + appRenderArgs._renderArgs._stencilMode = getActiveDisplayPlugin()->getStencilMaskMode(); + if (appRenderArgs._renderArgs._stencilMode == StencilMode::MESH) { + appRenderArgs._renderArgs._stencilMaskOperator = getActiveDisplayPlugin()->getStencilMaskMeshOperator(); + } } { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index d8c0ce8e1d..4d2f1018a7 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -48,6 +48,8 @@ public: void pluginUpdate() override {}; + virtual StencilMode getStencilMaskMode() const override { return StencilMode::PAINT; } + signals: void hmdMountedChanged(); void hmdVisibleChanged(bool visible); diff --git a/libraries/graphics/src/graphics/Geometry.cpp b/libraries/graphics/src/graphics/Geometry.cpp index a983ba07b4..cee2b0e3c9 100755 --- a/libraries/graphics/src/graphics/Geometry.cpp +++ b/libraries/graphics/src/graphics/Geometry.cpp @@ -362,7 +362,6 @@ MeshPointer Mesh::createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numI mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(numIndices * sizeof(uint32_t), (gpu::Byte*) indices), gpu::Element::INDEX_INT32)); } - std::vector parts; parts.push_back(graphics::Mesh::Part(0, numIndices, 0, graphics::Mesh::TRIANGLES)); mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(graphics::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index aa52e57c3f..48887d66b5 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -27,6 +27,7 @@ #include #include #include "Plugin.h" +#include "StencilMode.h" class QOpenGLFramebufferObject; @@ -221,6 +222,10 @@ public: // for updating plugin-related commands. Mimics the input plugin. virtual void pluginUpdate() = 0; + virtual StencilMode getStencilMaskMode() const { return StencilMode::NONE; } + using StencilMaskMeshOperator = std::function; + virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; } + signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 7217a3e5eb..6dfc1e50fd 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -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(); drawMask(*state); state->setColorWriteMask(gpu::State::WRITE_NONE); + state->setCullMode(gpu::State::CullMode::CULL_NONE); _meshStencilPipeline = gpu::Pipeline::create(program, state); } @@ -64,30 +64,37 @@ 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)) { + StencilMode maskMode = _maskMode; + std::function 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(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + }; + + if (maskMode == StencilMode::NONE) { + maskMode = args->_stencilMode; + maskOperator = args->_stencilMaskOperator; + } + + if (maskMode == StencilMode::NONE || (maskMode == StencilMode::MESH && !maskOperator)) { return; } doInBatch("PrepareStencil::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); - 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(0); - batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); - } else { + if (maskMode == StencilMode::PAINT) { batch.setPipeline(getPaintStencilPipeline()); batch.draw(gpu::TRIANGLE_STRIP, 4); + } else if (maskMode == StencilMode::MESH) { + batch.setPipeline(getMeshStencilPipeline()); + maskOperator(batch); } }); } diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index a8e4d1e1f2..410b7a5e0a 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -15,17 +15,19 @@ #include #include #include +#include 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(StencilMode 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 + StencilMode maskMode { StencilMode::NONE }; signals: void dirty(); @@ -66,8 +68,7 @@ private: graphics::MeshPointer _mesh; graphics::MeshPointer getMesh(); - int _maskMode { 0 }; - bool _forceDraw { false }; + StencilMode _maskMode { StencilMode::NONE }; }; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index b5c98e3428..d2354561e0 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -16,11 +16,11 @@ #include #include +#include #include #include "Forward.h" - class AABox; namespace render { @@ -133,6 +133,9 @@ namespace render { std::function _hudOperator; gpu::TexturePointer _hudTexture; + + StencilMode _stencilMode { StencilMode::NONE }; + std::function _stencilMaskOperator; }; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 597e537d8d..bb89ce306e 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -40,6 +40,7 @@ int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); int voidLambdaType = qRegisterMetaType>(); int variantLambdaType = qRegisterMetaType>(); +int stencilModeMetaTypeId = qRegisterMetaType(); 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, stencilModeToScriptValue, stencilModeFromScriptValue); } QScriptValue vec2ToScriptValue(QScriptEngine* engine, const glm::vec2& vec2) { @@ -1283,4 +1286,12 @@ QVariantMap parseTexturesToMap(QString newTextures, const QVariantMap& defaultTe } return toReturn; +} + +QScriptValue stencilModeToScriptValue(QScriptEngine* engine, const StencilMode& stencilMode) { + return engine->newVariant((int)stencilMode); +} + +void stencilModeFromScriptValue(const QScriptValue& object, StencilMode& stencilMode) { + stencilMode = StencilMode(object.toVariant().toInt()); } \ No newline at end of file diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index ea2c5b8354..13d7f81a2e 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -25,6 +25,7 @@ #include "shared/Bilateral.h" #include "Transform.h" #include "PhysicsCollisionGroups.h" +#include "StencilMode.h" class QColor; class QUrl; @@ -729,5 +730,8 @@ void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures); +Q_DECLARE_METATYPE(StencilMode) +QScriptValue stencilModeToScriptValue(QScriptEngine* engine, const StencilMode& stencilMode); +void stencilModeFromScriptValue(const QScriptValue &object, StencilMode& stencilMode); #endif // hifi_RegisteredMetaTypes_h diff --git a/libraries/shared/src/StencilMode.h b/libraries/shared/src/StencilMode.h new file mode 100644 index 0000000000..412d33b319 --- /dev/null +++ b/libraries/shared/src/StencilMode.h @@ -0,0 +1,19 @@ +// +// 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_StencilMode_h +#define hifi_StencilMode_h + +enum class StencilMode { + NONE = -1, // for legacy reasons, this is -1 + PAINT = 0, + MESH = 1 +}; + +#endif // hifi_StencilMode_h + diff --git a/plugins/oculus/CMakeLists.txt b/plugins/oculus/CMakeLists.txt index abce753b4d..6ddc75e1e5 100644 --- a/plugins/oculus/CMakeLists.txt +++ b/plugins/oculus/CMakeLists.txt @@ -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) diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index a67e3127e5..db26537a19 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -227,3 +227,66 @@ QVector 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 ovrVertices(buffer.UsedVertexCount); + std::vector 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 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 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(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + } + }; + } + } + return nullptr; +} \ No newline at end of file diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 1abb7cdad7..42aa02a18f 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -16,6 +16,8 @@ #define OVRPL_DISABLED #include +#include + class OculusBaseDisplayPlugin : public HmdDisplayPlugin { using Parent = HmdDisplayPlugin; public: @@ -34,6 +36,9 @@ public: QRectF getPlayAreaRect() override; QVector getSensorPositions() override; + virtual StencilMode getStencilMaskMode() const override { return StencilMode::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 _stencilMeshes; + bool _stencilMeshesInitialized { false }; }; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 11d941dcd0..b102722aea 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -784,3 +784,49 @@ 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 vertices; + std::vector 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(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + } + }; + } + } + return nullptr; +} \ No newline at end of file diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 265f328920..aaec787893 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -13,6 +13,8 @@ #include +#include + 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 StencilMode getStencilMaskMode() const override{ return StencilMode::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 _stencilMeshes; + bool _stencilMeshesInitialized { false }; };