diff options
-rw-r--r-- | src/runtime/q3dsdistancefieldmaterialgenerator.cpp | 14 | ||||
-rw-r--r-- | src/runtime/q3dsdistancefieldmaterialgenerator_p.h | 3 | ||||
-rw-r--r-- | src/runtime/q3dsres.qrc | 4 | ||||
-rw-r--r-- | src/runtime/q3dsscenemanager.cpp | 84 | ||||
-rw-r--r-- | src/runtime/q3dsscenemanager_p.h | 1 | ||||
-rw-r--r-- | src/runtime/q3dstextmesh.cpp | 36 | ||||
-rw-r--r-- | src/runtime/q3dstextmesh_p.h | 3 | ||||
-rw-r--r-- | src/runtime/shaders/distancefieldtext_dropshadow.frag | 29 | ||||
-rw-r--r-- | src/runtime/shaders/distancefieldtext_dropshadow.vert | 75 | ||||
-rw-r--r-- | src/runtime/shaders/distancefieldtext_dropshadow_core.frag | 34 | ||||
-rw-r--r-- | src/runtime/shaders/distancefieldtext_dropshadow_core.vert | 55 |
11 files changed, 310 insertions, 28 deletions
diff --git a/src/runtime/q3dsdistancefieldmaterialgenerator.cpp b/src/runtime/q3dsdistancefieldmaterialgenerator.cpp index 8dacef1..abb1b4d 100644 --- a/src/runtime/q3dsdistancefieldmaterialgenerator.cpp +++ b/src/runtime/q3dsdistancefieldmaterialgenerator.cpp @@ -42,7 +42,8 @@ QT_BEGIN_NAMESPACE -Qt3DRender::QMaterial *Q3DSDistanceFieldMaterialGenerator::generateMaterial(const QVector<Qt3DRender::QParameter *> ¶ms) +Qt3DRender::QMaterial *Q3DSDistanceFieldMaterialGenerator::generateMaterial(const QVector<Qt3DRender::QParameter *> ¶ms, + bool dropShadow) { Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial; Qt3DRender::QEffect *effect = new Qt3DRender::QEffect; @@ -53,13 +54,10 @@ Qt3DRender::QMaterial *Q3DSDistanceFieldMaterialGenerator::generateMaterial(cons Q3DSDefaultMaterialGenerator::addDefaultApiFilter(technique, &isGLES); Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram; - if (isGLES) { - shaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QLatin1String("qrc:/q3ds/shaders/distancefieldtext.vert")))); - shaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QLatin1String("qrc:/q3ds/shaders/distancefieldtext.frag")))); - } else { - shaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QLatin1String("qrc:/q3ds/shaders/distancefieldtext_core.vert")))); - shaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QLatin1String("qrc:/q3ds/shaders/distancefieldtext_core.frag")))); - } + + QString name = QStringLiteral("distancefieldtext") + (dropShadow ? QStringLiteral("_dropshadow") : QString()) + (!isGLES ? QStringLiteral("_core") : QString()); + shaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/q3ds/shaders/") + name + QStringLiteral(".vert")))); + shaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/q3ds/shaders/") + name + QStringLiteral(".frag")))); Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass; Qt3DRender::QFilterKey *transFilterKey = new Qt3DRender::QFilterKey; diff --git a/src/runtime/q3dsdistancefieldmaterialgenerator_p.h b/src/runtime/q3dsdistancefieldmaterialgenerator_p.h index bb85c73..07ef527 100644 --- a/src/runtime/q3dsdistancefieldmaterialgenerator_p.h +++ b/src/runtime/q3dsdistancefieldmaterialgenerator_p.h @@ -55,7 +55,8 @@ class QMaterial; class Q3DSDistanceFieldMaterialGenerator { public: - Qt3DRender::QMaterial *generateMaterial(const QVector<Qt3DRender::QParameter *> ¶ms); + Qt3DRender::QMaterial *generateMaterial(const QVector<Qt3DRender::QParameter *> ¶ms, + bool dropShadow); }; QT_END_NAMESPACE diff --git a/src/runtime/q3dsres.qrc b/src/runtime/q3dsres.qrc index e70f636..0c20267 100644 --- a/src/runtime/q3dsres.qrc +++ b/src/runtime/q3dsres.qrc @@ -132,5 +132,9 @@ <file alias="res/effectlib/gles2/shadowMapping.glsllib">../../res/effectlib/gles2/shadowMapping.glsllib</file> <file alias="res/effectlib/gles2/SSAOCustomMaterial.glsllib">../../res/effectlib/gles2/SSAOCustomMaterial.glsllib</file> <file alias="res/effectlib/gles2/tangentSpaceNormalTexture.glsllib">../../res/effectlib/gles2/tangentSpaceNormalTexture.glsllib</file> + <file>shaders/distancefieldtext_dropshadow_core.vert</file> + <file>shaders/distancefieldtext_dropshadow_core.frag</file> + <file>shaders/distancefieldtext_dropshadow.frag</file> + <file>shaders/distancefieldtext_dropshadow.vert</file> </qresource> </RCC> diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index d6f909c..8dc7aa2 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -4761,10 +4761,9 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN } #if QT_VERSION >= QT_VERSION_CHECK(5,12,2) - static bool distanceFieldRendering = distanceFieldsEnabled(); + static bool shouldDistanceFieldRender = distanceFieldsEnabled(); - bool shouldDistanceFieldRender = distanceFieldRendering && !text3DS->shadow(); - if (data->entity != nullptr && shouldDistanceFieldRender != data->distanceFieldText) { + if (data->entity != nullptr && text3DS->shadow() != data->dropShadow) { for (int i = 0; i < data->glyphsReferencedInSubentity.size(); ++i) { QPair<Q3DSDistanceFieldGlyphCache *, QVector<quint32> > &glyphsReferenced = data->glyphsReferencedInSubentity[i]; if (glyphsReferenced.first != nullptr && !glyphsReferenced.second.isEmpty()) @@ -4791,6 +4790,7 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN #if QT_VERSION >= QT_VERSION_CHECK(5,12,2) if (shouldDistanceFieldRender) { data->distanceFieldText = true; + data->dropShadow = text3DS->shadow(); QVector2D boundingBox = text3DS->boundingBox(); QRawFont font = m_fontDatabase->findFont(text3DS->font()); @@ -4969,6 +4969,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN QVector<quint32> glyphIndexes; Q3DSDistanceFieldGlyphCache *cache; float fontScale; + float shadowOffsetX; + float shadowOffsetY; }; QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo> glyphsPerTexture; @@ -5021,6 +5023,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN cache->processPendingGlyphs(); qreal fontPixelSize = glyphRun.rawFont().pixelSize(); + float shadowOffsetX = float(fontPixelSize) * text3DS->shadowOffsetX() / 1000.0f; + float shadowOffsetY = float(fontPixelSize) * text3DS->shadowOffsetY() / 1000.0f; qreal maxTexMargin = cache->distanceFieldRadius(); qreal fontScale = cache->fontScale(fontPixelSize); qreal margin = 2; @@ -5056,11 +5060,24 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN float cy1 = float(position.y() - metrics.baselineY) + offsetY; float cy2 = cy1 + float(metrics.height); + if (text3DS->shadow()) { + cx2 += shadowOffsetX; + cy2 += shadowOffsetY; + } + 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); + float ttx2 = tx2; + float tty2 = ty2; + + if (text3DS->shadow()) { + tx2 += float(c.width) * shadowOffsetX / float(metrics.width); + ty2 += float(c.height) * shadowOffsetY / float(metrics.height); + } + const QSGDistanceFieldGlyphCache::Texture *texture = cache->glyphTexture(glyphIndex); if (texture->textureId == 0) { qWarning() << "Empty texture for glyph" << glyphIndex; @@ -5071,9 +5088,11 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN GlyphInfo &glyphInfo = glyphsPerTexture[textureInfo]; glyphInfo.fontScale = float(fontScale); + glyphInfo.shadowOffsetX = shadowOffsetX; + glyphInfo.shadowOffsetY = shadowOffsetY; QVector<float> &vertexes = glyphInfo.vertexes; - vertexes.reserve(vertexes.size() + 10); + vertexes.reserve(vertexes.size() + 20 + (text3DS->shadow() ? 16 : 0)); vertexes.append(cx1); vertexes.append(0.0); @@ -5081,23 +5100,51 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN vertexes.append(tx1); vertexes.append(ty1); + if (text3DS->shadow()) { + vertexes.append(tx1); + vertexes.append(ty1); + vertexes.append(ttx2); + vertexes.append(tty2); + } + vertexes.append(cx2); vertexes.append(0.0); vertexes.append(cy1); vertexes.append(tx2); vertexes.append(ty1); + if (text3DS->shadow()) { + vertexes.append(tx1); + vertexes.append(ty1); + vertexes.append(ttx2); + vertexes.append(tty2); + } + vertexes.append(cx2); vertexes.append(0.0); vertexes.append(cy2); vertexes.append(tx2); vertexes.append(ty2); + if (text3DS->shadow()) { + vertexes.append(tx1); + vertexes.append(ty1); + vertexes.append(ttx2); + vertexes.append(tty2); + } + vertexes.append(cx1); vertexes.append(0.0); vertexes.append(cy2); vertexes.append(tx1); vertexes.append(ty2); + + if (text3DS->shadow()) { + vertexes.append(tx1); + vertexes.append(ty1); + vertexes.append(ttx2); + vertexes.append(tty2); + } } } } @@ -5140,11 +5187,23 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN Qt3DRender::QParameter *fontScaleParam = new Qt3DRender::QParameter; fontScaleParam->setName(QLatin1String("fontScale")); - Qt3DRender::QMaterial *material = m_distanceFieldMaterialGenerator->generateMaterial({ colorParam, - textureParam, - fontScaleParam, - textureWidthParam, - textureHeightParam }); + QVector<Qt3DRender::QParameter *> params = { colorParam, + textureParam, + fontScaleParam, + textureWidthParam, + textureHeightParam }; + + if (text3DS->shadow()) { + Qt3DRender::QParameter *shadowColorParam = new Qt3DRender::QParameter; + shadowColorParam->setName(QLatin1String("shadowColor")); + params.append(shadowColorParam); + + Qt3DRender::QParameter *shadowOffsetParam = new Qt3DRender::QParameter; + shadowOffsetParam->setName(QLatin1String("shadowOffset")); + params.append(shadowOffsetParam); + } + + Qt3DRender::QMaterial *material = m_distanceFieldMaterialGenerator->generateMaterial(params, text3DS->shadow()); subentity->addComponent(material); subentities.append(subentity); } @@ -5152,6 +5211,7 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>::const_iterator it; int subentityIndex = 0; + int shadowRgb = int(2.55f * (100 - int(text3DS->shadowStrength()))); for (it = glyphsPerTexture.constBegin(); it != glyphsPerTexture.constEnd(); ++it) { const GlyphInfo &glyphInfo = it.value(); const QVector<float> &vertexes = glyphInfo.vertexes; @@ -5168,7 +5228,7 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN { Q3DSTextMesh *mesh = qobject_cast<Q3DSTextMesh *>(component); if (mesh != nullptr) - mesh->setVertexes(vertexes); + mesh->setVertexes(vertexes, text3DS->shadow()); } { @@ -5184,6 +5244,10 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN parameter->setValue(color * data->globalOpacity); data->colorParam.append(parameter); + } else if (parameter->name() == QLatin1String("shadowColor")) { + parameter->setValue(QColor(shadowRgb, shadowRgb, shadowRgb)); + } else if (parameter->name() == QLatin1String("shadowOffset")) { + parameter->setValue(QVector2D(glyphInfo.shadowOffsetX, glyphInfo.shadowOffsetY)); } else if (parameter->name() == QLatin1String("_qt_texture")) { parameter->setValue(QVariant::fromValue(it.key()->texture)); } else if (parameter->name() == QLatin1String("fontScale")) { diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h index d1a4461..5cdb806 100644 --- a/src/runtime/q3dsscenemanager_p.h +++ b/src/runtime/q3dsscenemanager_p.h @@ -456,6 +456,7 @@ class Q3DSTextAttached : public Q3DSNodeAttached { public: bool distanceFieldText = false; + bool dropShadow = false; Qt3DExtras::QPlaneMesh *mesh = nullptr; Qt3DRender::QParameter *opacityParam = nullptr; QVector<Qt3DRender::QParameter *> colorParam; diff --git a/src/runtime/q3dstextmesh.cpp b/src/runtime/q3dstextmesh.cpp index 13fc8dd..4290204 100644 --- a/src/runtime/q3dstextmesh.cpp +++ b/src/runtime/q3dstextmesh.cpp @@ -64,30 +64,34 @@ namespace { class Q3DSTextMeshGeometry : public Qt3DRender::QGeometry { public: - Q3DSTextMeshGeometry(const QVector<float> &vertexes, Qt3DCore::QNode *parent = nullptr); + Q3DSTextMeshGeometry(bool shadow, + const QVector<float> &vertexes, + Qt3DCore::QNode *parent = nullptr); private: Qt3DRender::QBuffer *m_vertexBuffer; Qt3DRender::QBuffer *m_indexBuffer; Qt3DRender::QAttribute *m_positionAttribute; Qt3DRender::QAttribute *m_textureCoordinateAttribute; Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QAttribute *m_textureBoundsAttribute; }; - Q3DSTextMeshGeometry::Q3DSTextMeshGeometry(const QVector<float> &vertexes, + Q3DSTextMeshGeometry::Q3DSTextMeshGeometry(bool shadow, + const QVector<float> &vertexes, Qt3DCore::QNode *parent) : Qt3DRender::QGeometry(parent) { - Q_ASSERT(vertexes.size() % 10 == 0); - m_vertexBuffer = new Qt3DRender::QBuffer(this); m_vertexBuffer->setUsage(Qt3DRender::QBuffer::StaticDraw); m_vertexBuffer->setAccessType(Qt3DRender::QBuffer::Read); m_vertexBuffer->setData(QByteArray(reinterpret_cast<const char *>(vertexes.constData()), int(vertexes.size() * sizeof(float)))); - const uint stride = (3 + 2) * sizeof(float); + const uint floatsPerVertex = shadow ? 3 + 2 + 4 : 3 + 2; + const uint stride = floatsPerVertex * sizeof(float); - const uint vertexCount = uint(vertexes.size() / 5); + Q_ASSERT(uint(vertexes.size()) % floatsPerVertex == 0); + const uint vertexCount = uint(vertexes.size()) / floatsPerVertex; Q_ASSERT(vertexCount % 4 == 0); const uint quadCount = vertexCount / 4; @@ -125,6 +129,20 @@ namespace { m_textureCoordinateAttribute->setByteOffset(3 * sizeof(float)); m_textureCoordinateAttribute->setCount(vertexCount); + if (shadow) { + m_textureBoundsAttribute = new Qt3DRender::QAttribute(this); + m_textureBoundsAttribute->setName(QStringLiteral("textureBounds")); + m_textureBoundsAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + m_textureBoundsAttribute->setVertexSize(4); + m_textureBoundsAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + m_textureBoundsAttribute->setBuffer(m_vertexBuffer); + m_textureBoundsAttribute->setByteStride(stride); + m_textureBoundsAttribute->setByteOffset(5 * sizeof(float)); + m_textureBoundsAttribute->setCount(vertexCount); + } else { + m_textureBoundsAttribute = nullptr; + } + m_indexAttribute = new Qt3DRender::QAttribute(this); m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); m_indexAttribute->setVertexBaseType(indexType); @@ -134,6 +152,8 @@ namespace { addAttribute(m_positionAttribute); addAttribute(m_textureCoordinateAttribute); addAttribute(m_indexAttribute); + if (shadow) + addAttribute(m_textureBoundsAttribute); } } @@ -143,10 +163,10 @@ Q3DSTextMesh::Q3DSTextMesh(Qt3DCore::QNode *parent) { } -void Q3DSTextMesh::setVertexes(const QVector<float> &vertexes) +void Q3DSTextMesh::setVertexes(const QVector<float> &vertexes, bool dropShadow) { delete m_geometry; - m_geometry = new Q3DSTextMeshGeometry(vertexes, this); + m_geometry = new Q3DSTextMeshGeometry(dropShadow, vertexes, this); setGeometry(m_geometry); } diff --git a/src/runtime/q3dstextmesh_p.h b/src/runtime/q3dstextmesh_p.h index 69b07a3..b68ecc9 100644 --- a/src/runtime/q3dstextmesh_p.h +++ b/src/runtime/q3dstextmesh_p.h @@ -56,7 +56,8 @@ public: explicit Q3DSTextMesh(Qt3DCore::QNode *parent = nullptr); ~Q3DSTextMesh() override; - void setVertexes(const QVector<float> &vertexes); + void setVertexes(const QVector<float> &vertexes, + bool dropShadow); private: Qt3DRender::QGeometry *m_geometry; diff --git a/src/runtime/shaders/distancefieldtext_dropshadow.frag b/src/runtime/shaders/distancefieldtext_dropshadow.frag new file mode 100644 index 0000000..da51c5c --- /dev/null +++ b/src/runtime/shaders/distancefieldtext_dropshadow.frag @@ -0,0 +1,29 @@ +varying highp vec2 sampleCoord; +varying highp vec2 alphas; +varying highp vec2 shadowSampleCoord; +varying highp vec4 normalizedTextureBounds; + +uniform sampler2D _qt_texture; +uniform highp vec4 color; +uniform highp vec4 shadowColor; + +void main() +{ + highp float shadowAlpha = smoothstep(alphas.x, + alphas.y, + texture2D(_qt_texture, + clamp(shadowSampleCoord, + normalizedTextureBounds.xy, + normalizedTextureBounds.zw)).a); + highp vec4 shadowPixel = shadowColor * shadowAlpha; + + highp float textAlpha = smoothstep(alphas.x, + alphas.y, + texture2D(_qt_texture, + clamp(sampleCoord, + normalizedTextureBounds.xy, + normalizedTextureBounds.zw)).a); + highp vec4 textPixel = color * textAlpha; + + gl_FragColor = mix(shadowPixel, textPixel, textPixel.a); +} diff --git a/src/runtime/shaders/distancefieldtext_dropshadow.vert b/src/runtime/shaders/distancefieldtext_dropshadow.vert new file mode 100644 index 0000000..69fd211 --- /dev/null +++ b/src/runtime/shaders/distancefieldtext_dropshadow.vert @@ -0,0 +1,75 @@ +uniform highp mat4 mvp; +uniform highp mat4 modelView; +uniform highp float fontScale; +uniform int textureWidth; +uniform int textureHeight; +uniform highp vec2 shadowOffset; + +attribute highp vec4 vCoord; +attribute highp vec2 tCoord; +attribute highp vec4 textureBounds; + +varying highp vec2 sampleCoord; +varying highp vec2 shadowSampleCoord; +varying highp vec2 alphas; +varying highp vec4 normalizedTextureBounds; + +highp float thresholdFunc(highp float scale) +{ + highp float base = 0.5; + highp float baseDev = 0.065; + highp float devScaleMin = 0.15; + highp float devScaleMax = 0.3; + return base - ((clamp(scale, devScaleMin, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev); +} + +highp float spreadFunc(highp float scale) +{ + return 0.06 / scale; +} + +highp vec2 alphaRange(highp float scale) +{ + highp float base = thresholdFunc(scale); + highp float range = spreadFunc(scale); + highp float alphaMin = max(0.0, base - range); + highp float alphaMax = min(base + range, 1.0); + return highp vec2(alphaMin, alphaMax); +} + +highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int row0, int row1) +{ + return m[col0][row0] * m[col1][row1] - m[col0][row1] * m[col1][row0]; +} + +highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int col2, int row0, int row1, int row2) +{ + highp float det = m[col0][row0] * determinantOfSubmatrix(m, col1, col2, row1, row2); + det -= m[col1][row0] * determinantOfSubmatrix(m, col0, col2, row1, row2); + det += m[col2][row0] * determinantOfSubmatrix(m, col0, col1, row1, row2); + return det; +} + +highp float determinant(highp mat4 m) +{ + highp float det = m[0][0] * determinantOfSubmatrix(m, 1, 2, 3, 1, 2, 3); + det -= m[1][0] * determinantOfSubmatrix(m, 0, 2, 3, 1, 2, 3); + det += m[2][0] * determinantOfSubmatrix(m, 0, 1, 3, 1, 2, 3); + det -= m[3][0] * determinantOfSubmatrix(m, 0, 1, 2, 1, 2, 3); + return det; +} + +void main() +{ + highp float scale = fontScale * sqrt(abs(determinant(modelView))); + alphas = alphaRange(scale); + + highp vec2 textureSizeMultiplier = highp vec2(1.0 / highp float(textureWidth), 1.0 / highp float(textureHeight)); + + sampleCoord = tCoord * textureSizeMultiplier; + shadowSampleCoord = (tCoord - shadowOffset) * textureSizeMultiplier; + normalizedTextureBounds = highp vec4(textureBounds.xy * textureSizeMultiplier, + textureBounds.zw * textureSizeMultiplier); + + gl_Position = mvp * vCoord; +} diff --git a/src/runtime/shaders/distancefieldtext_dropshadow_core.frag b/src/runtime/shaders/distancefieldtext_dropshadow_core.frag new file mode 100644 index 0000000..46a1194 --- /dev/null +++ b/src/runtime/shaders/distancefieldtext_dropshadow_core.frag @@ -0,0 +1,34 @@ +#version 150 core + +in vec2 sampleCoord; +in vec2 shadowSampleCoord; +in vec4 normalizedTextureBounds; + +out vec4 fragColor; + +uniform sampler2D _qt_texture; +uniform vec4 color; +uniform vec4 shadowColor; + +in vec2 alphas; + +void main() +{ + float shadowAlpha = smoothstep(alphas.x, + alphas.y, + texture(_qt_texture, + clamp(shadowSampleCoord, + normalizedTextureBounds.xy, + normalizedTextureBounds.zw)).r); + vec4 shadowPixel = shadowColor * shadowAlpha; + + float textAlpha = smoothstep(alphas.x, + alphas.y, + texture(_qt_texture, + clamp(sampleCoord, + normalizedTextureBounds.xy, + normalizedTextureBounds.zw)).r); + vec4 textPixel = color * textAlpha; + + fragColor = mix(shadowPixel, textPixel, textPixel.a); +} diff --git a/src/runtime/shaders/distancefieldtext_dropshadow_core.vert b/src/runtime/shaders/distancefieldtext_dropshadow_core.vert new file mode 100644 index 0000000..727dac5 --- /dev/null +++ b/src/runtime/shaders/distancefieldtext_dropshadow_core.vert @@ -0,0 +1,55 @@ +#version 150 core + +in vec4 vCoord; +in vec2 tCoord; +in vec4 textureBounds; + +out vec2 sampleCoord; +out vec2 shadowSampleCoord; + +out vec2 alphas; +out vec4 normalizedTextureBounds; + +uniform mat4 mvp; +uniform mat4 modelView; +uniform int textureWidth; +uniform int textureHeight; +uniform float fontScale; +uniform vec2 shadowOffset; + +float thresholdFunc(float scale) +{ + float base = 0.5; + float baseDev = 0.065; + float devScaleMin = 0.15; + float devScaleMax = 0.3; + return base - ((clamp(scale, devScaleMin, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev); +} + +float spreadFunc(float scale) +{ + return 0.06 / scale; +} + +vec2 alphaRange(float scale) +{ + float base = thresholdFunc(scale); + float range = spreadFunc(scale); + float alphaMin = max(0.0, base - range); + float alphaMax = min(base + range, 1.0); + return vec2(alphaMin, alphaMax); +} + +void main() +{ + float scale = fontScale * sqrt(abs(determinant(modelView))); + alphas = alphaRange(scale); + + vec2 textureSizeMultiplier = vec2(1.0 / textureWidth, 1.0 / textureHeight); + + sampleCoord = tCoord * textureSizeMultiplier; + shadowSampleCoord = (tCoord - shadowOffset) * textureSizeMultiplier; + normalizedTextureBounds = vec4(textureBounds.xy * textureSizeMultiplier, + textureBounds.zw * textureSizeMultiplier); + gl_Position = mvp * vCoord; +} |