mirror of https://github.com/AxioDL/metaforce.git
addditional font atlas implementation
This commit is contained in:
parent
99d85ba60c
commit
b6a5655067
|
@ -1,3 +1,6 @@
|
|||
[submodule "freetype2"]
|
||||
path = freetype2
|
||||
url = https://github.com/AxioDL/freetype2
|
||||
[submodule "MathLib"]
|
||||
path = MathLib
|
||||
url = https://github.com/AxioDL/MathLib.git
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
add_subdirectory(freetype2)
|
||||
add_subdirectory(MathLib)
|
||||
set(MATHLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MathLib/include)
|
||||
|
||||
if(NOT DEFINED HECL_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "Specter may only be built as a sub-project containing hecl with
|
||||
|
@ -24,7 +26,8 @@ add_subdirectory(resources/fonts)
|
|||
|
||||
include_directories(include ${HECL_INCLUDE_DIR} ${BOO_INCLUDE_DIR}
|
||||
${LOG_VISOR_INCLUDE_DIR} ${ATHENA_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/freetype2/include)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/freetype2/include
|
||||
${MATHLIB_INCLUDE_DIR})
|
||||
|
||||
list(APPEND SPECTER_HEADERS
|
||||
include/Specter/Specter.hpp
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 8d54a3c7b5d76e32d9fb3ad57619a680b32909b7
|
|
@ -42,6 +42,8 @@ class FreeTypeGZipMemFace
|
|||
FT_Face m_face = nullptr;
|
||||
public:
|
||||
FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz);
|
||||
FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete;
|
||||
FreeTypeGZipMemFace& operator=(const FreeTypeGZipMemFace& other) = delete;
|
||||
~FreeTypeGZipMemFace() {close();}
|
||||
void open();
|
||||
void close();
|
||||
|
@ -53,7 +55,9 @@ class FontAtlas
|
|||
friend class FontCache;
|
||||
FT_Face m_face;
|
||||
boo::ITextureS* m_tex;
|
||||
uint32_t m_dpi;
|
||||
|
||||
public:
|
||||
struct Glyph
|
||||
{
|
||||
atUint32 m_unicodePoint;
|
||||
|
@ -65,14 +69,30 @@ class FontAtlas
|
|||
atUint8 m_width;
|
||||
atUint8 m_height;
|
||||
atInt8 m_verticalOffset;
|
||||
atUint16 m_kernIdx;
|
||||
atInt16 m_kernIdx = -1;
|
||||
};
|
||||
|
||||
struct KernAdj
|
||||
{
|
||||
atUint32 a;
|
||||
atUint32 b;
|
||||
atInt8 adj;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<Glyph> m_glyphs;
|
||||
std::map<atUint32, size_t> m_glyphLookup;
|
||||
std::vector<KernAdj> m_kernAdjs;
|
||||
std::unordered_map<atUint32, size_t> m_glyphLookup;
|
||||
|
||||
public:
|
||||
FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, bool subpixel, Athena::io::FileWriter& writer);
|
||||
FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, bool subpixel, Athena::io::FileReader& reader);
|
||||
FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||
bool subpixel, Athena::io::FileWriter& writer);
|
||||
FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||
bool subpixel, Athena::io::FileReader& reader);
|
||||
FontAtlas(const FontAtlas& other) = delete;
|
||||
FontAtlas& operator=(const FontAtlas& other) = delete;
|
||||
|
||||
uint32_t dpi() const {return m_dpi;}
|
||||
};
|
||||
|
||||
class FontCache
|
||||
|
@ -92,6 +112,8 @@ class FontCache
|
|||
std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
|
||||
public:
|
||||
FontCache(const HECL::Runtime::FileStoreManager& fileMgr);
|
||||
FontCache(const FontCache& other) = delete;
|
||||
FontCache& operator=(const FontCache& other) = delete;
|
||||
|
||||
FontTag prepCustomFont(boo::IGraphicsDataFactory* gf,
|
||||
const std::string& name, FT_Face face, bool subpixel=false,
|
||||
|
@ -106,6 +128,8 @@ public:
|
|||
{return prepCustomFont(gf, "bmonofont", m_monoFace, subpixel, points, dpi);}
|
||||
|
||||
void closeBuiltinFonts() {m_regFace.close(); m_monoFace.close();}
|
||||
|
||||
const FontAtlas& lookupAtlas(FontTag tag) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2,14 +2,68 @@
|
|||
#define SPECTER_TEXTVIEW_HPP
|
||||
|
||||
#include "View.hpp"
|
||||
#include <boo/graphicsdev/GL.hpp>
|
||||
#include <boo/graphicsdev/D3D.hpp>
|
||||
#include <boo/graphicsdev/Metal.hpp>
|
||||
|
||||
#include "FontCache.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
class TextView : public View
|
||||
{
|
||||
boo::IGraphicsBufferD* m_glyphBuf;
|
||||
int m_validDynamicSlots = 0;
|
||||
size_t m_curGlyphCapacity;
|
||||
const FontAtlas& m_fontAtlas;
|
||||
boo::IVertexFormat* m_vtxFmt = nullptr; /* OpenGL only */
|
||||
|
||||
public:
|
||||
class System
|
||||
{
|
||||
friend class TextView;
|
||||
boo::IGraphicsDataFactory* m_factory;
|
||||
FontCache& m_fcache;
|
||||
boo::IShaderPipeline* m_regular;
|
||||
boo::IShaderPipeline* m_subpixel;
|
||||
boo::IGraphicsBufferS* m_quadVBO;
|
||||
boo::IVertexFormat* m_vtxFmt = nullptr; /* Not OpenGL */
|
||||
|
||||
System(boo::IGraphicsDataFactory* factory, FontCache& fcache)
|
||||
: m_factory(factory), m_fcache(fcache) {}
|
||||
};
|
||||
static System BuildTextSystem(boo::GLDataFactory* factory, FontCache& fcache);
|
||||
#if _WIN32
|
||||
static Shaders BuildTextSystem(boo::ID3DDataFactory* factory, FontCache& fcache);
|
||||
#elif BOO_HAS_METAL
|
||||
static Shaders BuildTextSystem(boo::MetalDataFactory* factory, FontCache& fcache);
|
||||
#endif
|
||||
|
||||
TextView(System& system, FontTag font, size_t initGlyphCapacity=256);
|
||||
|
||||
struct RenderGlyph
|
||||
{
|
||||
Zeus::CMatrix4f m_mvp;
|
||||
Zeus::CVector3f m_uv[4];
|
||||
Zeus::CColor m_color;
|
||||
};
|
||||
std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;}
|
||||
void updateGlyphs() {m_validDynamicSlots = 0;}
|
||||
|
||||
void typesetGlyphs(const std::string& str,
|
||||
Zeus::CColor defaultColor=Zeus::CColor::skWhite);
|
||||
void typesetGlyphs(const std::wstring& str,
|
||||
Zeus::CColor defaultColor=Zeus::CColor::skWhite);
|
||||
|
||||
void colorGlyphs(Zeus::CColor newColor);
|
||||
void colorGlyphsTypeOn(Zeus::CColor newColor, float startInterval=0.2, float fadeTime=0.5);
|
||||
void think();
|
||||
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
|
||||
private:
|
||||
std::vector<RenderGlyph> m_glyphs;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2,18 +2,20 @@
|
|||
#define SPECTER_VIEW_HPP
|
||||
|
||||
#include <boo/boo.hpp>
|
||||
#include "CVector3f.hpp"
|
||||
#include "CMatrix4f.hpp"
|
||||
#include "CTransform.hpp"
|
||||
#include "CColor.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
class View
|
||||
{
|
||||
boo::SWindowRect m_rect;
|
||||
protected:
|
||||
boo::SWindowRect m_viewport;
|
||||
void bindViewport(boo::IGraphicsCommandQueue* gfxQ) {gfxQ->setViewport(m_viewport);}
|
||||
public:
|
||||
void bindViewport(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
gfxQ->setViewport(m_rect);
|
||||
}
|
||||
virtual void draw(boo::IGraphicsCommandQueue* gfxQ)=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -121,8 +121,9 @@ static inline void GridFitGlyph(FT_GlyphSlot slot, FT_UInt& width, FT_UInt& heig
|
|||
height = slot->metrics.height >> 6;
|
||||
}
|
||||
|
||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face,
|
||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||
bool subpixel, Athena::io::FileWriter& writer)
|
||||
: m_dpi(dpi)
|
||||
{
|
||||
FT_Int32 baseFlags = FT_LOAD_NO_BITMAP;
|
||||
if (subpixel)
|
||||
|
@ -163,6 +164,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face,
|
|||
charcode = FT_Get_Next_Char(face, charcode, &gindex);
|
||||
}
|
||||
m_glyphs.reserve(glyphCount);
|
||||
m_glyphLookup.reserve(glyphCount);
|
||||
|
||||
totalHeight = RoundUpPow2(totalHeight);
|
||||
unsigned finalHeight = fullTexmapLayers ? TEXMAP_DIM : totalHeight;
|
||||
|
@ -200,6 +202,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face,
|
|||
while (gindex != 0)
|
||||
{
|
||||
FT_Load_Glyph(face, gindex, FT_LOAD_RENDER | baseFlags);
|
||||
m_glyphLookup[charcode] = m_glyphs.size();
|
||||
m_glyphs.emplace_back();
|
||||
Glyph& g = m_glyphs.back();
|
||||
g.m_unicodePoint = charcode;
|
||||
|
@ -270,6 +273,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face,
|
|||
while (gindex != 0)
|
||||
{
|
||||
FT_Load_Glyph(face, gindex, FT_LOAD_RENDER | baseFlags);
|
||||
m_glyphLookup[charcode] = m_glyphs.size();
|
||||
m_glyphs.emplace_back();
|
||||
Glyph& g = m_glyphs.back();
|
||||
g.m_unicodePoint = charcode;
|
||||
|
@ -312,8 +316,174 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face,
|
|||
}
|
||||
}
|
||||
|
||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, bool subpixel, Athena::io::FileReader& reader)
|
||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||
bool subpixel, Athena::io::FileReader& reader)
|
||||
: m_dpi(dpi)
|
||||
{
|
||||
FT_Int32 baseFlags = FT_LOAD_NO_BITMAP;
|
||||
if (subpixel)
|
||||
baseFlags |= FT_LOAD_TARGET_LCD;
|
||||
else
|
||||
baseFlags |= FT_LOAD_TARGET_NORMAL;
|
||||
|
||||
/* First count glyphs exposed by unicode charmap */
|
||||
size_t glyphCount = 0;
|
||||
FT_UInt gindex;
|
||||
FT_ULong charcode = FT_Get_First_Char(face, &gindex);
|
||||
while (gindex != 0)
|
||||
{
|
||||
++glyphCount;
|
||||
charcode = FT_Get_Next_Char(face, charcode, &gindex);
|
||||
}
|
||||
m_glyphs.reserve(glyphCount);
|
||||
m_glyphLookup.reserve(glyphCount);
|
||||
|
||||
unsigned fullTexmapLayers = reader.readUint32Big() - 1;
|
||||
reader.readUint32Big();
|
||||
unsigned finalHeight = reader.readUint32Big();
|
||||
|
||||
if (subpixel)
|
||||
{
|
||||
/* Allocate texmap */
|
||||
std::unique_ptr<RgbaPixel[]> texmap;
|
||||
size_t bufSz;
|
||||
if (fullTexmapLayers)
|
||||
{
|
||||
//printf("ALLOC: %u\n", fullTexmapLayers + 1);
|
||||
size_t count = TEXMAP_DIM * TEXMAP_DIM * (fullTexmapLayers + 1);
|
||||
texmap.reset(new RgbaPixel[count]);
|
||||
bufSz = count * sizeof(RgbaPixel);
|
||||
memset(texmap.get(), 0, bufSz);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t count = TEXMAP_DIM * finalHeight;
|
||||
texmap.reset(new RgbaPixel[TEXMAP_DIM * finalHeight]);
|
||||
bufSz = count * sizeof(RgbaPixel);
|
||||
memset(texmap.get(), 0, bufSz);
|
||||
}
|
||||
|
||||
/* Assemble glyph texmaps and internal data structures */
|
||||
charcode = FT_Get_First_Char(face, &gindex);
|
||||
unsigned curLineWidth = 1;
|
||||
unsigned curLineHeight = 0;
|
||||
unsigned totalHeight = 1;
|
||||
fullTexmapLayers = 0;
|
||||
while (gindex != 0)
|
||||
{
|
||||
FT_Load_Glyph(face, gindex, baseFlags);
|
||||
FT_UInt width, height;
|
||||
GridFitGlyph(face->glyph, width, height);
|
||||
m_glyphs.emplace_back();
|
||||
Glyph& g = m_glyphs.back();
|
||||
g.m_unicodePoint = charcode;
|
||||
g.m_layerIdx = fullTexmapLayers;
|
||||
g.m_width = width;
|
||||
g.m_height = height;
|
||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||
g.m_uv[1] = totalHeight / float(finalHeight);
|
||||
g.m_uv[2] = g.m_uv[0] + g.m_width / float(TEXMAP_DIM);
|
||||
g.m_uv[3] = g.m_uv[1] + g.m_height / float(finalHeight);
|
||||
g.m_leftPadding = 0;
|
||||
g.m_advance = face->glyph->advance.x;
|
||||
g.m_rightPadding = 0;
|
||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY / 64;
|
||||
g.m_kernIdx = 0;
|
||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||
{
|
||||
totalHeight += curLineHeight + 1;
|
||||
curLineHeight = 0;
|
||||
curLineWidth = 1;
|
||||
}
|
||||
curLineHeight = std::max(curLineHeight, height);
|
||||
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM)
|
||||
{
|
||||
totalHeight = 1;
|
||||
++fullTexmapLayers;
|
||||
//printf("RealB: %u\n", gindex);
|
||||
curLineHeight = 0;
|
||||
curLineWidth = 1;
|
||||
}
|
||||
curLineWidth += g.m_width + 1;
|
||||
charcode = FT_Get_Next_Char(face, charcode, &gindex);
|
||||
}
|
||||
|
||||
reader.readUBytesToBuf((atUint8*)texmap.get(), bufSz);
|
||||
m_tex =
|
||||
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
||||
boo::TextureFormat::RGBA8, texmap.get(), bufSz);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate texmap */
|
||||
std::unique_ptr<GreyPixel[]> texmap;
|
||||
size_t bufSz;
|
||||
if (fullTexmapLayers)
|
||||
{
|
||||
//printf("ALLOC: %u\n", fullTexmapLayers + 1);
|
||||
size_t count = TEXMAP_DIM * TEXMAP_DIM * (fullTexmapLayers + 1);
|
||||
texmap.reset(new GreyPixel[count]);
|
||||
bufSz = count * sizeof(GreyPixel);
|
||||
memset(texmap.get(), 0, bufSz);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t count = TEXMAP_DIM * totalHeight;
|
||||
texmap.reset(new GreyPixel[TEXMAP_DIM * totalHeight]);
|
||||
bufSz = count * sizeof(GreyPixel);
|
||||
memset(texmap.get(), 0, bufSz);
|
||||
}
|
||||
|
||||
/* Assemble glyph texmaps and internal data structures */
|
||||
charcode = FT_Get_First_Char(face, &gindex);
|
||||
unsigned curLineWidth = 1;
|
||||
unsigned curLineHeight = 0;
|
||||
unsigned totalHeight = 1;
|
||||
fullTexmapLayers = 0;
|
||||
while (gindex != 0)
|
||||
{
|
||||
FT_Load_Glyph(face, gindex, baseFlags);
|
||||
FT_UInt width, height;
|
||||
GridFitGlyph(face->glyph, width, height);
|
||||
m_glyphs.emplace_back();
|
||||
Glyph& g = m_glyphs.back();
|
||||
g.m_unicodePoint = charcode;
|
||||
g.m_layerIdx = fullTexmapLayers;
|
||||
g.m_width = width;
|
||||
g.m_height = height;
|
||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||
g.m_uv[1] = totalHeight / float(finalHeight);
|
||||
g.m_uv[2] = g.m_uv[0] + g.m_width / float(TEXMAP_DIM);
|
||||
g.m_uv[3] = g.m_uv[1] + g.m_height / float(finalHeight);
|
||||
g.m_leftPadding = 0;
|
||||
g.m_advance = face->glyph->advance.x;
|
||||
g.m_rightPadding = 0;
|
||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY >> 6;
|
||||
g.m_kernIdx = 0;
|
||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||
{
|
||||
totalHeight += curLineHeight + 1;
|
||||
curLineHeight = 0;
|
||||
curLineWidth = 1;
|
||||
}
|
||||
curLineHeight = std::max(curLineHeight, height);
|
||||
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM)
|
||||
{
|
||||
totalHeight = 1;
|
||||
++fullTexmapLayers;
|
||||
//printf("RealB: %u\n", gindex);
|
||||
curLineHeight = 0;
|
||||
curLineWidth = 1;
|
||||
}
|
||||
curLineWidth += g.m_width + 1;
|
||||
charcode = FT_Get_Next_Char(face, charcode, &gindex);
|
||||
}
|
||||
|
||||
reader.readUBytesToBuf((atUint8*)texmap.get(), bufSz);
|
||||
m_tex =
|
||||
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
||||
boo::TextureFormat::I8, texmap.get(), bufSz);
|
||||
}
|
||||
}
|
||||
|
||||
FontCache::Library::Library()
|
||||
|
@ -367,7 +537,7 @@ FontTag FontCache::prepCustomFont(boo::IGraphicsDataFactory* gf,
|
|||
atUint32 magic = r.readUint32Big();
|
||||
if (r.position() == 4 && magic == 'FONT')
|
||||
{
|
||||
m_cachedAtlases.emplace(tag, std::make_unique<FontAtlas>(gf, face, subpixel, r));
|
||||
m_cachedAtlases.emplace(tag, std::make_unique<FontAtlas>(gf, face, dpi, subpixel, r));
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
@ -379,8 +549,16 @@ FontTag FontCache::prepCustomFont(boo::IGraphicsDataFactory* gf,
|
|||
if (w.hasError())
|
||||
Log.report(LogVisor::FatalError, "unable to open '%s' for writing", cachePath.c_str());
|
||||
w.writeUint32Big('FONT');
|
||||
m_cachedAtlases.emplace(tag, std::make_unique<FontAtlas>(gf, face, subpixel, w));
|
||||
m_cachedAtlases.emplace(tag, std::make_unique<FontAtlas>(gf, face, dpi, subpixel, w));
|
||||
return tag;
|
||||
}
|
||||
|
||||
const FontAtlas& FontCache::lookupAtlas(FontTag tag) const
|
||||
{
|
||||
auto search = m_cachedAtlases.find(tag);
|
||||
if (search == m_cachedAtlases.cend())
|
||||
Log.report(LogVisor::FatalError, "invalid font");
|
||||
return *search->second.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,164 @@
|
|||
#include "Specter/TextView.hpp"
|
||||
#include "utf8proc.h"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
static LogVisor::LogModule Log("Specter::TextView");
|
||||
|
||||
TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCache& fcache)
|
||||
{
|
||||
static const char* VS =
|
||||
"#version 330\n"
|
||||
"layout(location=0) in vec3 posIn;\n"
|
||||
"layout(location=1) in mat4 mvMtx;\n"
|
||||
"layout(location=5) in vec3 uvIn[4];\n"
|
||||
"layout(location=9) in vec4 colorIn;\n"
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" vec3 uv;\n"
|
||||
" vec4 color;\n"
|
||||
"};\n"
|
||||
"out VertToFrag vtf;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vtf.uv = uvIn[gl_VertexID];\n"
|
||||
" vtf.color = colorIn;\n"
|
||||
" gl_Position = mvMtx * vec4(posIn, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSReg =
|
||||
"#version 330\n"
|
||||
"uniform sampler2DArray fontTex;\n"
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" vec3 uv;\n"
|
||||
" vec4 color;\n"
|
||||
"};\n"
|
||||
"in VertToFrag vtf;\n"
|
||||
"layout(location=0) out vec4 colorOut;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" colorOut = vtf.color;\n"
|
||||
" colorOut.a = texture(fontTex, vtf.uv).r;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSSubpixel =
|
||||
"#version 330\n"
|
||||
"uniform sampler2DArray fontTex;\n"
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" vec3 uv;\n"
|
||||
" vec4 color;\n"
|
||||
"};\n"
|
||||
"in VertToFrag vtf;\n"
|
||||
"layout(location=0, index=0) out vec4 colorOut;\n"
|
||||
"layout(location=0, index=1) out vec4 blendOut;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" colorOut = vtf.color;\n"
|
||||
" blendOut = texture(fontTex, vtf.uv);\n"
|
||||
"}\n";
|
||||
|
||||
static float Quad[] =
|
||||
{
|
||||
0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
1.0, 1.0, 0.0,
|
||||
1.0, 0.0, 0.0,
|
||||
};
|
||||
|
||||
System ret(factory, fcache);
|
||||
|
||||
ret.m_regular =
|
||||
factory->newShaderPipeline(VS, FSReg, 1, "fontTex", 0, nullptr,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
true, true, false);
|
||||
|
||||
ret.m_subpixel =
|
||||
factory->newShaderPipeline(VS, FSSubpixel, 1, "fontTex", 0, nullptr,
|
||||
boo::BlendFactor::SrcColor1, boo::BlendFactor::InvSrcColor1,
|
||||
true, true, false);
|
||||
|
||||
ret.m_quadVBO =
|
||||
factory->newStaticBuffer(boo::BufferUse::Vertex, Quad, sizeof(Quad), 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
TextView::Shaders TextView::BuildTextSystem(boo::ID3DDataFactory* factory, FontCache& fcache)
|
||||
{
|
||||
}
|
||||
|
||||
#elif BOO_HAS_METAL
|
||||
TextView::Shaders TextView::BuildTextSystem(boo::MetalDataFactory* factory, FontCache& fcache)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
TextView::TextView(System& system, FontTag font, size_t initGlyphCapacity)
|
||||
: m_curGlyphCapacity(initGlyphCapacity),
|
||||
m_fontAtlas(system.m_fcache.lookupAtlas(font))
|
||||
{
|
||||
m_glyphBuf =
|
||||
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
||||
sizeof(RenderGlyph), initGlyphCapacity);
|
||||
|
||||
if (!system.m_vtxFmt)
|
||||
{
|
||||
boo::VertexElementDescriptor vdescs[] =
|
||||
{
|
||||
{system.m_quadVBO, nullptr, boo::VertexSemantic::Position},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 0},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 1},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 3},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
||||
};
|
||||
m_vtxFmt = system.m_factory->newVertexFormat(10, vdescs);
|
||||
}
|
||||
|
||||
m_glyphs.reserve(initGlyphCapacity);
|
||||
}
|
||||
|
||||
void TextView::typesetGlyphs(const std::string& str, Zeus::CColor defaultColor)
|
||||
{
|
||||
size_t rem = str.size();
|
||||
const utf8proc_uint8_t* it = str.data();
|
||||
while (rem)
|
||||
{
|
||||
utf8proc_int32_t ch;
|
||||
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
|
||||
if (sz < 0)
|
||||
Log.report(LogVisor::FatalError, "invalid UTF-8 char");
|
||||
|
||||
m_fontAtlas
|
||||
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
}
|
||||
}
|
||||
void TextView::typesetGlyphs(const std::wstring& str, Zeus::CColor defaultColor)
|
||||
{
|
||||
}
|
||||
|
||||
void TextView::colorGlyphs(Zeus::CColor newColor)
|
||||
{
|
||||
}
|
||||
void TextView::colorGlyphsTypeOn(Zeus::CColor newColor, float startInterval, float fadeTime)
|
||||
{
|
||||
}
|
||||
void TextView::think()
|
||||
{
|
||||
}
|
||||
|
||||
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue