@@ -18,34 +18,12 @@ namespace ext
18
18
namespace TextRendering
19
19
{
20
20
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)
43
22
{
44
23
uint32_t glyphW = msdfExtents.x ;
45
24
uint32_t glyphH = msdfExtents.y ;
46
25
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 );
49
27
int8_t * data = reinterpret_cast <int8_t *>(cpuBuf->getPointer ());
50
28
51
29
auto floatToSNORM8 = [](const float fl) -> int8_t
@@ -56,30 +34,22 @@ core::smart_refctd_ptr<ICPUBuffer> TextRenderer::generateShapeMSDF(msdfgen::Shap
56
34
57
35
msdfgen::edgeColoringSimple (glyph, 3.0 );
58
36
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 ();
66
38
67
- msdfgen::Bitmap<float , 4 > msdfMap (mipW, mipH );
39
+ msdfgen::Bitmap<float , 4 > msdfMap (msdfExtents. x , msdfExtents. y );
68
40
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 });
70
42
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)
72
46
{
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 ]);
81
52
}
82
- data += mipW * mipH * 4 ;
83
53
}
84
54
85
55
return std::move (cpuBuf);
@@ -98,33 +68,44 @@ FontFace::GlyphMetrics FontFace::getGlyphMetricss(uint32_t glyphId)
98
68
};
99
69
}
100
70
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)
102
72
{
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;
128
109
}
129
110
130
111
float32_t2 FontFace::getUV (float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange)
0 commit comments