mirror of https://github.com/AxioDL/metaforce.git
platform-sensitive system init
This commit is contained in:
parent
10c7d6e125
commit
d8921bbc5f
|
@ -31,6 +31,7 @@ include_directories(include ${HECL_INCLUDE_DIR} ${BOO_INCLUDE_DIR}
|
||||||
|
|
||||||
list(APPEND SPECTER_HEADERS
|
list(APPEND SPECTER_HEADERS
|
||||||
include/Specter/Specter.hpp
|
include/Specter/Specter.hpp
|
||||||
|
include/Specter/ViewSystem.hpp
|
||||||
include/Specter/View.hpp
|
include/Specter/View.hpp
|
||||||
include/Specter/RootView.hpp
|
include/Specter/RootView.hpp
|
||||||
include/Specter/TextView.hpp
|
include/Specter/TextView.hpp
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8d54a3c7b5d76e32d9fb3ad57619a680b32909b7
|
Subproject commit dc5c903a0dcabc57bdc7e83b3d037a2960e9bb73
|
|
@ -62,6 +62,7 @@ public:
|
||||||
{
|
{
|
||||||
atUint32 m_unicodePoint;
|
atUint32 m_unicodePoint;
|
||||||
atUint32 m_layerIdx;
|
atUint32 m_layerIdx;
|
||||||
|
float m_layerFloat;
|
||||||
float m_uv[4];
|
float m_uv[4];
|
||||||
atInt8 m_leftPadding;
|
atInt8 m_leftPadding;
|
||||||
atInt8 m_advance;
|
atInt8 m_advance;
|
||||||
|
@ -69,19 +70,38 @@ public:
|
||||||
atUint8 m_width;
|
atUint8 m_width;
|
||||||
atUint8 m_height;
|
atUint8 m_height;
|
||||||
atInt8 m_verticalOffset;
|
atInt8 m_verticalOffset;
|
||||||
atInt16 m_kernIdx = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KernAdj
|
|
||||||
{
|
|
||||||
atUint32 a;
|
|
||||||
atUint32 b;
|
|
||||||
atInt8 adj;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Glyph> m_glyphs;
|
std::vector<Glyph> m_glyphs;
|
||||||
std::vector<KernAdj> m_kernAdjs;
|
std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>> m_kernAdjs;
|
||||||
|
|
||||||
|
struct TT_KernHead : Athena::io::DNA<Athena::BigEndian>
|
||||||
|
{
|
||||||
|
DECL_DNA
|
||||||
|
Value<atUint32> length;
|
||||||
|
Value<atUint16> coverage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TT_KernSubHead : Athena::io::DNA<Athena::BigEndian>
|
||||||
|
{
|
||||||
|
DECL_DNA
|
||||||
|
Value<atUint16> nPairs;
|
||||||
|
Value<atUint16> searchRange;
|
||||||
|
Value<atUint16> entrySelector;
|
||||||
|
Value<atUint16> rangeShift;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TT_KernPair : Athena::io::DNA<Athena::BigEndian>
|
||||||
|
{
|
||||||
|
DECL_DNA
|
||||||
|
Value<atUint16> left;
|
||||||
|
Value<atUint16> right;
|
||||||
|
Value<atInt16> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
void buildKernTable(FT_Face face);
|
||||||
|
|
||||||
std::unordered_map<atUint32, size_t> m_glyphLookup;
|
std::unordered_map<atUint32, size_t> m_glyphLookup;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -93,6 +113,32 @@ public:
|
||||||
FontAtlas& operator=(const FontAtlas& other) = delete;
|
FontAtlas& operator=(const FontAtlas& other) = delete;
|
||||||
|
|
||||||
uint32_t dpi() const {return m_dpi;}
|
uint32_t dpi() const {return m_dpi;}
|
||||||
|
|
||||||
|
const Glyph* lookupGlyph(atUint32 charcode) const
|
||||||
|
{
|
||||||
|
auto search = m_glyphLookup.find(charcode);
|
||||||
|
if (search == m_glyphLookup.end())
|
||||||
|
return nullptr;
|
||||||
|
return &m_glyphs[search->second];
|
||||||
|
}
|
||||||
|
atInt16 lookupKern(atUint32 left, atUint32 right) const
|
||||||
|
{
|
||||||
|
auto leftSearch = m_glyphLookup.find(left);
|
||||||
|
if (leftSearch == m_glyphLookup.cend())
|
||||||
|
return 0;
|
||||||
|
size_t leftIdx = leftSearch->second;
|
||||||
|
auto rightSearch = m_glyphLookup.find(right);
|
||||||
|
if (rightSearch == m_glyphLookup.cend())
|
||||||
|
return 0;
|
||||||
|
size_t rightIdx = rightSearch->second;
|
||||||
|
auto pairSearch = m_kernAdjs.find(leftIdx);
|
||||||
|
if (pairSearch == m_kernAdjs.cend())
|
||||||
|
return 0;
|
||||||
|
for (const std::pair<atUint16, atInt16>& p : pairSearch->second)
|
||||||
|
if (p.first == rightIdx)
|
||||||
|
return p.second;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontCache
|
class FontCache
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
|
class ViewSystem;
|
||||||
|
|
||||||
class RootView : public View, public boo::IWindowCallback
|
class RootView : public View, public boo::IWindowCallback
|
||||||
{
|
{
|
||||||
FontCache& m_fontCache;
|
|
||||||
boo::IWindow* m_window = nullptr;
|
boo::IWindow* m_window = nullptr;
|
||||||
float m_scale = 1.0;
|
|
||||||
|
|
||||||
void resized(const boo::SWindowRect& rect);
|
void resized(const boo::SWindowRect& rect);
|
||||||
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
|
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
|
||||||
|
@ -36,8 +35,7 @@ class RootView : public View, public boo::IWindowCallback
|
||||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RootView(FontCache& fontCache) : m_fontCache(fontCache) {}
|
RootView(ViewSystem& system, boo::IWindow* window);
|
||||||
void setWindow(boo::IWindow* window, float userScale);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "View.hpp"
|
#include "View.hpp"
|
||||||
#include "RootView.hpp"
|
#include "RootView.hpp"
|
||||||
|
#include "TextView.hpp"
|
||||||
#include "Space.hpp"
|
#include "Space.hpp"
|
||||||
#include "Table.hpp"
|
#include "Table.hpp"
|
||||||
#include "Outliner.hpp"
|
#include "Outliner.hpp"
|
||||||
|
@ -15,5 +16,6 @@
|
||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
#include "NodeSocket.hpp"
|
#include "NodeSocket.hpp"
|
||||||
#include "FontCache.hpp"
|
#include "FontCache.hpp"
|
||||||
|
#include "ViewSystem.hpp"
|
||||||
|
|
||||||
#endif // SPECTER_HPP
|
#endif // SPECTER_HPP
|
||||||
|
|
|
@ -10,43 +10,42 @@
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
|
class ViewSystem;
|
||||||
|
|
||||||
class TextView : public View
|
class TextView : public View
|
||||||
{
|
{
|
||||||
boo::IGraphicsBufferD* m_glyphBuf;
|
boo::IGraphicsBufferD* m_glyphBuf;
|
||||||
int m_validDynamicSlots = 0;
|
|
||||||
size_t m_curGlyphCapacity;
|
|
||||||
const FontAtlas& m_fontAtlas;
|
const FontAtlas& m_fontAtlas;
|
||||||
boo::IVertexFormat* m_vtxFmt = nullptr; /* OpenGL only */
|
boo::IVertexFormat* m_bgVtxFmt = nullptr; /* OpenGL only */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class System
|
class System
|
||||||
{
|
{
|
||||||
|
friend class ViewSystem;
|
||||||
friend class TextView;
|
friend class TextView;
|
||||||
boo::IGraphicsDataFactory* m_factory;
|
FontCache* m_fcache = nullptr;
|
||||||
FontCache& m_fcache;
|
boo::IShaderPipeline* m_regular = nullptr;
|
||||||
boo::IShaderPipeline* m_regular;
|
boo::IShaderPipeline* m_subpixel = nullptr;
|
||||||
boo::IShaderPipeline* m_subpixel;
|
|
||||||
boo::IGraphicsBufferS* m_quadVBO;
|
|
||||||
boo::IVertexFormat* m_vtxFmt = nullptr; /* Not OpenGL */
|
boo::IVertexFormat* m_vtxFmt = nullptr; /* Not OpenGL */
|
||||||
|
|
||||||
System(boo::IGraphicsDataFactory* factory, FontCache& fcache)
|
void init(boo::GLDataFactory* factory, FontCache* fcache);
|
||||||
: m_factory(factory), m_fcache(fcache) {}
|
|
||||||
};
|
|
||||||
static System BuildTextSystem(boo::GLDataFactory* factory, FontCache& fcache);
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
static Shaders BuildTextSystem(boo::ID3DDataFactory* factory, FontCache& fcache);
|
void init(boo::ID3DDataFactory* factory, FontCache* fcache);
|
||||||
#elif BOO_HAS_METAL
|
#elif BOO_HAS_METAL
|
||||||
static Shaders BuildTextSystem(boo::MetalDataFactory* factory, FontCache& fcache);
|
void init(boo::MetalDataFactory* factory, FontCache* fcache);
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
TextView(System& system, FontTag font, size_t initGlyphCapacity=256);
|
TextView(ViewSystem& system, FontTag font, size_t initGlyphCapacity=256);
|
||||||
|
|
||||||
struct RenderGlyph
|
struct RenderGlyph
|
||||||
{
|
{
|
||||||
Zeus::CMatrix4f m_mvp;
|
Zeus::CVector3f m_pos[4];
|
||||||
|
Zeus::CMatrix4f m_mv;
|
||||||
Zeus::CVector3f m_uv[4];
|
Zeus::CVector3f m_uv[4];
|
||||||
Zeus::CColor m_color;
|
Zeus::CColor m_color;
|
||||||
|
|
||||||
|
RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, Zeus::CColor defaultColor);
|
||||||
};
|
};
|
||||||
std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;}
|
std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;}
|
||||||
void updateGlyphs() {m_validDynamicSlots = 0;}
|
void updateGlyphs() {m_validDynamicSlots = 0;}
|
||||||
|
|
|
@ -7,16 +7,59 @@
|
||||||
#include "CTransform.hpp"
|
#include "CTransform.hpp"
|
||||||
#include "CColor.hpp"
|
#include "CColor.hpp"
|
||||||
|
|
||||||
|
#include <boo/graphicsdev/GL.hpp>
|
||||||
|
#include <boo/graphicsdev/D3D.hpp>
|
||||||
|
#include <boo/graphicsdev/Metal.hpp>
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
|
class ViewSystem;
|
||||||
|
|
||||||
class View
|
class View
|
||||||
{
|
{
|
||||||
protected:
|
boo::IGraphicsBufferD* m_bgVertBuf;
|
||||||
boo::SWindowRect m_viewport;
|
boo::IGraphicsBufferD* m_bgInstBuf;
|
||||||
void bindViewport(boo::IGraphicsCommandQueue* gfxQ) {gfxQ->setViewport(m_viewport);}
|
boo::IVertexFormat* m_bgVtxFmt = nullptr; /* OpenGL only */
|
||||||
|
boo::IShaderDataBinding* m_bgShaderBinding;
|
||||||
|
Zeus::CVector3f m_bgRect[4];
|
||||||
|
Zeus::CColor m_bgColor;
|
||||||
public:
|
public:
|
||||||
virtual void draw(boo::IGraphicsCommandQueue* gfxQ)=0;
|
class System
|
||||||
|
{
|
||||||
|
friend class ViewSystem;
|
||||||
|
friend class View;
|
||||||
|
boo::IShaderPipeline* m_solidShader = nullptr;
|
||||||
|
boo::IVertexFormat* m_vtxFmt = nullptr; /* Not OpenGL */
|
||||||
|
|
||||||
|
void init(boo::GLDataFactory* factory);
|
||||||
|
#if _WIN32
|
||||||
|
void init(boo::ID3DDataFactory* factory);
|
||||||
|
#elif BOO_HAS_METAL
|
||||||
|
void init(boo::MetalDataFactory* factory);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexBlock
|
||||||
|
{
|
||||||
|
Zeus::CMatrix4f m_mv;
|
||||||
|
};
|
||||||
|
#define SPECTER_VIEW_VERT_BLOCK_GLSL\
|
||||||
|
"uniform SpecterViewBlock\n"\
|
||||||
|
"{\n"\
|
||||||
|
" mat4 mv;\n"\
|
||||||
|
"};\n"
|
||||||
|
|
||||||
|
protected:
|
||||||
|
View(ViewSystem& system);
|
||||||
|
int m_validDynamicSlots = 0;
|
||||||
|
boo::IGraphicsBufferD* m_specterVertBlock;
|
||||||
|
|
||||||
|
boo::SWindowRect m_absWindowRect;
|
||||||
|
void bindScissor(boo::IGraphicsCommandQueue* gfxQ) {gfxQ->setScissor(m_absWindowRect);}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setBackground(Zeus::CColor color) {m_bgColor = color; m_validDynamicSlots = 0;}
|
||||||
|
virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef SPECTER_VIEWSYSTEM_HPP
|
||||||
|
#define SPECTER_VIEWSYSTEM_HPP
|
||||||
|
|
||||||
|
#include "TextView.hpp"
|
||||||
|
|
||||||
|
namespace Specter
|
||||||
|
{
|
||||||
|
class ViewSystem
|
||||||
|
{
|
||||||
|
template <class Factory>
|
||||||
|
void init(Factory* factory, FontCache* fcache)
|
||||||
|
{
|
||||||
|
m_viewSystem.init(factory);
|
||||||
|
m_textSystem.init(factory, fcache);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
boo::IGraphicsDataFactory* m_factory = nullptr;
|
||||||
|
View::System m_viewSystem;
|
||||||
|
TextView::System m_textSystem;
|
||||||
|
|
||||||
|
ViewSystem() = default;
|
||||||
|
ViewSystem(const ViewSystem& other) = delete;
|
||||||
|
ViewSystem(ViewSystem&& other) = default;
|
||||||
|
ViewSystem& operator=(const ViewSystem& other) = delete;
|
||||||
|
ViewSystem& operator=(ViewSystem&& other) = default;
|
||||||
|
|
||||||
|
void init(boo::IGraphicsDataFactory* factory, FontCache* fcache);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPECTER_VIEWSYSTEM_HPP
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Specter/FontCache.hpp"
|
#include "Specter/FontCache.hpp"
|
||||||
#include <LogVisor/LogVisor.hpp>
|
#include <LogVisor/LogVisor.hpp>
|
||||||
|
#include <Athena/MemoryReader.hpp>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include FT_GZIP_H
|
#include FT_GZIP_H
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
#include FT_OUTLINE_H
|
#include FT_OUTLINE_H
|
||||||
#include <freetype/internal/internal.h>
|
#include <freetype/internal/internal.h>
|
||||||
#include <freetype/internal/ftstream.h>
|
#include <freetype/internal/ftstream.h>
|
||||||
|
#include <freetype/internal/tttypes.h>
|
||||||
|
|
||||||
extern "C" const uint8_t DROIDSANS_PERMISSIVE[];
|
extern "C" const uint8_t DROIDSANS_PERMISSIVE[];
|
||||||
extern "C" size_t DROIDSANS_PERMISSIVE_SZ;
|
extern "C" size_t DROIDSANS_PERMISSIVE_SZ;
|
||||||
|
@ -14,6 +16,8 @@ extern "C" size_t DROIDSANS_PERMISSIVE_SZ;
|
||||||
extern "C" const uint8_t BMONOFONT[];
|
extern "C" const uint8_t BMONOFONT[];
|
||||||
extern "C" size_t BMONOFONT_SZ;
|
extern "C" size_t BMONOFONT_SZ;
|
||||||
|
|
||||||
|
extern const FT_Driver_ClassRec tt_driver_class;
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
static LogVisor::LogModule Log("Specter::FontCache");
|
static LogVisor::LogModule Log("Specter::FontCache");
|
||||||
|
@ -121,6 +125,40 @@ static inline void GridFitGlyph(FT_GlyphSlot slot, FT_UInt& width, FT_UInt& heig
|
||||||
height = slot->metrics.height >> 6;
|
height = slot->metrics.height >> 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FontAtlas::buildKernTable(FT_Face face)
|
||||||
|
{
|
||||||
|
if (face->driver->clazz == &tt_driver_class)
|
||||||
|
{
|
||||||
|
TT_Face ttface = reinterpret_cast<TT_Face>(face);
|
||||||
|
Athena::io::MemoryReader r(ttface->kern_table, ttface->kern_table_size);
|
||||||
|
std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>>::iterator it = m_kernAdjs.end();
|
||||||
|
atUint32 nSubs = r.readUint32Big();
|
||||||
|
for (atUint32 i=0 ; i<nSubs ; ++i)
|
||||||
|
{
|
||||||
|
TT_KernHead kernHead;
|
||||||
|
kernHead.read(r);
|
||||||
|
if (kernHead.coverage >> 8 != 0)
|
||||||
|
{
|
||||||
|
r.seek(kernHead.length - 6, Athena::Current);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_KernSubHead subHead;
|
||||||
|
subHead.read(r);
|
||||||
|
|
||||||
|
for (atUint16 p=0 ; p<subHead.nPairs ; ++p)
|
||||||
|
{
|
||||||
|
TT_KernPair pair;
|
||||||
|
pair.read(r);
|
||||||
|
if (it == m_kernAdjs.end() || it->first != pair.left)
|
||||||
|
if ((it = m_kernAdjs.find(pair.left)) == m_kernAdjs.end())
|
||||||
|
it = m_kernAdjs.insert(std::make_pair(pair.left, std::vector<std::pair<atUint16, atInt16>>())).first;
|
||||||
|
it->second.emplace_back(pair.right, pair.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
bool subpixel, Athena::io::FileWriter& writer)
|
bool subpixel, Athena::io::FileWriter& writer)
|
||||||
: m_dpi(dpi)
|
: m_dpi(dpi)
|
||||||
|
@ -207,6 +245,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
Glyph& g = m_glyphs.back();
|
Glyph& g = m_glyphs.back();
|
||||||
g.m_unicodePoint = charcode;
|
g.m_unicodePoint = charcode;
|
||||||
g.m_layerIdx = fullTexmapLayers;
|
g.m_layerIdx = fullTexmapLayers;
|
||||||
|
g.m_layerFloat = float(g.m_layerIdx);
|
||||||
g.m_width = face->glyph->bitmap.width / 3;
|
g.m_width = face->glyph->bitmap.width / 3;
|
||||||
g.m_height = face->glyph->bitmap.rows;
|
g.m_height = face->glyph->bitmap.rows;
|
||||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||||
|
@ -217,7 +256,6 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
g.m_advance = face->glyph->advance.x;
|
g.m_advance = face->glyph->advance.x;
|
||||||
g.m_rightPadding = 0;
|
g.m_rightPadding = 0;
|
||||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY / 64;
|
g.m_verticalOffset = face->glyph->metrics.horiBearingY / 64;
|
||||||
g.m_kernIdx = 0;
|
|
||||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||||
{
|
{
|
||||||
totalHeight += curLineHeight + 1;
|
totalHeight += curLineHeight + 1;
|
||||||
|
@ -278,6 +316,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
Glyph& g = m_glyphs.back();
|
Glyph& g = m_glyphs.back();
|
||||||
g.m_unicodePoint = charcode;
|
g.m_unicodePoint = charcode;
|
||||||
g.m_layerIdx = fullTexmapLayers;
|
g.m_layerIdx = fullTexmapLayers;
|
||||||
|
g.m_layerFloat = float(g.m_layerIdx);
|
||||||
g.m_width = face->glyph->bitmap.width;
|
g.m_width = face->glyph->bitmap.width;
|
||||||
g.m_height = face->glyph->bitmap.rows;
|
g.m_height = face->glyph->bitmap.rows;
|
||||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||||
|
@ -288,7 +327,6 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
g.m_advance = face->glyph->advance.x;
|
g.m_advance = face->glyph->advance.x;
|
||||||
g.m_rightPadding = 0;
|
g.m_rightPadding = 0;
|
||||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY >> 6;
|
g.m_verticalOffset = face->glyph->metrics.horiBearingY >> 6;
|
||||||
g.m_kernIdx = 0;
|
|
||||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||||
{
|
{
|
||||||
totalHeight += curLineHeight + 1;
|
totalHeight += curLineHeight + 1;
|
||||||
|
@ -314,6 +352,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
||||||
boo::TextureFormat::I8, texmap.get(), bufSz);
|
boo::TextureFormat::I8, texmap.get(), bufSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildKernTable(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
|
@ -378,6 +418,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
Glyph& g = m_glyphs.back();
|
Glyph& g = m_glyphs.back();
|
||||||
g.m_unicodePoint = charcode;
|
g.m_unicodePoint = charcode;
|
||||||
g.m_layerIdx = fullTexmapLayers;
|
g.m_layerIdx = fullTexmapLayers;
|
||||||
|
g.m_layerFloat = float(g.m_layerIdx);
|
||||||
g.m_width = width;
|
g.m_width = width;
|
||||||
g.m_height = height;
|
g.m_height = height;
|
||||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||||
|
@ -388,7 +429,6 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
g.m_advance = face->glyph->advance.x;
|
g.m_advance = face->glyph->advance.x;
|
||||||
g.m_rightPadding = 0;
|
g.m_rightPadding = 0;
|
||||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY / 64;
|
g.m_verticalOffset = face->glyph->metrics.horiBearingY / 64;
|
||||||
g.m_kernIdx = 0;
|
|
||||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||||
{
|
{
|
||||||
totalHeight += curLineHeight + 1;
|
totalHeight += curLineHeight + 1;
|
||||||
|
@ -428,8 +468,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t count = TEXMAP_DIM * totalHeight;
|
size_t count = TEXMAP_DIM * finalHeight;
|
||||||
texmap.reset(new GreyPixel[TEXMAP_DIM * totalHeight]);
|
texmap.reset(new GreyPixel[TEXMAP_DIM * finalHeight]);
|
||||||
bufSz = count * sizeof(GreyPixel);
|
bufSz = count * sizeof(GreyPixel);
|
||||||
memset(texmap.get(), 0, bufSz);
|
memset(texmap.get(), 0, bufSz);
|
||||||
}
|
}
|
||||||
|
@ -449,6 +489,7 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
Glyph& g = m_glyphs.back();
|
Glyph& g = m_glyphs.back();
|
||||||
g.m_unicodePoint = charcode;
|
g.m_unicodePoint = charcode;
|
||||||
g.m_layerIdx = fullTexmapLayers;
|
g.m_layerIdx = fullTexmapLayers;
|
||||||
|
g.m_layerFloat = float(g.m_layerIdx);
|
||||||
g.m_width = width;
|
g.m_width = width;
|
||||||
g.m_height = height;
|
g.m_height = height;
|
||||||
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
g.m_uv[0] = curLineWidth / float(TEXMAP_DIM);
|
||||||
|
@ -459,7 +500,6 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
g.m_advance = face->glyph->advance.x;
|
g.m_advance = face->glyph->advance.x;
|
||||||
g.m_rightPadding = 0;
|
g.m_rightPadding = 0;
|
||||||
g.m_verticalOffset = face->glyph->metrics.horiBearingY >> 6;
|
g.m_verticalOffset = face->glyph->metrics.horiBearingY >> 6;
|
||||||
g.m_kernIdx = 0;
|
|
||||||
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
if (curLineWidth + g.m_width + 1 > TEXMAP_DIM)
|
||||||
{
|
{
|
||||||
totalHeight += curLineHeight + 1;
|
totalHeight += curLineHeight + 1;
|
||||||
|
@ -484,6 +524,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||||
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
|
||||||
boo::TextureFormat::I8, texmap.get(), bufSz);
|
boo::TextureFormat::I8, texmap.get(), bufSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildKernTable(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontCache::Library::Library()
|
FontCache::Library::Library()
|
||||||
|
@ -513,7 +555,7 @@ FontTag FontCache::prepCustomFont(boo::IGraphicsDataFactory* gf,
|
||||||
if (!face)
|
if (!face)
|
||||||
Log.report(LogVisor::FatalError, "invalid freetype face");
|
Log.report(LogVisor::FatalError, "invalid freetype face");
|
||||||
|
|
||||||
if (!face->charmap || face->charmap->encoding != ft_encoding_unicode)
|
if (!face->charmap || face->charmap->encoding != FT_ENCODING_UNICODE)
|
||||||
Log.report(LogVisor::FatalError, "font does not contain a unicode char map");
|
Log.report(LogVisor::FatalError, "font does not contain a unicode char map");
|
||||||
|
|
||||||
/* Set size with FreeType */
|
/* Set size with FreeType */
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
|
|
||||||
void RootView::setWindow(boo::IWindow* window, float userScale)
|
RootView::RootView(ViewSystem& system, boo::IWindow* window)
|
||||||
|
: View(system), m_window(window)
|
||||||
{
|
{
|
||||||
window->setCallback(this);
|
|
||||||
m_window = window;
|
|
||||||
m_scale = window->getVirtualPixelFactor() * userScale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootView::resized(const boo::SWindowRect& rect)
|
void RootView::resized(const boo::SWindowRect& rect)
|
||||||
|
@ -76,6 +75,7 @@ void RootView::modKeyUp(boo::EModifierKey mod)
|
||||||
|
|
||||||
void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||||
{
|
{
|
||||||
|
View::draw(gfxQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include "Specter/ViewSystem.hpp"
|
||||||
|
|
||||||
|
namespace Specter
|
||||||
|
{
|
||||||
|
static LogVisor::LogModule Log("Specter");
|
||||||
|
|
||||||
|
void ViewSystem::init(boo::IGraphicsDataFactory* factory, FontCache* fcache)
|
||||||
|
{
|
||||||
|
m_factory = factory;
|
||||||
|
switch (factory->platform())
|
||||||
|
{
|
||||||
|
case boo::IGraphicsDataFactory::Platform::OGL:
|
||||||
|
init<boo::GLDataFactory>(static_cast<boo::GLDataFactory*>(factory), fcache);
|
||||||
|
break;
|
||||||
|
#if _WIN32
|
||||||
|
case boo::IGraphicsDataFactory::Platform::D3D11:
|
||||||
|
case boo::IGraphicsDataFactory::Platform::D3D12:
|
||||||
|
init<boo::ID3DDataFactory>(static_cast<boo::ID3DDataFactory*>(factory), fcache);
|
||||||
|
break;
|
||||||
|
#elif BOO_HAS_METAL
|
||||||
|
case boo::IGraphicsDataFactory::Platform::Metal:
|
||||||
|
init<boo::MetalDataFactory>(static_cast<boo::MetalDataFactory*>(factory), fcache);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
Log.report(LogVisor::FatalError, _S("unable to init view system for %s"), factory->platformName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,22 @@
|
||||||
#include "Specter/TextView.hpp"
|
#include "Specter/TextView.hpp"
|
||||||
|
#include "Specter/ViewSystem.hpp"
|
||||||
#include "utf8proc.h"
|
#include "utf8proc.h"
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
static LogVisor::LogModule Log("Specter::TextView");
|
static LogVisor::LogModule Log("Specter::TextView");
|
||||||
|
|
||||||
TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCache& fcache)
|
void TextView::System::init(boo::GLDataFactory* factory, FontCache* fcache)
|
||||||
{
|
{
|
||||||
|
m_fcache = fcache;
|
||||||
|
|
||||||
static const char* VS =
|
static const char* VS =
|
||||||
"#version 330\n"
|
"#version 330\n"
|
||||||
"layout(location=0) in vec3 posIn;\n"
|
"layout(location=0) in vec3 posIn[4];\n"
|
||||||
"layout(location=1) in mat4 mvMtx;\n"
|
"layout(location=4) in mat4 mvMtx;\n"
|
||||||
"layout(location=5) in vec3 uvIn[4];\n"
|
"layout(location=8) in vec3 uvIn[4];\n"
|
||||||
"layout(location=9) in vec4 colorIn;\n"
|
"layout(location=12) in vec4 colorIn;\n"
|
||||||
|
SPECTER_VIEW_VERT_BLOCK_GLSL
|
||||||
"struct VertToFrag\n"
|
"struct VertToFrag\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" vec3 uv;\n"
|
" vec3 uv;\n"
|
||||||
|
@ -23,7 +27,7 @@ TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCach
|
||||||
"{\n"
|
"{\n"
|
||||||
" vtf.uv = uvIn[gl_VertexID];\n"
|
" vtf.uv = uvIn[gl_VertexID];\n"
|
||||||
" vtf.color = colorIn;\n"
|
" vtf.color = colorIn;\n"
|
||||||
" gl_Position = mvMtx * vec4(posIn, 1.0);\n"
|
" gl_Position = mv * mvMtx * vec4(posIn[gl_VertexID], 1.0);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
static const char* FSReg =
|
static const char* FSReg =
|
||||||
|
@ -59,56 +63,35 @@ TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCach
|
||||||
" blendOut = texture(fontTex, vtf.uv);\n"
|
" blendOut = texture(fontTex, vtf.uv);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
static float Quad[] =
|
static const char* BlockNames[] = {"SpecterViewBlock"};
|
||||||
{
|
|
||||||
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);
|
m_regular =
|
||||||
|
factory->newShaderPipeline(VS, FSReg, 1, "fontTex", 1, BlockNames,
|
||||||
ret.m_regular =
|
|
||||||
factory->newShaderPipeline(VS, FSReg, 1, "fontTex", 0, nullptr,
|
|
||||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||||
true, true, false);
|
true, true, false);
|
||||||
|
|
||||||
ret.m_subpixel =
|
m_subpixel =
|
||||||
factory->newShaderPipeline(VS, FSSubpixel, 1, "fontTex", 0, nullptr,
|
factory->newShaderPipeline(VS, FSSubpixel, 1, "fontTex", 1, BlockNames,
|
||||||
boo::BlendFactor::SrcColor1, boo::BlendFactor::InvSrcColor1,
|
boo::BlendFactor::SrcColor1, boo::BlendFactor::InvSrcColor1,
|
||||||
true, true, false);
|
true, true, false);
|
||||||
|
|
||||||
ret.m_quadVBO =
|
|
||||||
factory->newStaticBuffer(boo::BufferUse::Vertex, Quad, sizeof(Quad), 1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _WIN32
|
TextView::TextView(ViewSystem& system, FontTag font, size_t initGlyphCapacity)
|
||||||
TextView::Shaders TextView::BuildTextSystem(boo::ID3DDataFactory* factory, FontCache& fcache)
|
: View(system),
|
||||||
{
|
m_fontAtlas(system.m_textSystem.m_fcache->lookupAtlas(font))
|
||||||
}
|
|
||||||
|
|
||||||
#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 =
|
m_glyphBuf =
|
||||||
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
||||||
sizeof(RenderGlyph), initGlyphCapacity);
|
sizeof(RenderGlyph), initGlyphCapacity);
|
||||||
|
|
||||||
if (!system.m_vtxFmt)
|
if (!system.m_textSystem.m_vtxFmt)
|
||||||
{
|
{
|
||||||
boo::VertexElementDescriptor vdescs[] =
|
boo::VertexElementDescriptor vdescs[] =
|
||||||
{
|
{
|
||||||
{system.m_quadVBO, nullptr, boo::VertexSemantic::Position},
|
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
|
||||||
|
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
|
||||||
|
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
|
||||||
|
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
|
||||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 0},
|
{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, 1},
|
||||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
||||||
|
@ -119,31 +102,95 @@ TextView::TextView(System& system, FontTag font, size_t initGlyphCapacity)
|
||||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
||||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
{m_glyphBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
||||||
};
|
};
|
||||||
m_vtxFmt = system.m_factory->newVertexFormat(10, vdescs);
|
m_bgVtxFmt = system.m_factory->newVertexFormat(13, vdescs);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_glyphs.reserve(initGlyphCapacity);
|
m_glyphs.reserve(initGlyphCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, Zeus::CColor defaultColor)
|
||||||
|
{
|
||||||
|
m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f);
|
||||||
|
m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f);
|
||||||
|
m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f);
|
||||||
|
m_pos[3].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset, 0.f);
|
||||||
|
m_uv[0].assign(glyph.m_uv[0], glyph.m_uv[1], glyph.m_layerFloat);
|
||||||
|
m_uv[1].assign(glyph.m_uv[0], glyph.m_uv[3], glyph.m_layerFloat);
|
||||||
|
m_uv[2].assign(glyph.m_uv[2], glyph.m_uv[1], glyph.m_layerFloat);
|
||||||
|
m_uv[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat);
|
||||||
|
m_color = defaultColor;
|
||||||
|
adv += glyph.m_advance;
|
||||||
|
}
|
||||||
|
|
||||||
void TextView::typesetGlyphs(const std::string& str, Zeus::CColor defaultColor)
|
void TextView::typesetGlyphs(const std::string& str, Zeus::CColor defaultColor)
|
||||||
{
|
{
|
||||||
size_t rem = str.size();
|
size_t rem = str.size();
|
||||||
const utf8proc_uint8_t* it = str.data();
|
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
|
||||||
|
utf8proc_int32_t lCh = -1;
|
||||||
|
m_glyphs.clear();
|
||||||
|
m_glyphs.reserve(str.size());
|
||||||
|
int adv = 0;
|
||||||
|
|
||||||
while (rem)
|
while (rem)
|
||||||
{
|
{
|
||||||
utf8proc_int32_t ch;
|
utf8proc_int32_t ch;
|
||||||
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
|
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
Log.report(LogVisor::FatalError, "invalid UTF-8 char");
|
Log.report(LogVisor::FatalError, "invalid UTF-8 char");
|
||||||
|
if (ch == '\n')
|
||||||
|
break;
|
||||||
|
|
||||||
m_fontAtlas
|
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||||
|
if (!glyph)
|
||||||
|
{
|
||||||
|
rem -= sz;
|
||||||
|
it += sz;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lCh != -1)
|
||||||
|
{
|
||||||
|
adv += m_fontAtlas.lookupKern(lCh, ch);
|
||||||
|
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||||
|
|
||||||
|
lCh = ch;
|
||||||
rem -= sz;
|
rem -= sz;
|
||||||
it += sz;
|
it += sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_validDynamicSlots = 0;
|
||||||
}
|
}
|
||||||
void TextView::typesetGlyphs(const std::wstring& str, Zeus::CColor defaultColor)
|
void TextView::typesetGlyphs(const std::wstring& str, Zeus::CColor defaultColor)
|
||||||
{
|
{
|
||||||
|
wchar_t lCh = -1;
|
||||||
|
m_glyphs.clear();
|
||||||
|
m_glyphs.reserve(str.size());
|
||||||
|
int adv = 0;
|
||||||
|
|
||||||
|
for (wchar_t ch : str)
|
||||||
|
{
|
||||||
|
if (ch == L'\n')
|
||||||
|
break;
|
||||||
|
|
||||||
|
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||||
|
if (!glyph)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lCh != -1)
|
||||||
|
{
|
||||||
|
adv += m_fontAtlas.lookupKern(lCh, ch);
|
||||||
|
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||||
|
|
||||||
|
lCh = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_validDynamicSlots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextView::colorGlyphs(Zeus::CColor newColor)
|
void TextView::colorGlyphs(Zeus::CColor newColor)
|
||||||
|
@ -158,6 +205,14 @@ void TextView::think()
|
||||||
|
|
||||||
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||||
{
|
{
|
||||||
|
bindScissor(gfxQ);
|
||||||
|
int pendingSlot = 1 << gfxQ->pendingDynamicSlot();
|
||||||
|
if ((m_validDynamicSlots & pendingSlot) == 0)
|
||||||
|
{
|
||||||
|
m_glyphBuf->load(m_glyphs.data(), m_glyphs.size() * sizeof(RenderGlyph));
|
||||||
|
m_validDynamicSlots |= pendingSlot;
|
||||||
|
}
|
||||||
|
gfxQ->drawInstances(0, 4, m_glyphs.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,89 @@
|
||||||
#include "Specter/View.hpp"
|
#include "Specter/View.hpp"
|
||||||
|
#include "Specter/ViewSystem.hpp"
|
||||||
|
|
||||||
namespace Specter
|
namespace Specter
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void View::System::init(boo::GLDataFactory* factory)
|
||||||
|
{
|
||||||
|
static const char* VS =
|
||||||
|
"#version 330\n"
|
||||||
|
"layout(location=0) in vec3 posIn;\n"
|
||||||
|
"layout(location=1) in vec4 colorIn;\n"
|
||||||
|
SPECTER_VIEW_VERT_BLOCK_GLSL
|
||||||
|
"struct VertToFrag\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
"};\n"
|
||||||
|
"out VertToFrag vtf;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vtf.color = colorIn;\n"
|
||||||
|
" gl_Position = mv * vec4(posIn[gl_VertexID], 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* FS =
|
||||||
|
"#version 330\n"
|
||||||
|
"struct VertToFrag\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
"};\n"
|
||||||
|
"in VertToFrag vtf;\n"
|
||||||
|
"layout(location=0) out vec4 colorOut;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" colorOut = vtf.color;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* BlockNames[] = {"SpecterViewBlock"};
|
||||||
|
|
||||||
|
m_solidShader = factory->newShaderPipeline(VS, FS, 0, nullptr, 1, BlockNames,
|
||||||
|
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||||
|
false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
View::View(ViewSystem& system)
|
||||||
|
{
|
||||||
|
m_bgVertBuf =
|
||||||
|
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
||||||
|
sizeof(Zeus::CVector3f), 4);
|
||||||
|
|
||||||
|
m_bgInstBuf =
|
||||||
|
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
||||||
|
sizeof(Zeus::CColor), 1);
|
||||||
|
|
||||||
|
m_specterVertBlock =
|
||||||
|
system.m_factory->newDynamicBuffer(boo::BufferUse::Uniform,
|
||||||
|
sizeof(VertexBlock), 1);
|
||||||
|
|
||||||
|
if (!system.m_viewSystem.m_vtxFmt)
|
||||||
|
{
|
||||||
|
boo::VertexElementDescriptor vdescs[] =
|
||||||
|
{
|
||||||
|
{m_bgVertBuf, nullptr, boo::VertexSemantic::Position4, 0},
|
||||||
|
{m_bgInstBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
||||||
|
};
|
||||||
|
m_bgVtxFmt = system.m_factory->newVertexFormat(2, vdescs);
|
||||||
|
m_bgShaderBinding =
|
||||||
|
system.m_factory->newShaderDataBinding(system.m_viewSystem.m_solidShader, m_bgVtxFmt,
|
||||||
|
m_bgVertBuf, m_bgInstBuf, nullptr, 1,
|
||||||
|
(boo::IGraphicsBuffer**)&m_specterVertBlock,
|
||||||
|
0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||||
|
{
|
||||||
|
bindScissor(gfxQ);
|
||||||
|
int pendingSlot = 1 << gfxQ->pendingDynamicSlot();
|
||||||
|
if ((m_validDynamicSlots & pendingSlot) == 0)
|
||||||
|
{
|
||||||
|
m_bgVertBuf->load(m_bgRect, sizeof(Zeus::CVector3f) * 4);
|
||||||
|
m_bgInstBuf->load(&m_bgColor, sizeof(Zeus::CColor));
|
||||||
|
m_validDynamicSlots |= pendingSlot;
|
||||||
|
}
|
||||||
|
gfxQ->draw(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue