Skip to content

Commit f187d68

Browse files
committed
Merge branch 'cad_large_texture_streaming'
2 parents 8b1a20e + 269a973 commit f187d68

File tree

4 files changed

+96
-17
lines changed

4 files changed

+96
-17
lines changed

include/nbl/builtin/hlsl/text_rendering/msdf.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This can then be processed using smoothstep to provide anti-alising when renderi
2323
@params:
2424
- msdfSample: sampled SNORM value from the MSDF texture generated by msdfgen library.
2525
26-
- pixelRange = msdfPixelRange * screenPxRangeValue, It is the value to convert snorm distance to screen space distance
26+
- pixelRange = screenPxRangeValue * msdfPixelRange * 0.5, It is the value to convert snorm distance to screen space distance
2727
- msdfPixelRange: specifies the width of the range around the shape between the minimum and maximum representable signed distance in shape units or distance field pixels, respectivelly.
2828
for example if msdfPixelRange is 4, then the range of distance values are [-2, +2], and it can be computed by snormValue * MSDFPixelRange/2.0
2929
so an snorm value of 1.0 means a distance of 2 pixels outside the shape (in msdf texture space)
@@ -34,7 +34,7 @@ This can then be processed using smoothstep to provide anti-alising when renderi
3434
where GlyphTextureSpaceSize is the size of the glyph inside the msdf texture/atlas
3535
*/
3636
float msdfDistance(float3 msdfSample, float pixelRange) {
37-
return median(msdfSample.r, msdfSample.g, msdfSample.b) * pixelRange / 2.0f;
37+
return median(msdfSample.r, msdfSample.g, msdfSample.b) * pixelRange;
3838
}
3939

4040
}

include/nbl/ext/TextRendering/TextRendering.h

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include <nbl/builtin/hlsl/cpp_compat/vector.hlsl>
1515
#include FT_FREETYPE_H
1616
#include FT_OUTLINE_H
17+
#include FT_TRUETYPE_TABLES_H
18+
#include FT_SFNT_NAMES_H
19+
#include FT_MULTIPLE_MASTERS_H
1720

1821
using namespace nbl;
1922
using namespace nbl::core;
@@ -90,14 +93,14 @@ class FontFace : public nbl::core::IReferenceCounted
9093
float64_t2 size;
9194
};
9295

93-
FontFace(core::smart_refctd_ptr<TextRenderer>&& textRenderer, const std::string& path)
96+
static core::smart_refctd_ptr<FontFace> create(core::smart_refctd_ptr<TextRenderer>&& textRenderer, const std::string& path, int faceIdx = 0)
9497
{
95-
m_textRenderer = std::move(textRenderer);
96-
97-
auto error = FT_New_Face(m_textRenderer->m_ftLibrary, path.c_str(), 0, &m_ftFace);
98-
assert(!error);
98+
FT_Face face;
99+
FT_Error res = FT_New_Face(textRenderer->m_ftLibrary, path.c_str(), faceIdx, &face);
100+
if (res != 0)
101+
return nullptr;
99102

100-
m_hash = std::hash<std::string>{}(path);
103+
return core::smart_refctd_ptr<FontFace>(new FontFace(std::move(textRenderer), face, path), core::dont_grab);
101104
}
102105

103106
~FontFace()
@@ -131,7 +134,7 @@ class FontFace : public nbl::core::IReferenceCounted
131134
// transforms uv in glyph space to uv in the actual texture
132135
float32_t2 getUV(float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange);
133136

134-
size_t getHash() { return m_hash; }
137+
core::blake3_hash_t getHash() { return m_hash; }
135138

