diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 37204b0f9b..3e8e811c32 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2479,6 +2479,7 @@ Application::Application( copyViewFrustum(viewFrustum); return viewFrustum.getPosition(); }); + MirrorModeHelpers::setComputeMirrorViewOperator(EntityRenderer::computeMirrorViewOperator); DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, unsigned int banFlags) { userKickConfirmation(nodeID, banFlags); }); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index b2d6a6260b..790b45843c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1120,7 +1120,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const batch.setModelTransform(textTransform); { PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText"); - displayNameRenderer->draw(batch, text_x, -text_y, glm::vec2(-1.0f), nameUTF8.data(), textColor, true, forward); + displayNameRenderer->draw(batch, { nameUTF8.data(), textColor, { text_x, -text_y }, glm::vec2(-1.0f), forward }); } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 1fef0debdb..aec9f092b9 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -237,7 +237,11 @@ void EntityRenderer::computeMirrorView(ViewFrustum& viewFrustum) const { mirrorMode = _mirrorMode; portalExitID = _portalExitID; }); + computeMirrorViewOperator(viewFrustum, inPropertiesPosition, inPropertiesRotation, mirrorMode, portalExitID); +} +void EntityRenderer::computeMirrorViewOperator(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation, + MirrorMode mirrorMode, const QUuid& portalExitID) { glm::mat4 inToWorld = glm::translate(inPropertiesPosition) * glm::mat4_cast(inPropertiesRotation); glm::mat4 worldToIn = glm::inverse(inToWorld); @@ -284,6 +288,7 @@ void EntityRenderer::computeMirrorView(ViewFrustum& viewFrustum) const { glm::vec3 cameraSpacePosition = glm::inverse(view) * glm::vec4(outPropertiesPosition, 1.0f); glm::vec3 cameraSpaceNormal = glm::transpose(view) * (outPropertiesRotation * glm::vec4(0, 0, -1, 0)); glm::vec4 clipPlane = glm::vec4(cameraSpaceNormal, -glm::dot(cameraSpaceNormal, cameraSpacePosition)); + // Make sure we pick the direction facing away from us if (clipPlane.w > 0.0f) { clipPlane *= -1.0f; } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index bfec4743f3..fceba6f0e6 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -76,6 +76,8 @@ public: virtual Item::Bound getBound(RenderArgs* args) override; bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; void computeMirrorView(ViewFrustum& viewFrustum) const override; + static void computeMirrorViewOperator(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation, + MirrorMode mirrorMode, const QUuid& portalExitID); protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ae3f261d48..6b83d87732 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1085,10 +1085,6 @@ void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed, const Mod builder.withSubMetaCulled(); } - if (_mirrorMode == MirrorMode::MIRROR || (_mirrorMode == MirrorMode::PORTAL && !_portalExitID.isNull())) { - builder.withMirror(); - } - if (didVisualGeometryRequestSucceed) { _itemKey = builder.build(); } else { diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index a3ccf78593..6fd99a69fd 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -181,7 +181,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) { } auto geometryCache = DependencyManager::get(); - if (pipelineType == Pipeline::SIMPLE) { + if (pipelineType == Pipeline::SIMPLE || pipelineType == Pipeline::MIRROR) { geometryCache->renderQuad(batch, glm::vec2(-0.5f), glm::vec2(0.5f), backgroundColor, _geometryID); } else { geometryCache->renderQuad(batch, glm::vec2(-0.5f), glm::vec2(0.5f), glm::vec2(0.0f), glm::vec2(1.0f), backgroundColor, _geometryID); @@ -261,6 +261,10 @@ ItemKey entities::TextPayload::getKey() const { builder.withInvisible(); } + if (textRenderable->_mirrorMode == MirrorMode::MIRROR || (textRenderable->_mirrorMode == MirrorMode::PORTAL && !textRenderable->_portalExitID.isNull())) { + builder.withMirror(); + } + return builder; } } @@ -312,6 +316,16 @@ bool entities::TextPayload::passesZoneOcclusionTest(const std::unordered_set(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + return renderable->computeMirrorView(viewFrustum); + } + } +} + void entities::TextPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("TextPayload::render"); Q_ASSERT(args->_batch); @@ -336,12 +350,15 @@ void entities::TextPayload::render(RenderArgs* args) { glm::vec3 dimensions; glm::vec4 textColor; + bool mirror; textRenderable->withReadLock([&] { transform = textRenderable->_renderTransform; dimensions = textRenderable->_dimensions; float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha); + + mirror = textRenderable->_mirrorMode == MirrorMode::MIRROR || (textRenderable->_mirrorMode == MirrorMode::PORTAL && !textRenderable->_portalExitID.isNull()); }); bool forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; @@ -363,9 +380,8 @@ void entities::TextPayload::render(RenderArgs* args) { batch.setModelTransform(transform); glm::vec2 bounds = glm::vec2(dimensions.x - (textRenderable->_leftMargin + textRenderable->_rightMargin), dimensions.y - (textRenderable->_topMargin + textRenderable->_bottomMargin)); - textRenderer->draw(batch, textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale, bounds / scale, scale, - textRenderable->_text, textRenderable->_font, textColor, effectColor, textRenderable->_effectThickness, textRenderable->_effect, - textRenderable->_alignment, textRenderable->_unlit, forward); + textRenderer->draw(batch, textRenderable->_font, { textRenderable->_text, textColor, effectColor, { textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale }, + bounds / scale, scale, textRenderable->_effectThickness, textRenderable->_effect, textRenderable->_alignment, textRenderable->_unlit, forward, mirror }); } namespace render { @@ -401,4 +417,10 @@ template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Poi return false; } +template <> void payloadComputeMirrorView(const entities::TextPayload::Pointer& payload, ViewFrustum& viewFrustum) { + if (payload) { + payload->computeMirrorView(viewFrustum); + } +} + } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 8a18554dea..00b9a1ec19 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -101,6 +101,7 @@ public: ShapeKey getShapeKey() const; void render(RenderArgs* args); bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; + void computeMirrorView(ViewFrustum& viewFrustum) const; protected: QUuid _entityID; @@ -117,6 +118,7 @@ namespace render { template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); + template <> void payloadComputeMirrorView(const entities::TextPayload::Pointer& payload, ViewFrustum& viewFrustum); } #endif // hifi_RenderableTextEntityItem_h diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index de88381468..43d0f379bf 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -221,6 +221,10 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { builder.withSubMetaCulled(); } + if (_mirrorMode == MirrorMode::MIRROR || (_mirrorMode == MirrorMode::PORTAL && !_portalExitID.isNull())) { + builder.withMirror(); + } + _itemKey = builder.build(); } @@ -349,7 +353,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); - } else { + } else if (!_itemKey.isMirror()) { // apply material properties if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; @@ -381,7 +385,9 @@ bool ModelMeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& blendshapeBuffers, const QVector& blendedMeshSizes) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 066e8cb1d8..7d622ab489 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1078,9 +1078,11 @@ void Model::setMirrorMode(MirrorMode mirrorMode, const render::ScenePointer& sce } render::Transaction transaction; + auto renderItemsKey = _renderItemKeyGlobalFlags; for (auto item : _modelMeshRenderItemIDs) { - transaction.updateItem(item, [mirrorMode](ModelMeshPartPayload& data) { + transaction.updateItem(item, [mirrorMode, renderItemsKey](ModelMeshPartPayload& data) { data.setMirrorMode(mirrorMode); + data.updateKey(renderItemsKey); }); } scene->enqueueTransaction(transaction); @@ -1096,9 +1098,11 @@ void Model::setPortalExitID(const QUuid& portalExitID, const render::ScenePointe } render::Transaction transaction; + auto renderItemsKey = _renderItemKeyGlobalFlags; for (auto item : _modelMeshRenderItemIDs) { - transaction.updateItem(item, [portalExitID](ModelMeshPartPayload& data) { + transaction.updateItem(item, [portalExitID, renderItemsKey](ModelMeshPartPayload& data) { data.setPortalExitID(portalExitID); + data.updateKey(renderItemsKey); }); } scene->enqueueTransaction(transaction); diff --git a/libraries/render-utils/src/TextRenderer3D.cpp b/libraries/render-utils/src/TextRenderer3D.cpp index 76d8374fb7..8ab1b8e0e9 100644 --- a/libraries/render-utils/src/TextRenderer3D.cpp +++ b/libraries/render-utils/src/TextRenderer3D.cpp @@ -40,21 +40,18 @@ float TextRenderer3D::getFontSize() const { return 0.0f; } -void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, - const QString& str, const glm::vec4& color, bool unlit, bool forward) { +void TextRenderer3D::draw(gpu::Batch& batch, const Font::DrawProps& props) { if (_font) { - _font->drawString(batch, _drawInfo, str, color, glm::vec3(0.0f), 0, TextEffect::NO_EFFECT, TextAlignment::LEFT, { x, y }, bounds, 1.0f, unlit, forward); + _font->drawString(batch, _drawInfo, props); } } -void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale, - const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor, - float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward) { +void TextRenderer3D::draw(gpu::Batch& batch, const QString& font, const Font::DrawProps& props) { if (font != _family) { _family = font; _font = Font::load(_family); } if (_font) { - _font->drawString(batch, _drawInfo, str, color, effectColor, effectThickness, effect, alignment, { x, y }, bounds, scale, unlit, forward); + _font->drawString(batch, _drawInfo, props); } } \ No newline at end of file diff --git a/libraries/render-utils/src/TextRenderer3D.h b/libraries/render-utils/src/TextRenderer3D.h index edccf1429c..9db93e9dcc 100644 --- a/libraries/render-utils/src/TextRenderer3D.h +++ b/libraries/render-utils/src/TextRenderer3D.h @@ -26,12 +26,9 @@ public: glm::vec2 computeExtent(const QString& str) const; float getFontSize() const; // Pixel size - - void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, - const QString& str, const glm::vec4& color, bool unlit, bool forward); - void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale, - const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor, - float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward); + + void draw(gpu::Batch& batch, const Font::DrawProps& props); + void draw(gpu::Batch& batch, const QString& font, const Font::DrawProps& props); private: TextRenderer3D(const char* family); diff --git a/libraries/render-utils/src/render-utils/sdf_text3D.slp b/libraries/render-utils/src/render-utils/sdf_text3D.slp index 118135d099..f3f9af59aa 100644 --- a/libraries/render-utils/src/render-utils/sdf_text3D.slp +++ b/libraries/render-utils/src/render-utils/sdf_text3D.slp @@ -1 +1 @@ -DEFINES (translucent unlit:f)/forward \ No newline at end of file +DEFINES (translucent unlit:f)/forward mirror:f \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index c5bed1ecab..ebcfe52f4d 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -41,6 +41,12 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord1 _texCoord01.zw layout(location=RENDER_UTILS_ATTR_FADE1) flat in vec4 _glyphBounds; // we're reusing the fade texcoord locations here +<@if HIFI_USE_MIRROR@> + <@include graphics/ShaderConstants.h@> + + LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_MIRROR) uniform sampler2D mirrorMap; +<@endif@> + void main() { vec4 color = evalSDFSuperSampled(_texCoord0, _glyphBounds); @@ -51,13 +57,17 @@ void main() { } <@endif@> +<@if HIFI_USE_MIRROR@> + color.rgb = texelFetch(mirrorMap, ivec2(gl_FragCoord.xy), 0).rgb; +<@endif@> + <@if HIFI_USE_UNLIT@> <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> - _fragColor0 = vec4(color.rgb * isUnlitEnabled(), color.a); + _fragColor0 = vec4(color.rgb * isUnlitEnabled(), 1.0); <@else@> packDeferredFragmentUnlit( normalize(_normalWS), - color.a, + 1.0, color.rgb); <@endif@> <@else@> diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index 1a31e80d7d..95a3d895e8 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -29,7 +29,7 @@ static std::mutex fontMutex; -std::map, gpu::PipelinePointer> Font::_pipelines; +std::map, gpu::PipelinePointer> Font::_pipelines; gpu::Stream::FormatPointer Font::_format; struct TextureVertex { @@ -277,6 +277,7 @@ void Font::setupGPU() { if (_pipelines.empty()) { using namespace shader::render_utils::program; + // transparent, unlit, forward static const std::vector> keys = { std::make_tuple(false, false, false, sdf_text3D), std::make_tuple(true, false, false, sdf_text3D_translucent), std::make_tuple(false, true, false, sdf_text3D_unlit), std::make_tuple(true, true, false, sdf_text3D_translucent_unlit), @@ -284,18 +285,23 @@ void Font::setupGPU() { std::make_tuple(false, true, true, sdf_text3D_translucent_unlit/*sdf_text3D_unlit_forward*/), std::make_tuple(true, true, true, sdf_text3D_translucent_unlit/*sdf_text3D_translucent_unlit_forward*/) }; for (auto& key : keys) { + bool transparent = std::get<0>(key); + bool unlit = std::get<1>(key); + bool forward = std::get<2>(key); + auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, !std::get<0>(key), gpu::LESS_EQUAL); - state->setBlendFunction(std::get<0>(key), + state->setDepthTest(true, !transparent, gpu::LESS_EQUAL); + state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - if (std::get<0>(key)) { + if (transparent) { PrepareStencil::testMask(*state); } else { PrepareStencil::testMaskDrawShape(*state); } - _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key))] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state); + _pipelines[std::make_tuple(transparent, unlit, forward, false)] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state); + _pipelines[std::make_tuple(transparent, unlit, forward, true)] = gpu::Pipeline::create(gpu::Shader::createProgram(forward ? sdf_text3D_forward_mirror : sdf_text3D_mirror), state); } // Sanity checks @@ -444,32 +450,30 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm } } -void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color, - const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment, - const glm::vec2& origin, const glm::vec2& bounds, float scale, bool unlit, bool forward) { - if (!_loaded || str == "") { +void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const DrawProps& props) { + if (!_loaded || props.str == "") { return; } - int textEffect = (int)effect; + int textEffect = (int)props.effect; const int SHADOW_EFFECT = (int)TextEffect::SHADOW_EFFECT; // If we're switching to or from shadow effect mode, we need to rebuild the vertices - if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin || alignment != _alignment || + if (props.str != drawInfo.string || props.bounds != drawInfo.bounds || props.origin != drawInfo.origin || props.alignment != _alignment || (drawInfo.params.effect != textEffect && (textEffect == SHADOW_EFFECT || drawInfo.params.effect == SHADOW_EFFECT)) || - (textEffect == SHADOW_EFFECT && scale != _scale)) { - _scale = scale; - _alignment = alignment; - buildVertices(drawInfo, str, origin, bounds, scale, textEffect == SHADOW_EFFECT, alignment); + (textEffect == SHADOW_EFFECT && props.scale != _scale)) { + _scale = props.scale; + _alignment = props.alignment; + buildVertices(drawInfo, props.str, props.origin, props.bounds, props.scale, textEffect == SHADOW_EFFECT, props.alignment); } setupGPU(); - if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effectColor != effectColor || - drawInfo.params.effectThickness != effectThickness || drawInfo.params.effect != textEffect) { - drawInfo.params.color = color; - drawInfo.params.effectColor = effectColor; - drawInfo.params.effectThickness = effectThickness; + if (!drawInfo.paramsBuffer || drawInfo.params.color != props.color || drawInfo.params.effectColor != props.effectColor || + drawInfo.params.effectThickness != props.effectThickness || drawInfo.params.effect != textEffect) { + drawInfo.params.color = props.color; + drawInfo.params.effectColor = props.effectColor; + drawInfo.params.effectThickness = props.effectThickness; drawInfo.params.effect = textEffect; // need the gamma corrected color here @@ -484,7 +488,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString drawInfo.paramsBuffer->setSubData(0, sizeof(DrawParams), (const gpu::Byte*)&gpuDrawParams); } - batch.setPipeline(_pipelines[std::make_tuple(color.a < 1.0f, unlit, forward)]); + batch.setPipeline(_pipelines[std::make_tuple(props.color.a < 1.0f, props.unlit, props.forward, props.mirror)]); batch.setInputFormat(_format); batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride); batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture); diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h index 322e96439e..e8a353a686 100644 --- a/libraries/render-utils/src/text/Font.h +++ b/libraries/render-utils/src/text/Font.h @@ -57,10 +57,30 @@ public: glm::vec2 computeExtent(const QString& str) const; float getFontSize() const { return _fontSize; } + struct DrawProps { + DrawProps(const QString& str, const glm::vec4& color, const glm::vec3& effectColor, const glm::vec2& origin, const glm::vec2& bounds, + float scale, float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward, bool mirror) : + str(str), color(color), effectColor(effectColor), origin(origin), bounds(bounds), scale(scale), effectThickness(effectThickness), + effect(effect), alignment(alignment), unlit(unlit), forward(forward), mirror(mirror) {} + DrawProps(const QString& str, const glm::vec4& color, const glm::vec2& origin, const glm::vec2& bounds, bool forward) : + str(str), color(color), origin(origin), bounds(bounds), forward(forward) {} + + const QString& str; + const glm::vec4& color; + const glm::vec3& effectColor { glm::vec3(0.0f) }; + const glm::vec2& origin; + const glm::vec2& bounds; + float scale { 1.0f }; + float effectThickness { 0.0f }; + TextEffect effect { TextEffect::NO_EFFECT }; + TextAlignment alignment { TextAlignment::LEFT }; + bool unlit = true; + bool forward; + bool mirror = false; + }; + // Render string to batch - void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, const glm::vec4& color, - const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment, - const glm::vec2& origin, const glm::vec2& bound, float scale, bool unlit, bool forward); + void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const DrawProps& props); static Pointer load(const QString& family); @@ -105,7 +125,7 @@ private: gpu::TexturePointer _texture; gpu::BufferStreamPointer _stream; - static std::map, gpu::PipelinePointer> _pipelines; + static std::map, gpu::PipelinePointer> _pipelines; static gpu::Stream::FormatPointer _format; }; diff --git a/libraries/shared/src/MirrorMode.cpp b/libraries/shared/src/MirrorMode.cpp index 53a51b1c1c..f84948c6e4 100644 --- a/libraries/shared/src/MirrorMode.cpp +++ b/libraries/shared/src/MirrorMode.cpp @@ -15,6 +15,8 @@ const char* MirrorModeNames[] = { }; static const size_t MIRROR_MODE_NAMES = (sizeof(MirrorModeNames) / sizeof(MirrorModeNames[0])); +std::function MirrorModeHelpers::_computeMirrorViewOperator = + [](ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&) { return; }; QString MirrorModeHelpers::getNameForMirrorMode(MirrorMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)MIRROR_MODE_NAMES)) { @@ -23,3 +25,12 @@ QString MirrorModeHelpers::getNameForMirrorMode(MirrorMode mode) { return MirrorModeNames[(int)mode]; } + +void MirrorModeHelpers::setComputeMirrorViewOperator(std::function computeMirrorViewOperator) { + _computeMirrorViewOperator = computeMirrorViewOperator; +} + +void MirrorModeHelpers::computeMirrorView(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation, + MirrorMode mirrorMode, const QUuid& portalExitID) { + _computeMirrorViewOperator(viewFrustum, inPropertiesPosition, inPropertiesRotation, mirrorMode, portalExitID); +} \ No newline at end of file diff --git a/libraries/shared/src/MirrorMode.h b/libraries/shared/src/MirrorMode.h index 38af190070..2b2fa1d62e 100644 --- a/libraries/shared/src/MirrorMode.h +++ b/libraries/shared/src/MirrorMode.h @@ -9,8 +9,12 @@ #ifndef hifi_MirrorMode_h #define hifi_MirrorMode_h +#include + #include "QString" +#include "ViewFrustum.h" + /*@jsdoc *

If an entity is rendered as a mirror, a portal, or normally.

* @@ -35,6 +39,13 @@ enum class MirrorMode { class MirrorModeHelpers { public: static QString getNameForMirrorMode(MirrorMode mode); + + static void setComputeMirrorViewOperator(std::function computeMirrorViewOperator); + static void computeMirrorView(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation, + MirrorMode mirrorMode, const QUuid& portalExitID); + +private: + static std::function _computeMirrorViewOperator; }; #endif // hifi_MirrorMode_h