Skip to content

Commit e06d489

Browse files
committed
Work on mips
1 parent 046e29c commit e06d489

File tree

2 files changed

+53
-72
lines changed

2 files changed

+53
-72
lines changed

include/nbl/ext/TextRendering/TextRendering.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ class TextRenderer : public nbl::core::IReferenceCounted
3939
// Spits out CPUBuffer containing the image data in SNORM format
4040
core::smart_refctd_ptr<ICPUBuffer> generateShapeMSDF(
4141
msdfgen::Shape glyph, uint32_t msdfPixelRange,
42-
uint32_t2 msdfExtents, uint32_t msdfMipLevels,
43-
float32_t2 scale, float32_t2 translate);
42+
uint32_t2 msdfExtents, float32_t2 scale, float32_t2 translate);
4443

4544
TextRenderer()
4645
{
@@ -98,7 +97,8 @@ class FontFace : public nbl::core::IReferenceCounted
9897
// it will place the glyph in the center of msdfExtents considering the margin of msdfPixelRange
9998
// preserves aspect ratio of the glyph corresponding to metrics of the "glyphId"
10099
// use the `getUV` to address the glyph in your texture correctly.
101-
core::smart_refctd_ptr<ICPUBuffer> generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels);
100+
std::vector<core::smart_refctd_ptr<ICPUBuffer>> generateGlyphMSDF(
101+
uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels);
102102

103103
// transforms uv in glyph space to uv in the actual texture
104104
float32_t2 getUV(float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange);

src/nbl/ext/TextRendering/TextRendering.cpp

