mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 03:35:47 +02:00
mirrors on models + text
This commit is contained in:
parent
093cf29778
commit
a630a6f9c9
17 changed files with 142 additions and 54 deletions
|
@ -2479,6 +2479,7 @@ Application::Application(
|
||||||
copyViewFrustum(viewFrustum);
|
copyViewFrustum(viewFrustum);
|
||||||
return viewFrustum.getPosition();
|
return viewFrustum.getPosition();
|
||||||
});
|
});
|
||||||
|
MirrorModeHelpers::setComputeMirrorViewOperator(EntityRenderer::computeMirrorViewOperator);
|
||||||
|
|
||||||
DependencyManager::get<UsersScriptingInterface>()->setKickConfirmationOperator([this] (const QUuid& nodeID, unsigned int banFlags) { userKickConfirmation(nodeID, banFlags); });
|
DependencyManager::get<UsersScriptingInterface>()->setKickConfirmationOperator([this] (const QUuid& nodeID, unsigned int banFlags) { userKickConfirmation(nodeID, banFlags); });
|
||||||
|
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
||||||
batch.setModelTransform(textTransform);
|
batch.setModelTransform(textTransform);
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText");
|
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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,11 @@ void EntityRenderer::computeMirrorView(ViewFrustum& viewFrustum) const {
|
||||||
mirrorMode = _mirrorMode;
|
mirrorMode = _mirrorMode;
|
||||||
portalExitID = _portalExitID;
|
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 inToWorld = glm::translate(inPropertiesPosition) * glm::mat4_cast(inPropertiesRotation);
|
||||||
glm::mat4 worldToIn = glm::inverse(inToWorld);
|
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 cameraSpacePosition = glm::inverse(view) * glm::vec4(outPropertiesPosition, 1.0f);
|
||||||
glm::vec3 cameraSpaceNormal = glm::transpose(view) * (outPropertiesRotation * glm::vec4(0, 0, -1, 0));
|
glm::vec3 cameraSpaceNormal = glm::transpose(view) * (outPropertiesRotation * glm::vec4(0, 0, -1, 0));
|
||||||
glm::vec4 clipPlane = glm::vec4(cameraSpaceNormal, -glm::dot(cameraSpaceNormal, cameraSpacePosition));
|
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) {
|
if (clipPlane.w > 0.0f) {
|
||||||
clipPlane *= -1.0f;
|
clipPlane *= -1.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ public:
|
||||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||||
bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const override;
|
bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const override;
|
||||||
void computeMirrorView(ViewFrustum& viewFrustum) 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:
|
protected:
|
||||||
virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); }
|
virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); }
|
||||||
|
|
|
@ -1085,10 +1085,6 @@ void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed, const Mod
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mirrorMode == MirrorMode::MIRROR || (_mirrorMode == MirrorMode::PORTAL && !_portalExitID.isNull())) {
|
|
||||||
builder.withMirror();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (didVisualGeometryRequestSucceed) {
|
if (didVisualGeometryRequestSucceed) {
|
||||||
_itemKey = builder.build();
|
_itemKey = builder.build();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -181,7 +181,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
if (pipelineType == Pipeline::SIMPLE) {
|
if (pipelineType == Pipeline::SIMPLE || pipelineType == Pipeline::MIRROR) {
|
||||||
geometryCache->renderQuad(batch, glm::vec2(-0.5f), glm::vec2(0.5f), backgroundColor, _geometryID);
|
geometryCache->renderQuad(batch, glm::vec2(-0.5f), glm::vec2(0.5f), backgroundColor, _geometryID);
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderQuad(batch, glm::vec2(-0.5f), glm::vec2(0.5f), glm::vec2(0.0f), glm::vec2(1.0f), backgroundColor, _geometryID);
|
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();
|
builder.withInvisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (textRenderable->_mirrorMode == MirrorMode::MIRROR || (textRenderable->_mirrorMode == MirrorMode::PORTAL && !textRenderable->_portalExitID.isNull())) {
|
||||||
|
builder.withMirror();
|
||||||
|
}
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,6 +316,16 @@ bool entities::TextPayload::passesZoneOcclusionTest(const std::unordered_set<QUu
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void entities::TextPayload::computeMirrorView(ViewFrustum& viewFrustum) const {
|
||||||
|
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||||
|
if (entityTreeRenderer) {
|
||||||
|
auto renderable = entityTreeRenderer->renderableForEntityId(_entityID);
|
||||||
|
if (renderable) {
|
||||||
|
return renderable->computeMirrorView(viewFrustum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void entities::TextPayload::render(RenderArgs* args) {
|
void entities::TextPayload::render(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("TextPayload::render");
|
PerformanceTimer perfTimer("TextPayload::render");
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
|
@ -336,12 +350,15 @@ void entities::TextPayload::render(RenderArgs* args) {
|
||||||
glm::vec3 dimensions;
|
glm::vec3 dimensions;
|
||||||
|
|
||||||
glm::vec4 textColor;
|
glm::vec4 textColor;
|
||||||
|
bool mirror;
|
||||||
textRenderable->withReadLock([&] {
|
textRenderable->withReadLock([&] {
|
||||||
transform = textRenderable->_renderTransform;
|
transform = textRenderable->_renderTransform;
|
||||||
dimensions = textRenderable->_dimensions;
|
dimensions = textRenderable->_dimensions;
|
||||||
|
|
||||||
float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f;
|
float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f;
|
||||||
textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha);
|
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;
|
bool forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
||||||
|
@ -363,9 +380,8 @@ void entities::TextPayload::render(RenderArgs* args) {
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
glm::vec2 bounds = glm::vec2(dimensions.x - (textRenderable->_leftMargin + textRenderable->_rightMargin), dimensions.y - (textRenderable->_topMargin + textRenderable->_bottomMargin));
|
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,
|
textRenderer->draw(batch, textRenderable->_font, { textRenderable->_text, textColor, effectColor, { textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale },
|
||||||
textRenderable->_text, textRenderable->_font, textColor, effectColor, textRenderable->_effectThickness, textRenderable->_effect,
|
bounds / scale, scale, textRenderable->_effectThickness, textRenderable->_effect, textRenderable->_alignment, textRenderable->_unlit, forward, mirror });
|
||||||
textRenderable->_alignment, textRenderable->_unlit, forward);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
@ -401,4 +417,10 @@ template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Poi
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> void payloadComputeMirrorView(const entities::TextPayload::Pointer& payload, ViewFrustum& viewFrustum) {
|
||||||
|
if (payload) {
|
||||||
|
payload->computeMirrorView(viewFrustum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ public:
|
||||||
ShapeKey getShapeKey() const;
|
ShapeKey getShapeKey() const;
|
||||||
void render(RenderArgs* args);
|
void render(RenderArgs* args);
|
||||||
bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const;
|
bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const;
|
||||||
|
void computeMirrorView(ViewFrustum& viewFrustum) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUuid _entityID;
|
QUuid _entityID;
|
||||||
|
@ -117,6 +118,7 @@ namespace render {
|
||||||
template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload);
|
template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload);
|
||||||
template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args);
|
template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args);
|
||||||
template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set<QUuid>& containingZones);
|
template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set<QUuid>& containingZones);
|
||||||
|
template <> void payloadComputeMirrorView(const entities::TextPayload::Pointer& payload, ViewFrustum& viewFrustum);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_RenderableTextEntityItem_h
|
#endif // hifi_RenderableTextEntityItem_h
|
||||||
|
|
|
@ -221,6 +221,10 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) {
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mirrorMode == MirrorMode::MIRROR || (_mirrorMode == MirrorMode::PORTAL && !_portalExitID.isNull())) {
|
||||||
|
builder.withMirror();
|
||||||
|
}
|
||||||
|
|
||||||
_itemKey = builder.build();
|
_itemKey = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +353,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
|
||||||
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created,
|
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created,
|
||||||
ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned()));
|
ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned()));
|
||||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||||
} else {
|
} else if (!_itemKey.isMirror()) {
|
||||||
// apply material properties
|
// apply material properties
|
||||||
if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) {
|
if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
|
@ -381,7 +385,9 @@ bool ModelMeshPartPayload::passesZoneOcclusionTest(const std::unordered_set<QUui
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::computeMirrorView(ViewFrustum& viewFrustum) const {
|
void ModelMeshPartPayload::computeMirrorView(ViewFrustum& viewFrustum) const {
|
||||||
return;
|
Transform transform = _parentTransform;
|
||||||
|
transform = transform.worldTransform(_localTransform);
|
||||||
|
MirrorModeHelpers::computeMirrorView(viewFrustum, transform.getTranslation(), transform.getRotation(), _mirrorMode, _portalExitID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map<int, gpu::BufferPointer>& blendshapeBuffers, const QVector<int>& blendedMeshSizes) {
|
void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map<int, gpu::BufferPointer>& blendshapeBuffers, const QVector<int>& blendedMeshSizes) {
|
||||||
|
|
|
@ -1078,9 +1078,11 @@ void Model::setMirrorMode(MirrorMode mirrorMode, const render::ScenePointer& sce
|
||||||
}
|
}
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
for (auto item : _modelMeshRenderItemIDs) {
|
for (auto item : _modelMeshRenderItemIDs) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [mirrorMode](ModelMeshPartPayload& data) {
|
transaction.updateItem<ModelMeshPartPayload>(item, [mirrorMode, renderItemsKey](ModelMeshPartPayload& data) {
|
||||||
data.setMirrorMode(mirrorMode);
|
data.setMirrorMode(mirrorMode);
|
||||||
|
data.updateKey(renderItemsKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
|
@ -1096,9 +1098,11 @@ void Model::setPortalExitID(const QUuid& portalExitID, const render::ScenePointe
|
||||||
}
|
}
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
for (auto item : _modelMeshRenderItemIDs) {
|
for (auto item : _modelMeshRenderItemIDs) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [portalExitID](ModelMeshPartPayload& data) {
|
transaction.updateItem<ModelMeshPartPayload>(item, [portalExitID, renderItemsKey](ModelMeshPartPayload& data) {
|
||||||
data.setPortalExitID(portalExitID);
|
data.setPortalExitID(portalExitID);
|
||||||
|
data.updateKey(renderItemsKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
|
|
|
@ -40,21 +40,18 @@ float TextRenderer3D::getFontSize() const {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds,
|
void TextRenderer3D::draw(gpu::Batch& batch, const Font::DrawProps& props) {
|
||||||
const QString& str, const glm::vec4& color, bool unlit, bool forward) {
|
|
||||||
if (_font) {
|
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,
|
void TextRenderer3D::draw(gpu::Batch& batch, const QString& font, const Font::DrawProps& props) {
|
||||||
const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor,
|
|
||||||
float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward) {
|
|
||||||
if (font != _family) {
|
if (font != _family) {
|
||||||
_family = font;
|
_family = font;
|
||||||
_font = Font::load(_family);
|
_font = Font::load(_family);
|
||||||
}
|
}
|
||||||
if (_font) {
|
if (_font) {
|
||||||
_font->drawString(batch, _drawInfo, str, color, effectColor, effectThickness, effect, alignment, { x, y }, bounds, scale, unlit, forward);
|
_font->drawString(batch, _drawInfo, props);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,12 +26,9 @@ public:
|
||||||
|
|
||||||
glm::vec2 computeExtent(const QString& str) const;
|
glm::vec2 computeExtent(const QString& str) const;
|
||||||
float getFontSize() const; // Pixel size
|
float getFontSize() const; // Pixel size
|
||||||
|
|
||||||
void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds,
|
void draw(gpu::Batch& batch, const Font::DrawProps& props);
|
||||||
const QString& str, const glm::vec4& color, bool unlit, bool forward);
|
void draw(gpu::Batch& batch, const QString& font, const Font::DrawProps& props);
|
||||||
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);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextRenderer3D(const char* family);
|
TextRenderer3D(const char* family);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
DEFINES (translucent unlit:f)/forward
|
DEFINES (translucent unlit:f)/forward mirror:f
|
|
@ -41,6 +41,12 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
|
||||||
#define _texCoord1 _texCoord01.zw
|
#define _texCoord1 _texCoord01.zw
|
||||||
layout(location=RENDER_UTILS_ATTR_FADE1) flat in vec4 _glyphBounds; // we're reusing the fade texcoord locations here
|
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() {
|
void main() {
|
||||||
vec4 color = evalSDFSuperSampled(_texCoord0, _glyphBounds);
|
vec4 color = evalSDFSuperSampled(_texCoord0, _glyphBounds);
|
||||||
|
|
||||||
|
@ -51,13 +57,17 @@ void main() {
|
||||||
}
|
}
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
<@if HIFI_USE_MIRROR@>
|
||||||
|
color.rgb = texelFetch(mirrorMap, ivec2(gl_FragCoord.xy), 0).rgb;
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
<@if HIFI_USE_UNLIT@>
|
<@if HIFI_USE_UNLIT@>
|
||||||
<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@>
|
<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@>
|
||||||
_fragColor0 = vec4(color.rgb * isUnlitEnabled(), color.a);
|
_fragColor0 = vec4(color.rgb * isUnlitEnabled(), 1.0);
|
||||||
<@else@>
|
<@else@>
|
||||||
packDeferredFragmentUnlit(
|
packDeferredFragmentUnlit(
|
||||||
normalize(_normalWS),
|
normalize(_normalWS),
|
||||||
color.a,
|
1.0,
|
||||||
color.rgb);
|
color.rgb);
|
||||||
<@endif@>
|
<@endif@>
|
||||||
<@else@>
|
<@else@>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
static std::mutex fontMutex;
|
static std::mutex fontMutex;
|
||||||
|
|
||||||
std::map<std::tuple<bool, bool, bool>, gpu::PipelinePointer> Font::_pipelines;
|
std::map<std::tuple<bool, bool, bool, bool>, gpu::PipelinePointer> Font::_pipelines;
|
||||||
gpu::Stream::FormatPointer Font::_format;
|
gpu::Stream::FormatPointer Font::_format;
|
||||||
|
|
||||||
struct TextureVertex {
|
struct TextureVertex {
|
||||||
|
@ -277,6 +277,7 @@ void Font::setupGPU() {
|
||||||
if (_pipelines.empty()) {
|
if (_pipelines.empty()) {
|
||||||
using namespace shader::render_utils::program;
|
using namespace shader::render_utils::program;
|
||||||
|
|
||||||
|
// transparent, unlit, forward
|
||||||
static const std::vector<std::tuple<bool, bool, bool, uint32_t>> keys = {
|
static const std::vector<std::tuple<bool, bool, bool, uint32_t>> keys = {
|
||||||
std::make_tuple(false, false, false, sdf_text3D), std::make_tuple(true, false, false, sdf_text3D_translucent),
|
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),
|
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*/)
|
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) {
|
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<gpu::State>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
state->setCullMode(gpu::State::CULL_BACK);
|
||||||
state->setDepthTest(true, !std::get<0>(key), gpu::LESS_EQUAL);
|
state->setDepthTest(true, !transparent, gpu::LESS_EQUAL);
|
||||||
state->setBlendFunction(std::get<0>(key),
|
state->setBlendFunction(transparent,
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
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);
|
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
if (std::get<0>(key)) {
|
if (transparent) {
|
||||||
PrepareStencil::testMask(*state);
|
PrepareStencil::testMask(*state);
|
||||||
} else {
|
} else {
|
||||||
PrepareStencil::testMaskDrawShape(*state);
|
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
|
// 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,
|
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const DrawProps& props) {
|
||||||
const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment,
|
if (!_loaded || props.str == "") {
|
||||||
const glm::vec2& origin, const glm::vec2& bounds, float scale, bool unlit, bool forward) {
|
|
||||||
if (!_loaded || str == "") {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textEffect = (int)effect;
|
int textEffect = (int)props.effect;
|
||||||
const int SHADOW_EFFECT = (int)TextEffect::SHADOW_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 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)) ||
|
(drawInfo.params.effect != textEffect && (textEffect == SHADOW_EFFECT || drawInfo.params.effect == SHADOW_EFFECT)) ||
|
||||||
(textEffect == SHADOW_EFFECT && scale != _scale)) {
|
(textEffect == SHADOW_EFFECT && props.scale != _scale)) {
|
||||||
_scale = scale;
|
_scale = props.scale;
|
||||||
_alignment = alignment;
|
_alignment = props.alignment;
|
||||||
buildVertices(drawInfo, str, origin, bounds, scale, textEffect == SHADOW_EFFECT, alignment);
|
buildVertices(drawInfo, props.str, props.origin, props.bounds, props.scale, textEffect == SHADOW_EFFECT, props.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupGPU();
|
setupGPU();
|
||||||
|
|
||||||
if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effectColor != effectColor ||
|
if (!drawInfo.paramsBuffer || drawInfo.params.color != props.color || drawInfo.params.effectColor != props.effectColor ||
|
||||||
drawInfo.params.effectThickness != effectThickness || drawInfo.params.effect != textEffect) {
|
drawInfo.params.effectThickness != props.effectThickness || drawInfo.params.effect != textEffect) {
|
||||||
drawInfo.params.color = color;
|
drawInfo.params.color = props.color;
|
||||||
drawInfo.params.effectColor = effectColor;
|
drawInfo.params.effectColor = props.effectColor;
|
||||||
drawInfo.params.effectThickness = effectThickness;
|
drawInfo.params.effectThickness = props.effectThickness;
|
||||||
drawInfo.params.effect = textEffect;
|
drawInfo.params.effect = textEffect;
|
||||||
|
|
||||||
// need the gamma corrected color here
|
// 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);
|
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.setInputFormat(_format);
|
||||||
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||||
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
||||||
|
|
|
@ -57,10 +57,30 @@ public:
|
||||||
glm::vec2 computeExtent(const QString& str) const;
|
glm::vec2 computeExtent(const QString& str) const;
|
||||||
float getFontSize() const { return _fontSize; }
|
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
|
// Render string to batch
|
||||||
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
|
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const DrawProps& props);
|
||||||
const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment,
|
|
||||||
const glm::vec2& origin, const glm::vec2& bound, float scale, bool unlit, bool forward);
|
|
||||||
|
|
||||||
static Pointer load(const QString& family);
|
static Pointer load(const QString& family);
|
||||||
|
|
||||||
|
@ -105,7 +125,7 @@ private:
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
gpu::BufferStreamPointer _stream;
|
gpu::BufferStreamPointer _stream;
|
||||||
|
|
||||||
static std::map<std::tuple<bool, bool, bool>, gpu::PipelinePointer> _pipelines;
|
static std::map<std::tuple<bool, bool, bool, bool>, gpu::PipelinePointer> _pipelines;
|
||||||
static gpu::Stream::FormatPointer _format;
|
static gpu::Stream::FormatPointer _format;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ const char* MirrorModeNames[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t MIRROR_MODE_NAMES = (sizeof(MirrorModeNames) / sizeof(MirrorModeNames[0]));
|
static const size_t MIRROR_MODE_NAMES = (sizeof(MirrorModeNames) / sizeof(MirrorModeNames[0]));
|
||||||
|
std::function<void(ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&)> MirrorModeHelpers::_computeMirrorViewOperator =
|
||||||
|
[](ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&) { return; };
|
||||||
|
|
||||||
QString MirrorModeHelpers::getNameForMirrorMode(MirrorMode mode) {
|
QString MirrorModeHelpers::getNameForMirrorMode(MirrorMode mode) {
|
||||||
if (((int)mode <= 0) || ((int)mode >= (int)MIRROR_MODE_NAMES)) {
|
if (((int)mode <= 0) || ((int)mode >= (int)MIRROR_MODE_NAMES)) {
|
||||||
|
@ -23,3 +25,12 @@ QString MirrorModeHelpers::getNameForMirrorMode(MirrorMode mode) {
|
||||||
|
|
||||||
return MirrorModeNames[(int)mode];
|
return MirrorModeNames[(int)mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MirrorModeHelpers::setComputeMirrorViewOperator(std::function<void(ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&)> 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);
|
||||||
|
}
|
|
@ -9,8 +9,12 @@
|
||||||
#ifndef hifi_MirrorMode_h
|
#ifndef hifi_MirrorMode_h
|
||||||
#define hifi_MirrorMode_h
|
#define hifi_MirrorMode_h
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "QString"
|
#include "QString"
|
||||||
|
|
||||||
|
#include "ViewFrustum.h"
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* <p>If an entity is rendered as a mirror, a portal, or normally.</p>
|
* <p>If an entity is rendered as a mirror, a portal, or normally.</p>
|
||||||
* <table>
|
* <table>
|
||||||
|
@ -35,6 +39,13 @@ enum class MirrorMode {
|
||||||
class MirrorModeHelpers {
|
class MirrorModeHelpers {
|
||||||
public:
|
public:
|
||||||
static QString getNameForMirrorMode(MirrorMode mode);
|
static QString getNameForMirrorMode(MirrorMode mode);
|
||||||
|
|
||||||
|
static void setComputeMirrorViewOperator(std::function<void(ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&)> computeMirrorViewOperator);
|
||||||
|
static void computeMirrorView(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation,
|
||||||
|
MirrorMode mirrorMode, const QUuid& portalExitID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::function<void(ViewFrustum&, const glm::vec3&, const glm::quat&, MirrorMode, const QUuid&)> _computeMirrorViewOperator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MirrorMode_h
|
#endif // hifi_MirrorMode_h
|
||||||
|
|
Loading…
Reference in a new issue