136139
// TODO: make these protected, it's only used for customized tests such as building shapes for hatches
137140
FT_GlyphSlot getGlyphSlot(uint32_t glyphId)
@@ -140,14 +143,88 @@ class FontFace : public nbl::core::IReferenceCounted
140143
assert(!error);
141144
return m_ftFace->glyph;
142145
}
143-
FT_Face& getFreetypeFace() { return m_ftFace; }
146+
147+
FT_Face getFreetypeFace() { return m_ftFace; }
148+
144149
msdfgen::Shape generateGlyphShape(uint32_t glyphId);
150+
151+
// Functions to Set and Query Masters:
152+
153+
bool hasMultipleMasters() const
154+
{
155+
return FT_HAS_MULTIPLE_MASTERS(m_ftFace);
156+
}
157+
158+
uint32_t getMastersCount() const
159+
{
160+
uint32_t numMasters = 0u;
161+
if (hasMultipleMasters())
162+
{
163+
FT_MM_Var* multipleMasterData;
164+
FT_Error res = FT_Get_MM_Var(m_ftFace, &multipleMasterData);
165+
if (res == 0)
166+
{
167+
numMasters = multipleMasterData->num_namedstyles;
168+
FT_Done_MM_Var(m_textRenderer->m_ftLibrary, multipleMasterData);
169+
}
170+
}
171+
return numMasters;
172+
}
173+
174+
bool setMasterIndex(uint32_t index)
175+
{
176+
FT_Error res = FT_Set_Named_Instance(m_ftFace, index);
177+
if (res == 0)
178+
{
179+
calculateFaceHash();
180+
return true;
181+
}
182+
return false;
183+
}
184+
185+
// bits [0,15] are for faceIndex given to create function / constructor
186+
// bits [16,30] are for masterIndex given to `setMasterIndex` if it was ever called successfully
187+
// bit 31 is always 0
188+
// See FreeType documentation: https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_face
189+
int32_t getFaceIndex() const
190+
{
191+
return static_cast<int32_t>(m_ftFace->face_index);
192+
}
193+
194+
// Each face may have multiple masters. to change face index you need to recreate your face and use `int faceIdx` param
195+
uint32_t getNumFaces() const { return m_ftFace->num_faces; }
196+
197+
// Names:
198+
const char* getFontFamilyName() const { return m_ftFace->family_name; }
199+
const char* getStyleName() const { return m_ftFace->style_name; }
145200

146201
protected:
147202

203+
void calculateFaceHash()
204+
{
205+
core::blake3_hasher hasher;
206+
hasher.update(&m_ftFace->face_index, sizeof(FT_Long));
207+
hasher.update(&m_pathHash, sizeof(core::blake3_hash_t));
208+
m_hash = static_cast<blake3_hash_t>(hasher);
209+
}
210+
211+
FontFace(core::smart_refctd_ptr<TextRenderer>&& textRenderer, FT_Face face, const std::string& path)
212+
{
213+
m_textRenderer = std::move(textRenderer);
214+
m_ftFace = face;
215+
216+
// calculate hash path and store it
217+
core::blake3_hasher hasher;
218+
hasher.update(path.data(), path.size());
219+
m_pathHash = static_cast<blake3_hash_t>(hasher);
220+
// calculate final hash with faceIdx
221+
calculateFaceHash();
222+
}
223+
148224
core::smart_refctd_ptr<TextRenderer> m_textRenderer;
149225
FT_Face m_ftFace;
150-
size_t m_hash;
226+
core::blake3_hash_t m_pathHash;
227+
core::blake3_hash_t m_hash;
151228
};
152229

153230
// Helper class for building an msdfgen shape from a glyph
@@ -213,5 +290,4 @@ class GlyphShapeBuilder {
213290
}
214291
}
215292
}
216-
217293
#endif

src/nbl/ext/TextRendering/TextRendering.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@ core::smart_refctd_ptr<ICPUImage> FontFace::generateGlyphMSDF(uint32_t baseMSDFP
119119
// and we can't deep clone it
120120
auto shape = generateGlyphShape(glyphId);
121121

122-
// Empty shapes should've been filtered sooner
123-
assert(!shape.contours.empty());
124-
125122
uint32_t mipW = textureExtents.x / (1 << i);
126123
uint32_t mipH = textureExtents.y / (1 << i);
127124

@@ -136,6 +133,12 @@ core::smart_refctd_ptr<ICPUImage> FontFace::generateGlyphMSDF(uint32_t baseMSDFP
136133
region.imageOffset = { 0u,0u,0u };
137134
region.imageExtent = { mipW, mipH, 1u };
138135

136+
if (shape.contours.empty())
137+
{
138+
_NBL_DEBUG_BREAK_IF(true); // glyph id has no contours in it's shape for this font
139+
return nullptr;
140+
}
141+
139142
auto shapeBounds = shape.getBounds();
140143

141144
float32_t2 mipExtents = float32_t2(float(mipW), float(mipH));
@@ -166,7 +169,7 @@ core::smart_refctd_ptr<ICPUImage> FontFace::generateGlyphMSDF(uint32_t baseMSDFP
166169
assert(bufferOffset <= buffer->getCreationParams().size);
167170
image->setBufferAndRegions(std::move(buffer), std::move(regions));
168171

169-
return std::move(image);
172+
return image;
170173
}
171174

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

0 commit comments

Comments
 (0)