Lines changed: 50 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,12 @@ namespace ext
1818
namespace TextRendering
1919
{
2020

21-
// TODO find an alternative for this (we need it because msdfgen consumes the glyphs when doing generateMSDF)
22-
msdfgen::Shape deepCloneShape(const msdfgen::Shape& original) {
23-
msdfgen::Shape copy;
24-
for (uint32_t contour = 0; contour < original.contours.size(); contour++)
25-
{
26-
msdfgen::Contour c;
27-
auto originalEdges = original.contours[contour].edges;
28-
c.edges.reserve(originalEdges.size());
29-
30-
for (uint32_t edge = 0; edge < originalEdges.size(); edge++)
31-
{
32-
auto segment = msdfgen::EdgeHolder();
33-
segment = originalEdges[edge];
34-
c.edges.push_back(segment);
35-
}
36-
37-
copy.contours.push_back(c);
38-
}
39-
return copy;
40-
}
41-
42-
core::smart_refctd_ptr<ICPUBuffer> TextRenderer::generateShapeMSDF(msdfgen::Shape glyph, uint32_t msdfPixelRange, uint32_t2 msdfExtents, uint32_t msdfMipLevels, float32_t2 scale, float32_t2 translate)
21+
core::smart_refctd_ptr<ICPUBuffer> TextRenderer::generateShapeMSDF(msdfgen::Shape glyph, uint32_t msdfPixelRange, uint32_t2 msdfExtents, float32_t2 scale, float32_t2 translate)
4322
{
4423
uint32_t glyphW = msdfExtents.x;
4524
uint32_t glyphH = msdfExtents.y;
4625

47-
uint32_t size = 0;
48-
auto cpuBuf = core::make_smart_refctd_ptr<ICPUBuffer>(size);
26+
auto cpuBuf = core::make_smart_refctd_ptr<ICPUBuffer>(glyphW * glyphH * sizeof(int8_t) * 4);
4927
int8_t* data = reinterpret_cast<int8_t*>(cpuBuf->getPointer());
5028

5129
auto floatToSNORM8 = [](const float fl) -> int8_t
@@ -56,30 +34,22 @@ core::smart_refctd_ptr<ICPUBuffer> TextRenderer::generateShapeMSDF(msdfgen::Shap
5634

5735
msdfgen::edgeColoringSimple(glyph, 3.0);
5836

59-
for (uint32_t mip = 0; mip < msdfMipLevels; mip++)
60-
{
61-
msdfgen::Shape glyphCopy = deepCloneShape(glyph);
62-
uint32_t mipW = glyphW / (1 << mip);
63-
uint32_t mipH = glyphH / (1 << mip);
64-
65-
auto shapeBounds = glyphCopy.getBounds();
37+
auto shapeBounds = glyph.getBounds();
6638

67-
msdfgen::Bitmap<float, 4> msdfMap(mipW, mipH);
39+
msdfgen::Bitmap<float, 4> msdfMap(msdfExtents.x, msdfExtents.y);
6840

69-
msdfgen::generateMTSDF(msdfMap, glyphCopy, msdfPixelRange, { scale.x, scale.y }, { translate.x, translate.y });
41+
msdfgen::generateMTSDF(msdfMap, glyph, msdfPixelRange, { scale.x, scale.y }, { translate.x, translate.y });
7042

71-
for (int y = 0; y < mipW; ++y)
43+
for (int y = 0; y < msdfExtents.x; ++y)
44+
{
45+
for (int x = 0; x < msdfExtents.y; ++x)
7246
{
73-
for (int x = 0; x < mipH; ++x)
74-
{
75-
auto pixel = msdfMap(x, mipH - 1 - y);
76-
data[(x + y * mipW) * 4 + 0] = floatToSNORM8(pixel[0]);
77-
data[(x + y * mipW) * 4 + 1] = floatToSNORM8(pixel[1]);
78-
data[(x + y * mipW) * 4 + 2] = floatToSNORM8(pixel[2]);
79-
data[(x + y * mipW) * 4 + 3] = floatToSNORM8(pixel[3]);
80-
}
47+
auto pixel = msdfMap(x, msdfExtents.y - 1 - y);
48+
data[(x + y * msdfExtents.x) * 4 + 0] = floatToSNORM8(pixel[0]);
49+
data[(x + y * msdfExtents.x) * 4 + 1] = floatToSNORM8(pixel[1]);
50+
data[(x + y * msdfExtents.x) * 4 + 2] = floatToSNORM8(pixel[2]);
51+
data[(x + y * msdfExtents.x) * 4 + 3] = floatToSNORM8(pixel[3]);
8152
}
82-
data += mipW * mipH * 4;
8353
}
8454

8555
return std::move(cpuBuf);
@@ -98,33 +68,44 @@ FontFace::GlyphMetrics FontFace::getGlyphMetricss(uint32_t glyphId)
9868
};
9969
}
10070

101-
core::smart_refctd_ptr<ICPUBuffer> FontFace::generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels)
71+
std::vector<core::smart_refctd_ptr<ICPUBuffer>> FontFace::generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels)
10272
{
103-
auto shape = generateGlyphShape(glyphId);
104-
105-
// Empty shapes should've been filtered sooner
106-
assert(!shape.contours.empty());
107-
108-
auto shapeBounds = shape.getBounds();
109-
110-
float32_t2 frameSize = float32_t2(
111-
(shapeBounds.r - shapeBounds.l),
112-
(shapeBounds.t - shapeBounds.b)
113-
);
114-
115-
const float32_t2 margin = float32_t2(msdfPixelRange * 2.0f);
116-
const float32_t2 nonUniformScale = (float32_t2(textureExtents) - margin) / frameSize;
117-
const float32_t uniformScale = core::min(nonUniformScale.x, nonUniformScale.y);
118-
119-
// Center before: ((shapeBounds.l + shapeBounds.r) * 0.5, (shapeBounds.t + shapeBounds.b) * 0.5)
120-
// Center after: msdfExtents / 2.0
121-
// Transformation implementation: Center after = (Center before + Translation) * Scale
122-
// Plugging in the values and solving for translate yields:
123-
// Translate = (msdfExtents / (2 * scale)) - ((shapeBounds.l + shapeBounds.r) * 0.5, (shapeBounds.t + shapeBounds.b) * 0.5)
124-
const float32_t2 shapeSpaceCenter = float32_t2(shapeBounds.l + shapeBounds.r, shapeBounds.t + shapeBounds.b) * float32_t2(0.5);
125-
const float32_t2 translate = float32_t2(textureExtents) / (float32_t2(2.0) * uniformScale) - shapeSpaceCenter;
126-
127-
return m_textRenderer->generateShapeMSDF(shape, msdfPixelRange, textureExtents, mipLevels, float32_t2(uniformScale, uniformScale), translate);
73+
std::vector<core::smart_refctd_ptr<ICPUBuffer>> buffers;
74+
for (uint32_t i = 0; i < mipLevels; i++)
75+
{
76+
// we need to generate a msdfgen per mip map, because the msdf generate call consumes the shape
77+
// and we can't deep clone it
78+
auto shape = generateGlyphShape(glyphId);
79+
80+
// Empty shapes should've been filtered sooner
81+
assert(!shape.contours.empty());
82+
83+
auto shapeBounds = shape.getBounds();
84+
85+
uint32_t mipW = textureExtents.x / (1 << i);
86+
uint32_t mipH = textureExtents.y / (1 << i);
87+
float32_t2 mipExtents = float32_t2(float(mipW), float(mipH));
88+
89+
float32_t2 frameSize = float32_t2(
90+
(shapeBounds.r - shapeBounds.l),
91+
(shapeBounds.t - shapeBounds.b)
92+
);
93+
94+
const float32_t2 margin = float32_t2((msdfPixelRange / (1 << i)) * 2.0f);
95+
const float32_t2 nonUniformScale = (mipExtents - margin) / frameSize;
96+
const float32_t uniformScale = core::min(nonUniformScale.x, nonUniformScale.y);
97+
98+
// Center before: ((shapeBounds.l + shapeBounds.r) * 0.5, (shapeBounds.t + shapeBounds.b) * 0.5)
99+
// Center after: msdfExtents / 2.0
100+
// Transformation implementation: Center after = (Center before + Translation) * Scale
101+
// Plugging in the values and solving for translate yields:
102+
// Translate = (msdfExtents / (2 * scale)) - ((shapeBounds.l + shapeBounds.r) * 0.5, (shapeBounds.t + shapeBounds.b) * 0.5)
103+
const float32_t2 shapeSpaceCenter = float32_t2(shapeBounds.l + shapeBounds.r, shapeBounds.t + shapeBounds.b) * float32_t2(0.5);
104+
const float32_t2 translate = mipExtents / (float32_t2(2.0) * uniformScale) - shapeSpaceCenter;
105+
106+
buffers.push_back(m_textRenderer->generateShapeMSDF(shape, msdfPixelRange, mipExtents, float32_t2(uniformScale, uniformScale), translate));
107+
}
108+
return buffers;
128109
}
129110

130111
float32_t2 FontFace::getUV(float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange)

0 commit comments

Comments
 (0)