diff options
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp')
m--------- | src/Runtime/ogl-runtime | 0 | ||||
-rw-r--r-- | src/Runtime/ogl-runtime/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp | 1067 |
2 files changed, 0 insertions, 1067 deletions
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime new file mode 160000 +Subproject 2025912174c4cf99270b7439ec3b021e1d089ae diff --git a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp b/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp deleted file mode 100644 index 8c1b28af..00000000 --- a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp +++ /dev/null @@ -1,1067 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of Qt 3D Studio. -** -** $QT_BEGIN_LICENSE:GPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "Qt3DSDistanceFieldRenderer.h" - -#if QT_VERSION >= QT_VERSION_CHECK(5,12,2) - -#include "Qt3DSRenderContextCore.h" -#include "Qt3DSRenderShaderCodeGeneratorV2.h" -#include "render/Qt3DSRenderBaseTypes.h" -#include "render/Qt3DSRenderContext.h" -#include "qmath.h" -#include "foundation/Qt3DSAllocator.h" - -using namespace qt3ds::render; - -Q3DSDistanceFieldRenderer::Q3DSDistanceFieldRenderer(NVFoundationBase &foundation) - : m_foundation(foundation) -{ - const QWindowList list = QGuiApplication::topLevelWindows(); - if (list.size() > 0) - m_pixelRatio = list[0]->devicePixelRatio(); -} - -Q3DSDistanceFieldRenderer::~Q3DSDistanceFieldRenderer() -{ - NVAllocatorCallback &alloc = m_context->GetAllocator(); - - QHash<size_t, Q3DSDistanceFieldMesh>::const_iterator it; - for (it = m_meshCache.constBegin(); it != m_meshCache.constEnd(); ++it) { - const Q3DSDistanceFieldMesh &mesh = it.value(); - NVDelete(alloc, mesh.vertexBuffer); - NVDelete(alloc, mesh.indexBuffer); - NVDelete(alloc, mesh.inputAssembler); - } -} - -void Q3DSDistanceFieldRenderer::AddSystemFontDirectory(const char8_t *dir) -{ - QString systemDir(dir); - m_systemDirs += systemDir; - m_fontDatabase.registerFonts({ systemDir }); -} - -void Q3DSDistanceFieldRenderer::AddProjectFontDirectory(const char8_t *dir) -{ - QString projectDir(dir); - m_projectDirs += projectDir; - m_fontDatabase.registerFonts({ projectDir }); -} - -void Q3DSDistanceFieldRenderer::ClearProjectFontDirectories() -{ - m_fontDatabase.unregisterFonts(m_projectDirs); - m_projectDirs.clear(); -} - -ITextRenderer &Q3DSDistanceFieldRenderer::GetTextRenderer(NVRenderContext &) -{ - return *this; -} - -void Q3DSDistanceFieldRenderer::EndFrame() -{ - // Remove meshes for glyphs that weren't rendered last frame - NVAllocatorCallback &alloc = m_context->GetAllocator(); - - QHash<size_t, Q3DSDistanceFieldMesh>::const_iterator it = m_meshCache.constBegin(); - while (it != m_meshCache.constEnd()) { - const size_t glyphHash = it.key(); - const Q3DSDistanceFieldMesh &mesh = it.value(); - if (!m_renderedGlyphs.contains(glyphHash)) { - NVDelete(alloc, mesh.vertexBuffer); - NVDelete(alloc, mesh.indexBuffer); - NVDelete(alloc, mesh.inputAssembler); - m_meshCache.erase(it++); - } else { - it++; - } - } - m_renderedGlyphs.clear(); -} - -QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo> -Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo) -{ - if (textInfo.m_BoundingBox.x < 0 || textInfo.m_BoundingBox.y < 0) - return QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>(); - - QVector2D boundingBox = QVector2D(textInfo.m_BoundingBox.x, textInfo.m_BoundingBox.y); - const float halfWidth = boundingBox.x() / 2.0f; - const float halfHeight = boundingBox.y() / 2.0f; - bool hasValidBoundingBox = boundingBox.x() > 0 || boundingBox.y() > 0; - - QRawFont font = m_fontDatabase.findFont(textInfo.m_Font.c_str()); - qreal scaleFactor = font.pixelSize() / qreal(textInfo.m_FontSize); - - const qreal maximumWidth = boundingBox.isNull() ? qreal(0x01000000) - : qreal(boundingBox.x()) * scaleFactor; - const qreal maximumHeight = boundingBox.isNull() ? qreal(0x01000000) - : qreal(boundingBox.y()) * scaleFactor; - - QTextLayout layout; - QTextOption option = layout.textOption(); - - QTextOption::WrapMode wrapMode; - switch (textInfo.m_WordWrap) { - case TextWordWrap::Clip: - wrapMode = QTextOption::ManualWrap; - break; - case TextWordWrap::WrapWord: - wrapMode = QTextOption::WrapAtWordBoundaryOrAnywhere; - break; - case TextWordWrap::WrapAnywhere: - wrapMode = QTextOption::WrapAnywhere; - break; - case TextWordWrap::Unknown: - wrapMode = QTextOption::ManualWrap; - Q_ASSERT(0); - }; - option.setWrapMode(wrapMode); - option.setUseDesignMetrics(true); - - layout.setTextOption(option); - layout.setRawFont(font); - - QString text = textInfo.m_Text.c_str(); - text.replace(QLatin1Char('\n'), QChar::LineSeparator); - - qreal width; - qreal height; - bool needsElide; - do { - needsElide = false; - - layout.clearLayout(); - - qreal leading = qreal(textInfo.m_Leading) * scaleFactor; - width = 0.0; - height = -leading; - - QVector<QTextLayout::FormatRange> formatRanges; - - QTextLayout::FormatRange formatRange; - formatRange.start = 0; - formatRange.length = text.length(); - formatRange.format.setFontLetterSpacingType(QFont::AbsoluteSpacing); - formatRange.format.setFontLetterSpacing(qreal(textInfo.m_Tracking) * scaleFactor); - formatRanges.append(formatRange); - layout.setFormats(formatRanges); - - layout.setText(text); - layout.beginLayout(); - - QTextLine previousLine; - forever { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - - line.setLineWidth(maximumWidth); - height += leading; - height = qCeil(height); - - qreal textWidth = line.naturalTextWidth(); - line.setPosition(QPointF(0.0, height)); - - width = qMin(maximumWidth, qMax(width, textWidth)); - height += layout.engine()->lines[line.lineNumber()].height().toReal(); - - // Fast path for right elide - if (textInfo.m_Elide == TextElide::ElideRight - && previousLine.isValid() - && height > maximumHeight) { - break; - } - - previousLine = line; - } - layout.endLayout(); - - if (textInfo.m_Elide != TextElide::ElideNone && height > maximumHeight) { - needsElide = true; - - QString elidedText; - switch (textInfo.m_Elide) { - case TextElide::ElideRight: - if (previousLine.textStart() > 0) - elidedText = text.left(previousLine.textStart()); - - elidedText += layout.engine()->elidedText( - Qt::ElideRight, QFixed::fromReal(width), 0, previousLine.textStart(), - text.length() - previousLine.textStart()); - break; - case TextElide::ElideLeft: - { - height = 0.0; - previousLine = QTextLine(); - for (int i = layout.lineCount() - 1; i >= 0; --i) { - qreal lineHeight = layout.lineAt(i).height(); - if (i < layout.lineCount() - 1 && height + lineHeight > maximumHeight) - break; - height += lineHeight; - previousLine = layout.lineAt(i); - } - - Q_ASSERT(previousLine.isValid()); - elidedText += layout.engine()->elidedText( - Qt::ElideLeft, QFixed::fromReal(width), 0, 0, - previousLine.textStart() + previousLine.textLength()); - - int nextPosition = (previousLine.textStart() + previousLine.textLength()); - if (nextPosition < text.length()) - elidedText += text.mid(nextPosition); - break; - } - case TextElide::ElideMiddle: - { - height = 0.0; - QTextLine lastLineBefore; - QTextLine firstLineAfter; - for (int i = 0; i < (layout.lineCount() / 2) + (layout.lineCount() % 2); ++i) { - qreal lineHeight = 3 * layout.lineAt(i).height(); - if (height + lineHeight > maximumHeight) - break; - height += lineHeight; - - lastLineBefore = layout.lineAt(i); - firstLineAfter = layout.lineAt(layout.lineCount() - i - 1); - } - - int nextPosition = 0; - if (lastLineBefore.isValid()) { - elidedText += text.left(lastLineBefore.textStart() - + lastLineBefore.textLength()); - nextPosition = lastLineBefore.textStart() + lastLineBefore.textLength(); - } - - QString suffix; - int length = text.length() - nextPosition; - if (firstLineAfter.isValid()) { - length = firstLineAfter.textStart() - nextPosition; - suffix = text.mid(firstLineAfter.textStart()); - } - - elidedText += layout.engine()->elidedText( - Qt::ElideMiddle, QFixed::fromReal(width), 0, nextPosition, length); - - elidedText += suffix; - break; - } - case TextElide::ElideNone: - Q_UNREACHABLE(); - }; - - // Failsafe - if (elidedText.isEmpty() || elidedText == text) - needsElide = false; - else - text = elidedText; - } - } while (needsElide); - - QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo> glyphsPerTexture; - - float originY = float(height) / 2.0f; - if (textInfo.m_VerticalAlignment == TextVerticalAlignment::Bottom) - originY = float(height); - else if (textInfo.m_VerticalAlignment == TextVerticalAlignment::Top) - originY = 0.0; - - float originX = float(width) / 2.0f; - if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Right) - originX = float(width); - else if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Left) - originX = 0.0; - - float offsetY = -originY; - - QT3DSVec3 minimum(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), 0); - QT3DSVec3 maximum(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), 0); - - // To match the original behavior of the sources, we don't actually align to - // the bounding box. This is only used for word wrapping and elide. Keeping the - // code here in case this was a mistake or we for some other reason want to change - // it. -#if 0 - // If there is no bounding box, then alignmentHeight == height, so we skip it - if (!boundingBox.isNull() && text3DS->verticalAlignment() == Q3DSTextNode::Bottom) - offsetY += float(maximumHeight - height); - else if (!boundingBox.isNull() && text3DS->verticalAlignment() == Q3DSTextNode::Middle) - offsetY += float(maximumHeight / 2.0 - height / 2.0); - float alignmentWidth = boundingBox.isNull() ? float(width) : float(maximumWidth); -#else - float alignmentWidth = float(width); -#endif - - for (int j = 0; j < layout.lineCount(); ++j) { - QTextLine line = layout.lineAt(j); - - float offsetX = -originX; - if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Right) - offsetX += alignmentWidth - float(line.naturalTextWidth()); - else if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Center) - offsetX += alignmentWidth / 2.0f - float(line.naturalTextWidth()) / 2.0f; - - const QList<QGlyphRun> glyphRuns = line.glyphRuns(); - for (const QGlyphRun &glyphRun : glyphRuns) { - const QVector<quint32> glyphIndexes = glyphRun.glyphIndexes(); - const QVector<QPointF> glyphPositions = glyphRun.positions(); - - Q3DSDistanceFieldGlyphCache *cache = m_glyphCacheManager.glyphCache( - glyphRun.rawFont()); - cache->populate(glyphRun.glyphIndexes()); - cache->processPendingGlyphs(); - - qreal fontPixelSize = glyphRun.rawFont().pixelSize(); - - qreal shadowOffsetX = qreal(cache->fontSize()) - * qreal(textInfo.m_DropShadowOffsetX) / 1000.0; - qreal shadowOffsetY = qreal(cache->fontSize()) - * qreal(textInfo.m_DropShadowOffsetY) / 1000.0; - - qreal maxTexMargin = cache->distanceFieldRadius(); - qreal fontScale = cache->fontScale(fontPixelSize); - qreal margin = 2; - qreal texMargin = margin / fontScale; - if (texMargin > maxTexMargin) { - texMargin = maxTexMargin; - margin = maxTexMargin * fontScale; - } - - for (int i = 0; i < glyphIndexes.size(); ++i) { - quint32 glyphIndex = glyphIndexes.at(i); - QPointF position = glyphPositions.at(i); - - QSGDistanceFieldGlyphCache::TexCoord c = cache->glyphTexCoord(glyphIndex); - if (c.isNull()) - continue; - - QSGDistanceFieldGlyphCache::Metrics metrics = cache->glyphMetrics(glyphIndex, - fontPixelSize); - if (metrics.isNull()) - continue; - - metrics.width += margin * 2; - metrics.height += margin * 2; - metrics.baselineX -= margin; - metrics.baselineY += margin; - c.xMargin -= texMargin; - c.yMargin -= texMargin; - c.width += texMargin * 2; - c.height += texMargin * 2; - - float cx1 = float(position.x() + metrics.baselineX) + offsetX; - float cx2 = cx1 + float(metrics.width); - float cy1 = float(position.y() - metrics.baselineY) + offsetY; - float cy2 = cy1 + float(metrics.height); - - cx1 /= float(scaleFactor); - cy1 /= float(scaleFactor); - cx2 /= float(scaleFactor); - cy2 /= float(scaleFactor); - - if (textInfo.m_DropShadow) { - if (shadowOffsetX < 0.0) - cx1 += float(shadowOffsetX * fontScale); - else - cx2 += float(shadowOffsetX * fontScale); - - if (shadowOffsetY < 0.0) - cy1 += float(shadowOffsetY * fontScale); - else - cy2 += float(shadowOffsetY * fontScale); - } - - float x1Clip = 1.0f; - float x2Clip = 1.0f; - float y1Clip = 1.0f; - float y2Clip = 1.0f; - - if (hasValidBoundingBox) { - if ((cx1 < -halfWidth && cx2 < -halfWidth) - || (cx1 > halfWidth && cx2 > halfWidth) - || (cy1 < -halfHeight && cy2 < -halfHeight) - || (cy1 > halfHeight && cy2 > halfHeight)) { - continue; - } - - float xDiff = qAbs(cx1 - cx2); - float yDiff = qAbs(cy1 - cy2); - - if (cx1 < -halfWidth) { - x1Clip = 1.0f - qAbs(cx1 - (-halfWidth)) / xDiff; - cx1 = -halfWidth; - } - - if (cx2 > halfWidth) { - x2Clip = 1.0f - qAbs(cx2 - halfWidth) / xDiff; - cx2 = halfWidth; - } - - if (cy1 < -halfHeight) { - y1Clip = 1.0f - qAbs(cy1 - (-halfHeight)) / yDiff; - cy1 = -halfHeight; - } - - if (cy2 > halfHeight) { - y2Clip = 1.0f - qAbs(cy2 - halfHeight) / yDiff; - cy2 = halfHeight; - } - } - - cy1 = -cy1; - cy2 = -cy2; - - if (cx1 < minimum.x) - minimum.x = cx1; - else if (cx1 > maximum.x) - maximum.x = cx1; - - if (cx2 < minimum.x) - minimum.x = cx2; - else if (cx2 > maximum.x) - maximum.x = cx2; - - if (cy1 < minimum.y) - minimum.y = cy1; - else if (cy1 > maximum.y) - maximum.y = cy1; - - if (cy2 < minimum.y) - minimum.y = cy2; - else if (cy2 > maximum.y) - maximum.y = cy2; - - if (hasValidBoundingBox) { - if (maximum.x < halfWidth) - maximum.x = halfWidth; - if (minimum.x > -halfWidth) - minimum.x = -halfWidth; - if (maximum.y < halfHeight) - maximum.y = halfHeight; - if (minimum.y > -halfHeight) - minimum.y = -halfHeight; - } - - float tx1 = float(c.x + c.xMargin); - float tx2 = tx1 + float(c.width); - float ty1 = float(c.y + c.yMargin); - float ty2 = ty1 + float(c.height); - - // Preserve original bounds of glyphs - float ttx1 = tx1; - float tty1 = ty1; - float ttx2 = tx2; - float tty2 = ty2; - - if (textInfo.m_DropShadow) { - if (shadowOffsetX < 0.0) - tx1 += float(c.width * shadowOffsetX * fontScale) / float(metrics.width); - else - tx2 += float(c.width * shadowOffsetX * fontScale) / float(metrics.width); - - if (shadowOffsetY < 0.0) - ty1 += float(c.height * shadowOffsetY * fontScale) / float(metrics.height); - else - ty2 += float(c.height * shadowOffsetY * fontScale) / float(metrics.height); - } - - if (hasValidBoundingBox) { - float tx1Orig = tx1; - float tx2Orig = tx2; - float ty1Orig = ty1; - float ty2Orig = ty2; - - float xDiff = qAbs(tx1 - tx2); - tx1 = tx2Orig - xDiff * x1Clip; - tx2 = tx1Orig + xDiff * x2Clip; - - float yDiff = qAbs(ty1 - ty2); - ty1 = ty2Orig - yDiff * y1Clip; - ty2 = ty1Orig + yDiff * y2Clip; - } - - const QSGDistanceFieldGlyphCache::Texture *texture - = cache->glyphTexture(glyphIndex); - if (texture->textureId == 0) { - qWarning() << "Empty texture for glyph" << glyphIndex; - continue; - } - - Q3DSDistanceFieldGlyphCache::TextureInfo *textureInfo = cache->textureInfoById( - texture->textureId); - - GlyphInfo &glyphInfo = glyphsPerTexture[textureInfo]; - glyphInfo.fontScale = float(fontScale); - glyphInfo.shadowOffsetX = float(shadowOffsetX); - glyphInfo.shadowOffsetY = float(shadowOffsetY); - glyphInfo.bounds = NVBounds3(minimum, maximum); - - QVector<float> &vertexes = glyphInfo.vertexes; - vertexes.reserve(vertexes.size() + 20 + (textInfo.m_DropShadow ? 16 : 0)); - - vertexes.append(cx1); - vertexes.append(cy1); - vertexes.append(0.0); - vertexes.append(tx1); - vertexes.append(ty1); - - if (textInfo.m_DropShadow) { - vertexes.append(ttx1); - vertexes.append(tty1); - vertexes.append(ttx2); - vertexes.append(tty2); - } - - vertexes.append(cx2); - vertexes.append(cy1); - vertexes.append(0.0); - vertexes.append(tx2); - vertexes.append(ty1); - - if (textInfo.m_DropShadow) { - vertexes.append(ttx1); - vertexes.append(tty1); - vertexes.append(ttx2); - vertexes.append(tty2); - } - - vertexes.append(cx2); - vertexes.append(cy2); - vertexes.append(0.0); - vertexes.append(tx2); - vertexes.append(ty2); - - if (textInfo.m_DropShadow) { - vertexes.append(ttx1); - vertexes.append(tty1); - vertexes.append(ttx2); - vertexes.append(tty2); - } - - vertexes.append(cx1); - vertexes.append(cy2); - vertexes.append(0.0); - vertexes.append(tx1); - vertexes.append(ty2); - - if (textInfo.m_DropShadow) { - vertexes.append(ttx1); - vertexes.append(tty1); - vertexes.append(ttx2); - vertexes.append(tty2); - } - } - } - } - - return glyphsPerTexture; -} - -template <typename T> -static QVector<T> fillIndexBuffer(uint quadCount) -{ - QVector<T> indexes; - - const uint triangleCount = 2 * quadCount; - indexes.resize(3 * int(triangleCount)); - - Q_ASSERT(indexes.size() % 6 == 0); - - for (uint i = 0; i < quadCount; i ++) { - indexes[int(i * 6 + 0)] = T(i * 4 + 0); - indexes[int(i * 6 + 1)] = T(i * 4 + 3); - indexes[int(i * 6 + 2)] = T(i * 4 + 1); - - indexes[int(i * 6 + 3)] = T(i * 4 + 1); - indexes[int(i * 6 + 4)] = T(i * 4 + 3); - indexes[int(i * 6 + 5)] = T(i * 4 + 2); - } - - return indexes; -} - -void Q3DSDistanceFieldRenderer::buildShaders() -{ - IShaderProgramGenerator &gen = m_context->GetShaderProgramGenerator(); - gen.BeginProgram(); - IShaderStageGenerator &vertexGenerator(*gen.GetStage(ShaderGeneratorStages::Vertex)); - IShaderStageGenerator &fragmentGenerator(*gen.GetStage(ShaderGeneratorStages::Fragment)); - - if (m_context->GetRenderContext().GetRenderContextType() == NVRenderContextValues::GLES2) { - vertexGenerator.AddInclude("distancefieldtext.vert"); - fragmentGenerator.AddInclude("distancefieldtext.frag"); - } else { - vertexGenerator.AddInclude("distancefieldtext_core.vert"); - fragmentGenerator.AddInclude("distancefieldtext_core.frag"); - } - - m_shader.program = gen.CompileGeneratedShader("distancefieldtext", - SShaderCacheProgramFlags(), - TShaderFeatureSet(), false); - - if (m_shader.program) { - m_shader.mvp = NVRenderCachedShaderProperty<QT3DSMat44>( - "mvp", *m_shader.program); - m_shader.textureWidth = NVRenderCachedShaderProperty<QT3DSI32>( - "textureWidth", *m_shader.program); - m_shader.textureHeight = NVRenderCachedShaderProperty<QT3DSI32>( - "textureHeight", *m_shader.program); - m_shader.fontScale = NVRenderCachedShaderProperty<QT3DSF32>( - "fontScale", *m_shader.program); - m_shader.texture = NVRenderCachedShaderProperty<NVRenderTexture2D *>( - "_qt_texture", *m_shader.program); - m_shader.color = NVRenderCachedShaderProperty<QT3DSVec4>( - "color", *m_shader.program); - } - - gen.BeginProgram(); - vertexGenerator = *gen.GetStage(ShaderGeneratorStages::Vertex); - fragmentGenerator = *gen.GetStage(ShaderGeneratorStages::Fragment); - - if (m_context->GetRenderContext().GetRenderContextType() == NVRenderContextValues::GLES2) { - vertexGenerator.AddInclude("distancefieldtext_dropshadow.vert"); - fragmentGenerator.AddInclude("distancefieldtext_dropshadow.frag"); - } else { - vertexGenerator.AddInclude("distancefieldtext_dropshadow_core.vert"); - fragmentGenerator.AddInclude("distancefieldtext_dropshadow_core.frag"); - } - - m_dropShadowShader.program = gen.CompileGeneratedShader("distancefieldtext_dropshadow", - SShaderCacheProgramFlags(), - TShaderFeatureSet(), false); - - if (m_dropShadowShader.program) { - m_dropShadowShader.mvp = NVRenderCachedShaderProperty<QT3DSMat44>( - "mvp", *m_dropShadowShader.program); - m_dropShadowShader.textureWidth = NVRenderCachedShaderProperty<QT3DSI32>( - "textureWidth", *m_dropShadowShader.program); - m_dropShadowShader.textureHeight = NVRenderCachedShaderProperty<QT3DSI32>( - "textureHeight", *m_dropShadowShader.program); - m_dropShadowShader.fontScale = NVRenderCachedShaderProperty<QT3DSF32>( - "fontScale", *m_dropShadowShader.program); - m_dropShadowShader.shadowOffset = NVRenderCachedShaderProperty<QT3DSVec2>( - "shadowOffset", *m_dropShadowShader.program); - m_dropShadowShader.texture = NVRenderCachedShaderProperty<NVRenderTexture2D *>( - "_qt_texture", *m_dropShadowShader.program); - m_dropShadowShader.color = NVRenderCachedShaderProperty<QT3DSVec4>( - "color", *m_dropShadowShader.program); - m_dropShadowShader.shadowColor = NVRenderCachedShaderProperty<QT3DSVec4>( - "shadowColor", *m_dropShadowShader.program); - } -} - -Q3DSDistanceFieldMesh Q3DSDistanceFieldRenderer::buildMesh(const GlyphInfo &glyphInfo, - bool shadow) -{ - static NVRenderVertexBufferEntry entries[] = { - NVRenderVertexBufferEntry("vCoord", NVRenderComponentTypes::QT3DSF32, 3), - NVRenderVertexBufferEntry("tCoord", NVRenderComponentTypes::QT3DSF32, 2, 3 * sizeof(float)) - }; - - static NVRenderVertexBufferEntry shadowEntries[] = { - NVRenderVertexBufferEntry("vCoord", NVRenderComponentTypes::QT3DSF32, 3), - NVRenderVertexBufferEntry("tCoord", NVRenderComponentTypes::QT3DSF32, 2, - 3 * sizeof(float)), - NVRenderVertexBufferEntry("textureBounds", NVRenderComponentTypes::QT3DSF32, 4, - 5 * sizeof(float)) - }; - - const uint floatsPerVertex = 3 + 2 + (shadow ? 4 : 0); - const uint stride = floatsPerVertex * sizeof(float); - const uint offset = 0; - - NVRenderContext &renderContext = m_context->GetRenderContext(); - QVector<float> vertexes = glyphInfo.vertexes; - - Q_ASSERT(uint(vertexes.size()) % floatsPerVertex == 0); - const uint vertexCount = uint(vertexes.size()) / floatsPerVertex; - - Q_ASSERT(vertexCount % 4 == 0); - const uint quadCount = vertexCount / 4; - - Q3DSDistanceFieldMesh mesh; - - mesh.attribLayout = renderContext.CreateAttributeLayout( - toConstDataRef(shadow ? shadowEntries : entries, shadow ? 3 : 2)); - mesh.vertexBuffer = renderContext.CreateVertexBuffer( - NVRenderBufferUsageType::Static, size_t(vertexes.size()) * sizeof(float), stride, - toU8DataRef(vertexes.begin(), QT3DSU32(vertexes.size()))); - - if (vertexCount <= 0xffff) { - QVector<QT3DSU16> indexes = fillIndexBuffer<QT3DSU16>(quadCount); - mesh.indexBuffer = renderContext.CreateIndexBuffer( - NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16, - size_t(indexes.size()) * sizeof(QT3DSU16), - toU8DataRef(indexes.begin(), QT3DSU32(indexes.size()))); - } else { - QVector<QT3DSU32> indexes = fillIndexBuffer<QT3DSU32>(quadCount); - mesh.indexBuffer = renderContext.CreateIndexBuffer( - NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU32, - size_t(indexes.size()) * sizeof(QT3DSU32), - toU8DataRef(indexes.begin(), QT3DSU32(indexes.size()))); - } - - mesh.inputAssembler = renderContext.CreateInputAssembler( - mesh.attribLayout, toConstDataRef(&mesh.vertexBuffer, 1), mesh.indexBuffer, - toConstDataRef(&stride, 1), toConstDataRef(&offset, 1)); - - return mesh; -} - -void Q3DSDistanceFieldRenderer::renderMesh( - NVRenderInputAssembler *inputAssembler, NVRenderTexture2D *texture, const QT3DSMat44 &mvp, - QT3DSI32 textureWidth, QT3DSI32 textureHeight, QT3DSF32 fontScale, QT3DSVec4 color) -{ - NVRenderContext &renderContext = m_context->GetRenderContext(); - renderContext.SetCullingEnabled(false); - - renderContext.SetBlendFunction(NVRenderBlendFunctionArgument( - NVRenderSrcBlendFunc::One, - NVRenderDstBlendFunc::OneMinusSrcAlpha, - NVRenderSrcBlendFunc::One, - NVRenderDstBlendFunc::OneMinusSrcAlpha)); - renderContext.SetBlendEquation(NVRenderBlendEquationArgument( - NVRenderBlendEquation::Add, NVRenderBlendEquation::Add)); - - renderContext.SetActiveShader(m_shader.program); - m_shader.mvp.Set(mvp); - m_shader.textureWidth.Set(textureWidth); - m_shader.textureHeight.Set(textureHeight); - m_shader.fontScale.Set(fontScale); - m_shader.texture.Set(texture); - m_shader.color.Set(color); - - renderContext.SetInputAssembler(inputAssembler); - renderContext.Draw(NVRenderDrawMode::Triangles, inputAssembler->GetIndexCount(), 0); -} - -void Q3DSDistanceFieldRenderer::renderMeshWithDropShadow( - NVRenderInputAssembler *inputAssembler, NVRenderTexture2D *texture, const QT3DSMat44 &mvp, - QT3DSI32 textureWidth, QT3DSI32 textureHeight, QT3DSF32 fontScale, QT3DSVec2 shadowOffset, - QT3DSVec4 color, QT3DSVec4 shadowColor) -{ - NVRenderContext &renderContext = m_context->GetRenderContext(); - renderContext.SetCullingEnabled(false); - - renderContext.SetBlendFunction(NVRenderBlendFunctionArgument( - NVRenderSrcBlendFunc::One, - NVRenderDstBlendFunc::OneMinusSrcAlpha, - NVRenderSrcBlendFunc::One, - NVRenderDstBlendFunc::OneMinusSrcAlpha)); - renderContext.SetBlendEquation(NVRenderBlendEquationArgument( - NVRenderBlendEquation::Add, NVRenderBlendEquation::Add)); - - renderContext.SetActiveShader(m_dropShadowShader.program); - m_dropShadowShader.mvp.Set(mvp); - m_dropShadowShader.textureWidth.Set(textureWidth); - m_dropShadowShader.textureHeight.Set(textureHeight); - m_dropShadowShader.fontScale.Set(fontScale); - m_dropShadowShader.shadowOffset.Set(shadowOffset); - m_dropShadowShader.texture.Set(texture); - m_dropShadowShader.color.Set(color); - m_dropShadowShader.shadowColor.Set(shadowColor); - - renderContext.SetInputAssembler(inputAssembler); - renderContext.Draw(NVRenderDrawMode::Triangles, inputAssembler->GetIndexCount(), 0); -} - -namespace std { -template<class T> -struct hash<QVector<T>> -{ - size_t operator()(const QVector<T> &s) const - { - return qHash(s); - } -}; - -template<> -struct hash<TextHorizontalAlignment::Enum> -{ - size_t operator()(const TextHorizontalAlignment::Enum& s) const - { - return qHash(s); - } -}; - -template<> -struct hash<TextVerticalAlignment::Enum> -{ - size_t operator()(const TextVerticalAlignment::Enum& s) const - { - return qHash(s); - } -}; - -template<> -struct hash<TextElide::Enum> -{ - size_t operator()(const TextElide::Enum& s) const - { - return qHash(s); - } -}; - -template<> -struct hash<TextWordWrap::Enum> -{ - size_t operator()(const TextWordWrap::Enum& s) const - { - return qHash(s); - } -}; -} - -// Copied from boost -template <class T> -inline void hashCombine(std::size_t &seed, const T &v) -{ - std::hash<T> hasher; - seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); -} - -size_t getTextHashValue(const SText &text) -{ - size_t hashValue = 0; - hashCombine(hashValue, text.m_TextColor.x); - hashCombine(hashValue, text.m_TextColor.y); - hashCombine(hashValue, text.m_TextColor.z); - hashCombine(hashValue, text.m_TextColor.w); - hashCombine(hashValue, std::string(text.m_Font.c_str())); - hashCombine(hashValue, std::string(text.m_Text.c_str())); - hashCombine(hashValue, text.m_Elide); - hashCombine(hashValue, text.m_Leading); - hashCombine(hashValue, text.m_FontSize); - hashCombine(hashValue, text.m_Tracking); - hashCombine(hashValue, text.m_WordWrap); - hashCombine(hashValue, text.m_DropShadow); - hashCombine(hashValue, text.m_BoundingBox.x); - hashCombine(hashValue, text.m_BoundingBox.y); - hashCombine(hashValue, text.m_DropShadowOffsetX); - hashCombine(hashValue, text.m_DropShadowOffsetY); - hashCombine(hashValue, text.m_DropShadowStrength); - hashCombine(hashValue, text.m_VerticalAlignment); - hashCombine(hashValue, text.m_HorizontalAlignment); - return hashValue; -} - -size_t getGlyphHashValue(const GlyphInfo &glyph) -{ - size_t hashValue = 0; - hashCombine(hashValue, glyph.vertexes); - hashCombine(hashValue, glyph.glyphIndexes); - hashCombine(hashValue, glyph.fontScale); - hashCombine(hashValue, glyph.shadowOffsetX); - hashCombine(hashValue, glyph.shadowOffsetY); - return hashValue; -} - -void Q3DSDistanceFieldRenderer::renderText(SText &text, const QT3DSMat44 &mvp) -{ - if (!m_shader.program) - buildShaders(); - - float alpha = text.m_GlobalOpacity * text.m_TextColor.w; - QT3DSVec4 textColor = QT3DSVec4(text.m_TextColor.getXYZ() * alpha, alpha); - int shadowRgb = int(100 - int(text.m_DropShadowStrength)); - QT3DSVec4 shadowColor(shadowRgb * 0.01f * alpha, shadowRgb * 0.01f * alpha, - shadowRgb * 0.01f * alpha, alpha); - - size_t textHashValue = getTextHashValue(text); - if (!m_glyphCache.contains(textHashValue)) - m_glyphCache[textHashValue] = buildGlyphsPerTexture(text); - - QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo> &glyphsPerTexture - = m_glyphCache[textHashValue]; - - QT3DSVec3 minimum(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), 0); - QT3DSVec3 maximum(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), 0); - - QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>::const_iterator it; - for (it = glyphsPerTexture.constBegin(); it != glyphsPerTexture.constEnd(); ++it) { - const GlyphInfo &glyphInfo = it.value(); - - if (glyphInfo.bounds.minimum.x < minimum.x) - minimum.x = glyphInfo.bounds.minimum.x; - if (glyphInfo.bounds.minimum.y < minimum.y) - minimum.y = glyphInfo.bounds.minimum.y; - if (glyphInfo.bounds.minimum.z < minimum.z) - minimum.z = glyphInfo.bounds.minimum.z; - - if (glyphInfo.bounds.maximum.x > maximum.x) - maximum.x = glyphInfo.bounds.maximum.x; - if (glyphInfo.bounds.maximum.y > maximum.y) - maximum.y = glyphInfo.bounds.maximum.y; - if (glyphInfo.bounds.maximum.z > maximum.z) - maximum.z = glyphInfo.bounds.maximum.z; - - size_t glyphHashValue = getGlyphHashValue(glyphInfo); - - if (!m_meshCache.contains(glyphHashValue)) - m_meshCache[glyphHashValue] = buildMesh(glyphInfo, text.m_DropShadow); - - Q3DSDistanceFieldMesh &mesh = m_meshCache[glyphHashValue]; - - STextureDetails textureDetails = it.key()->texture->GetTextureDetails(); - - if (text.m_DropShadow) { - renderMeshWithDropShadow(mesh.inputAssembler, it.key()->texture, mvp, - int(textureDetails.m_Width), int(textureDetails.m_Height), - glyphInfo.fontScale * float(m_pixelRatio), - QT3DSVec2(glyphInfo.shadowOffsetX, glyphInfo.shadowOffsetY), - textColor, shadowColor); - } else { - renderMesh(mesh.inputAssembler, it.key()->texture, mvp, - int(textureDetails.m_Width), int(textureDetails.m_Height), - glyphInfo.fontScale * float(m_pixelRatio), textColor); - } - - m_renderedGlyphs += glyphHashValue; - } - - text.m_Bounds = NVBounds3(minimum, maximum); -} - -void Q3DSDistanceFieldRenderer::renderTextDepth(SText &text, const QT3DSMat44 &mvp) -{ - // TODO: Create a depth pass shader for distance field text - renderText(text, mvp); -} - -void Q3DSDistanceFieldRenderer::setContext(IQt3DSRenderContext &context) -{ - m_context = &context; - m_glyphCacheManager.setContext(context); - buildShaders(); -} - -ITextRendererCore &ITextRendererCore::createDistanceFieldRenderer(NVFoundationBase &fnd) -{ - return *QT3DS_NEW(fnd.getAllocator(), Q3DSDistanceFieldRenderer)(fnd); -} - -// Unused methods: - -void Q3DSDistanceFieldRenderer::PreloadFonts() -{ - Q_ASSERT(false); -} - -void Q3DSDistanceFieldRenderer::BeginPreloadFonts(IThreadPool &, IPerfTimer &) -{ - Q_ASSERT(false); -} - -void Q3DSDistanceFieldRenderer::EndPreloadFonts() -{ - Q_ASSERT(false); -} - -void Q3DSDistanceFieldRenderer::ReloadFonts() -{ - Q_ASSERT(false); -} - -NVConstDataRef<SRendererFontEntry> Q3DSDistanceFieldRenderer::GetProjectFontList() -{ - Q_ASSERT(false); - return NVConstDataRef<SRendererFontEntry>(); -} - -Option<CRegisteredString> Q3DSDistanceFieldRenderer::GetFontNameForFont(CRegisteredString) -{ - Q_ASSERT(false); - return Option<CRegisteredString>(); -} - -Option<CRegisteredString> Q3DSDistanceFieldRenderer::GetFontNameForFont(const char8_t *) -{ - Q_ASSERT(false); - return Option<CRegisteredString>(); -} - -STextDimensions Q3DSDistanceFieldRenderer::MeasureText(const STextRenderInfo &, QT3DSF32, - const char8_t *) -{ - Q_ASSERT(false); - return STextDimensions(); -} - -STextTextureDetails Q3DSDistanceFieldRenderer::RenderText(const STextRenderInfo &, - NVRenderTexture2D &) -{ - Q_ASSERT(false); - return STextTextureDetails(); -} - -STextTextureDetails Q3DSDistanceFieldRenderer::RenderText( - const STextRenderInfo &, NVRenderPathFontItem &, NVRenderPathFontSpecification &) -{ - Q_ASSERT(false); - return STextTextureDetails(); -} - -SRenderTextureAtlasDetails Q3DSDistanceFieldRenderer::RenderText(const STextRenderInfo &) -{ - Q_ASSERT(false); - return SRenderTextureAtlasDetails(); -} - -void Q3DSDistanceFieldRenderer::BeginFrame() -{ - Q_ASSERT(false); -} - -QT3DSI32 Q3DSDistanceFieldRenderer::CreateTextureAtlas() -{ - Q_ASSERT(false); - return 0; -} - -STextTextureAtlasEntryDetails Q3DSDistanceFieldRenderer::RenderAtlasEntry(QT3DSU32, - NVRenderTexture2D &) -{ - Q_ASSERT(false); - return STextTextureAtlasEntryDetails(); -} - -bool Q3DSDistanceFieldRenderer::checkAndBuildGlyphs(SText &text) -{ - auto hashVal = getTextHashValue(text); - if (!m_glyphCache.contains(hashVal)) { - m_glyphCache[hashVal] = buildGlyphsPerTexture(text); - return true; - } - - return false; -} -#endif |