mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-29 05:49:54 +02:00
Merge pull request #15855 from SamGondelman/forward
BUGZ-661: Fix text entity rendering in deferred vs. forward
This commit is contained in:
commit
07fdbeaa0a
3 changed files with 267 additions and 66 deletions
|
@ -25,28 +25,22 @@ using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
static const int FIXED_FONT_POINT_SIZE = 40;
|
static const int FIXED_FONT_POINT_SIZE = 40;
|
||||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line
|
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line height.
|
||||||
// height.
|
|
||||||
const float LINE_SCALE_RATIO = 1.2f;
|
const float LINE_SCALE_RATIO = 1.2f;
|
||||||
|
|
||||||
TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
||||||
Parent(entity),
|
Parent(entity),
|
||||||
_textRenderer(TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f)) {
|
_textRenderer(TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f)) {
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
if (geometryCache) {
|
|
||||||
_geometryID = geometryCache->allocateID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEntityRenderer::~TextEntityRenderer() {
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
if (_geometryID && geometryCache) {
|
|
||||||
geometryCache->releaseID(_geometryID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextEntityRenderer::isTransparent() const {
|
bool TextEntityRenderer::isTransparent() const {
|
||||||
return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
return Parent::isTransparent() || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextEntityRenderer::isTextTransparent() const {
|
||||||
|
return resultWithReadLock<bool>([&] {
|
||||||
|
return Parent::isTransparent() || _textAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::Bound TextEntityRenderer::getBound() {
|
Item::Bound TextEntityRenderer::getBound() {
|
||||||
|
@ -60,8 +54,12 @@ Item::Bound TextEntityRenderer::getBound() {
|
||||||
return bound;
|
return bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemKey TextEntityRenderer::getKey() {
|
||||||
|
return ItemKey::Builder(Parent::getKey()).withMetaCullGroup();
|
||||||
|
}
|
||||||
|
|
||||||
ShapeKey TextEntityRenderer::getShapeKey() {
|
ShapeKey TextEntityRenderer::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
auto builder = render::ShapeKey::Builder();
|
||||||
if (isTransparent()) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
@ -71,6 +69,15 @@ ShapeKey TextEntityRenderer::getShapeKey() {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t TextEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
|
||||||
|
auto parentSubs = Parent::metaFetchMetaSubItems(subItems);
|
||||||
|
if (Item::isValidID(_textRenderID)) {
|
||||||
|
subItems.emplace_back(_textRenderID);
|
||||||
|
return parentSubs + 1;
|
||||||
|
}
|
||||||
|
return parentSubs;
|
||||||
|
}
|
||||||
|
|
||||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||||
if (_text != entity->getText()) {
|
if (_text != entity->getText()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -134,6 +141,7 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
||||||
_dimensions = entity->getScaledDimensions();
|
_dimensions = entity->getScaledDimensions();
|
||||||
updateModelTransformAndBound();
|
updateModelTransformAndBound();
|
||||||
_renderTransform = getModelTransform();
|
_renderTransform = getModelTransform();
|
||||||
|
_renderTransform.postScale(_dimensions);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -152,65 +160,49 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
||||||
_rightMargin = entity->getRightMargin();
|
_rightMargin = entity->getRightMargin();
|
||||||
_topMargin = entity->getTopMargin();
|
_topMargin = entity->getTopMargin();
|
||||||
_bottomMargin = entity->getBottomMargin();
|
_bottomMargin = entity->getBottomMargin();
|
||||||
|
updateTextRenderItem();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEntityRenderer::doRender(RenderArgs* args) {
|
void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||||
|
|
||||||
glm::vec4 textColor;
|
|
||||||
glm::vec4 backgroundColor;
|
|
||||||
Transform modelTransform;
|
|
||||||
glm::vec3 dimensions;
|
|
||||||
BillboardMode billboardMode;
|
|
||||||
bool forward;
|
|
||||||
withReadLock([&] {
|
|
||||||
modelTransform = _renderTransform;
|
|
||||||
dimensions = _dimensions;
|
|
||||||
billboardMode = _billboardMode;
|
|
||||||
|
|
||||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
|
||||||
textColor = glm::vec4(_textColor, fadeRatio * _textAlpha);
|
|
||||||
textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created);
|
|
||||||
backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
|
|
||||||
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
|
|
||||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Render background
|
|
||||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
|
||||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
|
||||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
|
||||||
|
|
||||||
// Batch render calls
|
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
|
||||||
// FIXME: we need to find a better way of rendering text so we don't have to do this
|
glm::vec4 backgroundColor;
|
||||||
if (forward) {
|
Transform modelTransform;
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
|
BillboardMode billboardMode;
|
||||||
|
PrimitiveMode primitiveMode;
|
||||||
|
RenderLayer renderLayer;
|
||||||
|
withReadLock([&] {
|
||||||
|
modelTransform = _renderTransform;
|
||||||
|
billboardMode = _billboardMode;
|
||||||
|
primitiveMode = _primitiveMode;
|
||||||
|
renderLayer = _renderLayer;
|
||||||
|
|
||||||
|
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||||
|
backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
|
||||||
|
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (backgroundColor.a <= 0.0f) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto transformToTopLeft = modelTransform;
|
modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition()));
|
||||||
transformToTopLeft.setRotation(EntityItem::getBillboardRotation(transformToTopLeft.getTranslation(), transformToTopLeft.getRotation(), billboardMode, args->getViewFrustum().getPosition()));
|
batch.setModelTransform(modelTransform);
|
||||||
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
|
||||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
|
||||||
|
|
||||||
if (backgroundColor.a > 0.0f) {
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
batch.setModelTransform(transformToTopLeft);
|
render::ShapePipelinePointer pipeline;
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
if (renderLayer == RenderLayer::WORLD && args->_renderMethod != Args::RenderMethod::FORWARD) {
|
||||||
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, forward);
|
pipeline = backgroundColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
} else {
|
||||||
|
pipeline = backgroundColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline();
|
||||||
}
|
}
|
||||||
|
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
||||||
if (textColor.a > 0.0f) {
|
geometryCache->renderWireShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline);
|
||||||
// FIXME: Factor out textRenderer so that text parts can be grouped by pipeline for a gpu performance increase.
|
} else {
|
||||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline);
|
||||||
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
|
||||||
batch.setModelTransform(transformToTopLeft);
|
|
||||||
|
|
||||||
glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin));
|
|
||||||
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, forward);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,4 +214,173 @@ QSizeF TextEntityRenderer::textSize(const QString& text) const {
|
||||||
float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||||
|
|
||||||
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEntityRenderer::onAddToSceneTyped(const TypedEntityPointer& entity) {
|
||||||
|
Parent::onAddToSceneTyped(entity);
|
||||||
|
_textPayload = std::make_shared<TextPayload>(entity->getID(), _textRenderer);
|
||||||
|
_textRenderID = AbstractViewStateInterface::instance()->getMain3DScene()->allocateID();
|
||||||
|
auto renderPayload = std::make_shared<TextPayload::Payload>(_textPayload);
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.resetItem(_textRenderID, renderPayload);
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
|
updateTextRenderItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
||||||
|
Parent::onRemoveFromSceneTyped(entity);
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.removeItem(_textRenderID);
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
|
_textPayload.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextEntityRenderer::updateTextRenderItem() const {
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.updateItem(_textRenderID);
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
entities::TextPayload::TextPayload(const QUuid& entityID, const std::weak_ptr<TextRenderer3D>& textRenderer) :
|
||||||
|
_entityID(entityID), _textRenderer(textRenderer) {
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
if (geometryCache) {
|
||||||
|
_geometryID = geometryCache->allocateID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entities::TextPayload::~TextPayload() {
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
if (_geometryID && geometryCache) {
|
||||||
|
geometryCache->releaseID(_geometryID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemKey entities::TextPayload::getKey() const {
|
||||||
|
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||||
|
if (renderable) {
|
||||||
|
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||||
|
ItemKey::Builder key;
|
||||||
|
// Similar to EntityRenderer::getKey()
|
||||||
|
if (textRenderable->isTextTransparent()) {
|
||||||
|
key = ItemKey::Builder::transparentShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||||
|
} else if (textRenderable->_canCastShadow) {
|
||||||
|
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withShadowCaster().withLayer(textRenderable->getHifiRenderLayer());
|
||||||
|
} else {
|
||||||
|
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textRenderable->_visible) {
|
||||||
|
key.withInvisible();
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return ItemKey::Builder::opaqueShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
Item::Bound entities::TextPayload::getBound() const {
|
||||||
|
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||||
|
if (renderable) {
|
||||||
|
return std::static_pointer_cast<TextEntityRenderer>(renderable)->getBound();
|
||||||
|
}
|
||||||
|
return Item::Bound();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeKey entities::TextPayload::getShapeKey() const {
|
||||||
|
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||||
|
if (renderable) {
|
||||||
|
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||||
|
|
||||||
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
|
if (textRenderable->isTextTransparent()) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
if (textRenderable->_primitiveMode == PrimitiveMode::LINES) {
|
||||||
|
builder.withWireframe();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
return ShapeKey::Builder::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void entities::TextPayload::render(RenderArgs* args) {
|
||||||
|
PerformanceTimer perfTimer("TextPayload::render");
|
||||||
|
Q_ASSERT(args->_batch);
|
||||||
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
|
||||||
|
auto textRenderer = _textRenderer.lock();
|
||||||
|
if (!textRenderer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||||
|
if (!renderable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||||
|
|
||||||
|
glm::vec4 textColor;
|
||||||
|
Transform modelTransform;
|
||||||
|
BillboardMode billboardMode;
|
||||||
|
float lineHeight, leftMargin, rightMargin, topMargin, bottomMargin;
|
||||||
|
QString text;
|
||||||
|
glm::vec3 dimensions;
|
||||||
|
bool forward;
|
||||||
|
textRenderable->withReadLock([&] {
|
||||||
|
modelTransform = textRenderable->_renderTransform;
|
||||||
|
billboardMode = textRenderable->_billboardMode;
|
||||||
|
lineHeight = textRenderable->_lineHeight;
|
||||||
|
leftMargin = textRenderable->_leftMargin;
|
||||||
|
rightMargin = textRenderable->_rightMargin;
|
||||||
|
topMargin = textRenderable->_topMargin;
|
||||||
|
bottomMargin = textRenderable->_bottomMargin;
|
||||||
|
text = textRenderable->_text;
|
||||||
|
dimensions = textRenderable->_dimensions;
|
||||||
|
|
||||||
|
float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f;
|
||||||
|
textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha);
|
||||||
|
textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created);
|
||||||
|
forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (textColor.a <= 0.0f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition()));
|
||||||
|
|
||||||
|
float scale = lineHeight / textRenderer->getFontSize();
|
||||||
|
modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z));
|
||||||
|
modelTransform.setScale(scale);
|
||||||
|
batch.setModelTransform(modelTransform);
|
||||||
|
|
||||||
|
glm::vec2 bounds = glm::vec2(dimensions.x - (leftMargin + rightMargin), dimensions.y - (topMargin + bottomMargin));
|
||||||
|
textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale, forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
template <> const ItemKey payloadGetKey(const TextPayload::Pointer& payload) {
|
||||||
|
if (payload) {
|
||||||
|
return payload->getKey();
|
||||||
|
}
|
||||||
|
return ItemKey::Builder::opaqueShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload) {
|
||||||
|
if (payload) {
|
||||||
|
return payload->getBound();
|
||||||
|
}
|
||||||
|
return Item::Bound();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> const ShapeKey shapeGetShapeKey(const TextPayload::Pointer& payload) {
|
||||||
|
if (payload) {
|
||||||
|
return payload->getShapeKey();
|
||||||
|
}
|
||||||
|
return ShapeKey::Builder::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> void payloadRender(const TextPayload::Pointer& payload, RenderArgs* args) {
|
||||||
|
return payload->render(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,19 +19,26 @@ class TextRenderer3D;
|
||||||
|
|
||||||
namespace render { namespace entities {
|
namespace render { namespace entities {
|
||||||
|
|
||||||
|
class TextPayload;
|
||||||
|
|
||||||
class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
||||||
using Parent = TypedEntityRenderer<TextEntityItem>;
|
using Parent = TypedEntityRenderer<TextEntityItem>;
|
||||||
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
||||||
public:
|
public:
|
||||||
TextEntityRenderer(const EntityItemPointer& entity);
|
TextEntityRenderer(const EntityItemPointer& entity);
|
||||||
~TextEntityRenderer();
|
|
||||||
|
|
||||||
QSizeF textSize(const QString& text) const;
|
QSizeF textSize(const QString& text) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool isTransparent() const override;
|
bool isTransparent() const override;
|
||||||
|
bool isTextTransparent() const;
|
||||||
Item::Bound getBound() override;
|
Item::Bound getBound() override;
|
||||||
ShapeKey getShapeKey() override;
|
ShapeKey getShapeKey() override;
|
||||||
|
ItemKey getKey() override;
|
||||||
|
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override;
|
||||||
|
|
||||||
|
void onAddToSceneTyped(const TypedEntityPointer& entity) override;
|
||||||
|
void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
|
@ -39,7 +46,6 @@ private:
|
||||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
|
|
||||||
int _geometryID{ 0 };
|
|
||||||
std::shared_ptr<TextRenderer3D> _textRenderer;
|
std::shared_ptr<TextRenderer3D> _textRenderer;
|
||||||
|
|
||||||
PulsePropertyGroup _pulseProperties;
|
PulsePropertyGroup _pulseProperties;
|
||||||
|
@ -58,8 +64,42 @@ private:
|
||||||
|
|
||||||
BillboardMode _billboardMode;
|
BillboardMode _billboardMode;
|
||||||
glm::vec3 _dimensions;
|
glm::vec3 _dimensions;
|
||||||
|
|
||||||
|
std::shared_ptr<TextPayload> _textPayload;
|
||||||
|
render::ItemID _textRenderID;
|
||||||
|
void updateTextRenderItem() const;
|
||||||
|
|
||||||
|
friend class render::entities::TextPayload;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextPayload {
|
||||||
|
public:
|
||||||
|
TextPayload() = default;
|
||||||
|
TextPayload(const QUuid& entityID, const std::weak_ptr<TextRenderer3D>& textRenderer);
|
||||||
|
~TextPayload();
|
||||||
|
|
||||||
|
typedef render::Payload<TextPayload> Payload;
|
||||||
|
typedef Payload::DataPointer Pointer;
|
||||||
|
|
||||||
|
ItemKey getKey() const;
|
||||||
|
Item::Bound getBound() const;
|
||||||
|
ShapeKey getShapeKey() const;
|
||||||
|
void render(RenderArgs* args);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QUuid _entityID;
|
||||||
|
std::weak_ptr<TextRenderer3D> _textRenderer;
|
||||||
|
|
||||||
|
int _geometryID { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
template <> const ItemKey payloadGetKey(const entities::TextPayload::Pointer& payload);
|
||||||
|
template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload);
|
||||||
|
template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload);
|
||||||
|
template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // hifi_RenderableTextEntityItem_h
|
#endif // hifi_RenderableTextEntityItem_h
|
||||||
|
|
|
@ -30,7 +30,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
|
||||||
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
|
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
|
||||||
|
|
||||||
// Layered objects are not culled
|
// Layered objects are not culled
|
||||||
const ItemFilter layeredFilter = ItemFilter::Builder().withVisible().withoutSubMetaCulled().withTagBits(tagBits, tagMask);
|
const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask);
|
||||||
const auto nonspatialFilter = render::Varying(layeredFilter);
|
const auto nonspatialFilter = render::Varying(layeredFilter);
|
||||||
const auto nonspatialSelection = task.addJob<FetchNonspatialItems>("FetchLayeredSelection", nonspatialFilter);
|
const auto nonspatialSelection = task.addJob<FetchNonspatialItems>("FetchLayeredSelection", nonspatialFilter);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue