Skip to content

Commit 046e29c

Browse files
committed
Work on generating the msdf mips
1 parent a2450b3 commit 046e29c

File tree

2 files changed

+53
-31
lines changed

2 files changed

+53
-31
lines changed

include/nbl/ext/TextRendering/TextRendering.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class TextRenderer : public nbl::core::IReferenceCounted
3737
static constexpr asset::E_FORMAT MSDFTextureFormat = asset::E_FORMAT::EF_R8G8B8A8_SNORM;
3838

3939
// Spits out CPUBuffer containing the image data in SNORM format
40-
core::smart_refctd_ptr<ICPUImage> generateShapeMSDF(
40+
core::smart_refctd_ptr<ICPUBuffer> generateShapeMSDF(
4141
msdfgen::Shape glyph, uint32_t msdfPixelRange,
4242
uint32_t2 msdfExtents, uint32_t msdfMipLevels,
4343
float32_t2 scale, float32_t2 translate);
@@ -98,7 +98,7 @@ class FontFace : public nbl::core::IReferenceCounted
9898
// it will place the glyph in the center of msdfExtents considering the margin of msdfPixelRange
9999
// preserves aspect ratio of the glyph corresponding to metrics of the "glyphId"
100100
// use the `getUV` to address the glyph in your texture correctly.
101-
core::smart_refctd_ptr<ICPUImage> generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels);
101+
core::smart_refctd_ptr<ICPUBuffer> generateGlyphMSDF(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: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,49 +18,71 @@ namespace ext
1818
namespace TextRendering
1919
{
2020

21-
core::smart_refctd_ptr<ICPUImage> TextRenderer::generateShapeMSDF(msdfgen::Shape glyph, uint32_t msdfPixelRange, uint32_t2 msdfExtents, uint32_t msdfMipLevels, float32_t2 scale, float32_t2 translate)
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)
2243
{
2344
uint32_t glyphW = msdfExtents.x;
2445
uint32_t glyphH = msdfExtents.y;
2546

26-
auto shapeBounds = glyph.getBounds();
47+
uint32_t size = 0;
48+
auto cpuBuf = core::make_smart_refctd_ptr<ICPUBuffer>(size);
49+
int8_t* data = reinterpret_cast<int8_t*>(cpuBuf->getPointer());
50+
51+
auto floatToSNORM8 = [](const float fl) -> int8_t
52+
{
53+
// we need to invert values because msdfgen assigns positive values for shape interior which is the exact opposite of our convention
54+
return -1 * (int8_t)(std::clamp(fl * 2.0f - 1.0f, -1.0f, 1.0f) * 127.f);
55+
};
2756

2857
msdfgen::edgeColoringSimple(glyph, 3.0);
29-
msdfgen::Bitmap<float, 4> msdfMap(glyphW, glyphH);
3058

31-
msdfgen::generateMTSDF(msdfMap, glyph, msdfPixelRange, { scale.x, scale.y }, { translate.x, translate.y });
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);
3264

65+
auto shapeBounds = glyphCopy.getBounds();
3366

34-
asset::ICPUImage::SCreationParams creationParams;
35-
creationParams.type = asset::IImage::ET_2D;
36-
creationParams.samples = asset::IImage::ESCF_1_BIT;
37-
creationParams.format = TextRenderer::MSDFTextureFormat;
38-
creationParams.extent = { msdfExtents.x, msdfExtents.y, 1 };
39-
creationParams.mipLevels = msdfMipLevels;
40-
creationParams.arrayLayers = 1;
41-
auto image = asset::ICPUImage::create(std::move(creationParams));
67+
msdfgen::Bitmap<float, 4> msdfMap(mipW, mipH);
4268

43-
int8_t* data = reinterpret_cast<int8_t*>(image->getBuffer()->getPointer());
44-
45-
auto floatToSNORM8 = [](const float fl) -> int8_t
46-
{
47-
// we need to invert values because msdfgen assigns positive values for shape interior which is the exact opposite of our convention
48-
return -1 * (int8_t)(std::clamp(fl * 2.0f - 1.0f, -1.0f, 1.0f) * 127.f);
49-
};
69+
msdfgen::generateMTSDF(msdfMap, glyphCopy, msdfPixelRange, { scale.x, scale.y }, { translate.x, translate.y });
5070

51-
for (int y = 0; y < msdfMap.height(); ++y)
52-
{
53-
for (int x = 0; x < msdfMap.width(); ++x)
71+
for (int y = 0; y < mipW; ++y)
5472
{
55-
auto pixel = msdfMap(x, glyphH - 1 - y);
56-
data[(x + y * glyphW) * 4 + 0] = floatToSNORM8(pixel[0]);
57-
data[(x + y * glyphW) * 4 + 1] = floatToSNORM8(pixel[1]);
58-
data[(x + y * glyphW) * 4 + 2] = floatToSNORM8(pixel[2]);
59-
data[(x + y * glyphW) * 4 + 3] = floatToSNORM8(pixel[3]);
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+
}
6081
}
82+
data += mipW * mipH * 4;
6183
}
6284

63-
return std::move(image);
85+
return std::move(cpuBuf);
6486
}
6587

6688
constexpr double FreeTypeFontScaling = 1.0 / 64.0;
@@ -76,7 +98,7 @@ FontFace::GlyphMetrics FontFace::getGlyphMetricss(uint32_t glyphId)
7698
};
7799
}
78100

79-
core::smart_refctd_ptr<ICPUImage> FontFace::generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels)
101+
core::smart_refctd_ptr<ICPUBuffer> FontFace::generateGlyphMSDF(uint32_t msdfPixelRange, uint32_t glyphId, uint32_t2 textureExtents, uint32_t mipLevels)
80102
{
81103
auto shape = generateGlyphShape(glyphId);
82104

0 commit comments

Comments
 (0)