Convert CTextSupportShader; CTextRenderBuffer updates

This commit is contained in:
Luke Street 2020-10-04 02:47:43 -04:00
parent 35f33333a5
commit 3c9816af12
6 changed files with 203 additions and 159 deletions

View File

@ -50,20 +50,17 @@ runtime_add_list(Graphics GRAPHICS_SOURCES)
runtime_add_hsh(Graphics runtime_add_hsh(Graphics
CMoviePlayer.cpp CMoviePlayer.cpp
Shaders/CLineRendererShaders.cpp
Shaders/CColoredQuadFilter.cpp
Shaders/CTexturedQuadFilter.cpp
Shaders/CCameraBlurFilter.cpp
Shaders/CFogVolumePlaneShader.cpp
Shaders/CAABoxShader.cpp Shaders/CAABoxShader.cpp
Shaders/CCameraBlurFilter.cpp
Shaders/CColoredQuadFilter.cpp
Shaders/CColoredStripShader.cpp Shaders/CColoredStripShader.cpp
Shaders/CDecalShaders.cpp Shaders/CDecalShaders.cpp
Shaders/CEnergyBarShader.cpp
Shaders/CThermalColdFilter.cpp
Shaders/CThermalHotFilter.cpp
Shaders/CElementGenShaders.cpp Shaders/CElementGenShaders.cpp
Shaders/CEnergyBarShader.cpp
Shaders/CEnvFxShaders.cpp Shaders/CEnvFxShaders.cpp
Shaders/CFogVolumeFilter.cpp Shaders/CFogVolumeFilter.cpp
Shaders/CFogVolumePlaneShader.cpp
Shaders/CLineRendererShaders.cpp
Shaders/CMapSurfaceShader.cpp Shaders/CMapSurfaceShader.cpp
Shaders/CParticleSwooshShaders.cpp Shaders/CParticleSwooshShaders.cpp
Shaders/CPhazonSuitFilter.cpp Shaders/CPhazonSuitFilter.cpp
@ -71,6 +68,10 @@ runtime_add_hsh(Graphics
Shaders/CRandomStaticFilter.cpp Shaders/CRandomStaticFilter.cpp
Shaders/CScanLinesFilter.cpp Shaders/CScanLinesFilter.cpp
Shaders/CSpaceWarpFilter.cpp Shaders/CSpaceWarpFilter.cpp
Shaders/CXRayBlurFilter.cpp Shaders/CTextSupportShader.cpp
Shaders/CTexturedQuadFilter.cpp
Shaders/CThermalColdFilter.cpp
Shaders/CThermalHotFilter.cpp
Shaders/CWorldShadowShader.cpp Shaders/CWorldShadowShader.cpp
Shaders/CXRayBlurFilter.cpp
) )

View File

@ -1,45 +1,142 @@
#include "Runtime/Graphics/Shaders/CTextSupportShader.hpp" #include "Runtime/Graphics/Shaders/CTextSupportShader.hpp"
#include "hsh/hsh.h"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/GuiSys/CFontImageDef.hpp" #include "Runtime/GuiSys/CFontImageDef.hpp"
#include "Runtime/GuiSys/CRasterFont.hpp" #include "Runtime/GuiSys/CRasterFont.hpp"
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
#include "CTextSupportShader.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
constexpr hsh::sampler ClampEdgeSamp(hsh::Linear, hsh::Linear, hsh::Linear, hsh::ClampToEdge, hsh::ClampToEdge,
hsh::ClampToEdge);
template <CGuiWidget::EGuiModelDrawFlags Flags>
struct DrawFlagsAttachmentExt {
using type = BlendAttachment<>;
};
template <>
struct DrawFlagsAttachmentExt<CGuiWidget::EGuiModelDrawFlags::Additive> {
using type = AdditiveAttachment<>;
};
template <>
struct DrawFlagsAttachmentExt<CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw> {
using type = color_attachment<hsh::One, hsh::One, hsh::Add, hsh::One, hsh::One, hsh::Add,
hsh::ColorComponentFlags(hsh::CC_Red | hsh::CC_Green | hsh::CC_Blue)>;
};
template <CGuiWidget::EGuiModelDrawFlags Flags>
using DrawFlagsAttachment = typename DrawFlagsAttachmentExt<Flags>::type;
template <CGuiWidget::EGuiModelDrawFlags Flags>
struct CTextSupportShaderCharacterPipeline
: pipeline<topology<hsh::TriangleStrip>, DrawFlagsAttachment<Flags>, depth_write<false>, depth_compare<hsh::LEqual>> {
CTextSupportShaderCharacterPipeline(hsh::vertex_buffer<CTextSupportShader::CharacterInstance> vbo,
hsh::uniform_buffer<CTextSupportShader::Uniform> ubo, hsh::texture2d_array tex) {
this->position = ubo->m_mvp * hsh::float4(vbo->m_pos[this->vertex_id], 1.f);
hsh::float4 fontColor = ubo->m_uniformColor * vbo->m_fontColor;
hsh::float4 outlineColor = ubo->m_uniformColor * vbo->m_outlineColor;
hsh::float4 texel = tex.sample<float>(vbo->m_uv[this->vertex_id]);
this->color_out[0] = (fontColor * texel.x + outlineColor * texel.y) * vbo->m_mulColor;
}
};
template struct CTextSupportShaderCharacterPipeline<CGuiWidget::EGuiModelDrawFlags::Alpha>;
template struct CTextSupportShaderCharacterPipeline<CGuiWidget::EGuiModelDrawFlags::Additive>;
template struct CTextSupportShaderCharacterPipeline<CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw>;
template <CGuiWidget::EGuiModelDrawFlags Flags>
struct CTextSupportShaderImagePipeline
: pipeline<topology<hsh::TriangleStrip>, DrawFlagsAttachment<Flags>, depth_write<false>, depth_compare<hsh::LEqual>> {
CTextSupportShaderImagePipeline(hsh::vertex_buffer<CTextSupportShader::ImageInstance> vbo,
hsh::uniform_buffer<CTextSupportShader::Uniform> ubo, hsh::texture2d tex) {
this->position = ubo->m_mvp * hsh::float4(vbo->m_pos[this->vertex_id], 1.f);
// FIXME hsh bug: sampler appears to be completely ignored
hsh::float4 texel = tex.sample<float>(vbo->m_uv[this->vertex_id], ClampEdgeSamp);
this->color_out[0] = ubo->m_uniformColor * vbo->m_color * texel;
}
};
template struct CTextSupportShaderImagePipeline<CGuiWidget::EGuiModelDrawFlags::Alpha>;
template struct CTextSupportShaderImagePipeline<CGuiWidget::EGuiModelDrawFlags::Additive>;
template struct CTextSupportShaderImagePipeline<CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw>;
void CTextSupportShader::CharacterInstance::SetMetrics(const CGlyph& glyph, const zeus::CVector2i& offset) { void CTextSupportShader::CharacterInstance::SetMetrics(const CGlyph& glyph, const zeus::CVector2i& offset) {
float layer = glyph.GetLayer(); float layer = glyph.GetLayer();
m_pos[0].assign(offset.x, 0.f, offset.y); m_pos[0] = {float(offset.x), 0.f, float(offset.y)};
m_uv[0].assign(glyph.GetStartU(), 1.f - glyph.GetStartV(), layer); m_uv[0] = {glyph.GetStartU(), 1.f - glyph.GetStartV(), layer};
m_pos[1].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y); m_pos[1] = {float(offset.x + glyph.GetCellWidth()), 0.f, float(offset.y)};
m_uv[1].assign(glyph.GetEndU(), 1.f - glyph.GetStartV(), layer); m_uv[1] = {glyph.GetEndU(), 1.f - glyph.GetStartV(), layer};
m_pos[2].assign(offset.x, 0.f, offset.y + glyph.GetCellHeight()); m_pos[2] = {float(offset.x), 0.f, float(offset.y + glyph.GetCellHeight())};
m_uv[2].assign(glyph.GetStartU(), 1.f - glyph.GetEndV(), layer); m_uv[2] = {glyph.GetStartU(), 1.f - glyph.GetEndV(), layer};
m_pos[3].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y + glyph.GetCellHeight()); m_pos[3] = {float(offset.x + glyph.GetCellWidth()), 0.f, float(offset.y + glyph.GetCellHeight())};
m_uv[3].assign(glyph.GetEndU(), 1.f - glyph.GetEndV(), layer); m_uv[3] = {glyph.GetEndU(), 1.f - glyph.GetEndV(), layer};
} }
void CTextSupportShader::ImageInstance::SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset) { void CTextSupportShader::ImageInstance::SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset) {
zeus::CVector2f imgSize; zeus::CVector2f imgSize;
if (imgDef.x4_texs.size()) { if (!imgDef.x4_texs.empty()) {
const CTexture& tex = *imgDef.x4_texs[0].GetObj(); const CTexture& tex = *imgDef.x4_texs[0].GetObj();
imgSize.assign(tex.GetWidth() * imgDef.x14_cropFactor.x(), tex.GetHeight() * imgDef.x14_cropFactor.y()); imgSize = {tex.GetWidth() * imgDef.x14_cropFactor.x(), tex.GetHeight() * imgDef.x14_cropFactor.y()};
} }
zeus::CVector2f cropPad = imgDef.x14_cropFactor * 0.5f; zeus::CVector2f cropPad = imgDef.x14_cropFactor * 0.5f;
m_pos[0].assign(offset.x, 0.f, offset.y); m_pos[0] = {float(offset.x), 0.f, float(offset.y)};
m_uv[0].assign(0.5f - cropPad.x(), 0.5f + cropPad.y()); m_uv[0] = {0.5f - cropPad.x(), 0.5f + cropPad.y()};
m_pos[1].assign(offset.x + imgSize.x(), 0.f, offset.y); m_pos[1] = {offset.x + imgSize.x(), 0.f, float(offset.y)};
m_uv[1].assign(0.5f + cropPad.x(), 0.5f + cropPad.y()); m_uv[1] = {0.5f + cropPad.x(), 0.5f + cropPad.y()};
m_pos[2].assign(offset.x, 0.f, offset.y + imgSize.y()); m_pos[2] = {float(offset.x), 0.f, offset.y + imgSize.y()};
m_uv[2].assign(0.5f - cropPad.x(), 0.5f - cropPad.y()); m_uv[2] = {0.5f - cropPad.x(), 0.5f - cropPad.y()};
m_pos[3].assign(offset.x + imgSize.x(), 0.f, offset.y + imgSize.y()); m_pos[3] = {offset.x + imgSize.x(), 0.f, offset.y + imgSize.y()};
m_uv[3].assign(0.5f + cropPad.x(), 0.5f - cropPad.y()); m_uv[3] = {0.5f + cropPad.x(), 0.5f - cropPad.y()};
}
static CGuiWidget::EGuiModelDrawFlags ResolveFlags(CGuiWidget::EGuiModelDrawFlags flags) {
switch (flags) {
case CGuiWidget::EGuiModelDrawFlags::Shadeless:
case CGuiWidget::EGuiModelDrawFlags::Opaque:
case CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw:
return CGuiWidget::EGuiModelDrawFlags::Alpha;
default:
return flags;
}
}
void CTextSupportShader::BuildCharacterShaderBinding(CTextRenderBuffer& buf, BooFontCharacters& chs,
CGuiWidget::EGuiModelDrawFlags flags) {
chs.m_instBuf = hsh::create_dynamic_vertex_buffer<CTextSupportShader::CharacterInstance>(chs.m_charCount);
hsh::texture2d_array tex = chs.m_font->GetTexture();
if (flags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
chs.m_dataBindingOverdraw.hsh_char_overdraw_bind(
CTextSupportShaderCharacterPipeline<flags>(chs.m_instBuf.get(), buf.m_uniBuf2.get(), tex));
}
chs.m_dataBinding.hsh_char_bind(
CTextSupportShaderCharacterPipeline<ResolveFlags(flags)>(chs.m_instBuf.get(), buf.m_uniBuf.get(), tex));
}
void CTextSupportShader::BuildImageShaderBinding(CTextRenderBuffer& buf, BooImage& img,
CGuiWidget::EGuiModelDrawFlags flags) {
img.m_instBuf = hsh::create_dynamic_vertex_buffer<CTextSupportShader::ImageInstance>(1);
if (flags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
for (TToken<CTexture>& token : img.m_imageDef.x4_texs) {
hsh::texture2d tex = token->GetBooTexture();
img.m_dataBindingOverdraw.emplace_back().hsh_img_overdraw_bind(
CTextSupportShaderImagePipeline<flags>(img.m_instBuf.get(), buf.m_uniBuf2.get(), tex));
}
}
flags = ResolveFlags(flags);
for (TToken<CTexture>& token : img.m_imageDef.x4_texs) {
hsh::texture2d tex = token->GetBooTexture();
img.m_dataBinding.emplace_back().hsh_img_bind(
CTextSupportShaderImagePipeline<flags>(img.m_instBuf.get(), buf.m_uniBuf.get(), tex));
}
} }
} // namespace urde } // namespace urde

View File

@ -14,10 +14,13 @@ namespace urde {
class CGlyph; class CGlyph;
class CFontImageDef; class CFontImageDef;
class CTextRenderBuffer; class CTextRenderBuffer;
struct BooFontCharacters;
struct BooImage;
class CTextSupportShader { class CTextSupportShader {
friend class CTextRenderBuffer; friend class CTextRenderBuffer;
public:
struct Uniform { struct Uniform {
hsh::float4x4 m_mvp; hsh::float4x4 m_mvp;
hsh::float4 m_uniformColor; hsh::float4 m_uniformColor;
@ -25,7 +28,7 @@ class CTextSupportShader {
struct CharacterInstance { struct CharacterInstance {
std::array<hsh::float3, 4> m_pos; std::array<hsh::float3, 4> m_pos;
std::array<hsh::float2, 4> m_uv; std::array<hsh::float3, 4> m_uv;
hsh::float4 m_fontColor; hsh::float4 m_fontColor;
hsh::float4 m_outlineColor; hsh::float4 m_outlineColor;
hsh::float4 m_mulColor; hsh::float4 m_mulColor;
@ -38,6 +41,10 @@ class CTextSupportShader {
hsh::float4 m_color; hsh::float4 m_color;
void SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset); void SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset);
}; };
static void BuildCharacterShaderBinding(CTextRenderBuffer& buf, BooFontCharacters& chs,
CGuiWidget::EGuiModelDrawFlags flags);
static void BuildImageShaderBinding(CTextRenderBuffer& buf, BooImage& img, CGuiWidget::EGuiModelDrawFlags flags);
}; };
} // namespace urde } // namespace urde

View File

@ -31,7 +31,7 @@ CWorldShadowShader::CWorldShadowShader(u32 w, u32 h) : m_w(w), m_h(h) {
bool depth = false; bool depth = false;
m_dataBind.hsh_bind(CWorldShadowShaderPipeline<depth>(m_vbo.get(), m_uniBuf.get())); m_dataBind.hsh_bind(CWorldShadowShaderPipeline<depth>(m_vbo.get(), m_uniBuf.get()));
depth = true; depth = true;
m_dataBind.hsh_z_bind(CWorldShadowShaderPipeline<depth>(m_vbo.get(), m_uniBuf.get())); m_zDataBind.hsh_z_bind(CWorldShadowShaderPipeline<depth>(m_vbo.get(), m_uniBuf.get()));
} }
void CWorldShadowShader::bindRenderTarget() { m_tex.attach(); } void CWorldShadowShader::bindRenderTarget() { m_tex.attach(); }

View File

@ -12,31 +12,6 @@
namespace urde { namespace urde {
struct CTextRenderBuffer::BooFontCharacters {
TLockedToken<CRasterFont> m_font;
hecl::VertexBufferPool<CTextSupportShader::CharacterInstance>::Token m_instBuf;
boo::ObjToken<boo::IShaderDataBinding> m_dataBinding;
boo::ObjToken<boo::IShaderDataBinding> m_dataBinding2;
std::vector<CTextSupportShader::CharacterInstance> m_charData;
u32 m_charCount = 0;
bool m_dirty = true;
BooFontCharacters(const CToken& token) : m_font(token) {}
};
struct CTextRenderBuffer::BooImage {
CFontImageDef m_imageDef;
hecl::VertexBufferPool<CTextSupportShader::ImageInstance>::Token m_instBuf;
std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding;
std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding2;
CTextSupportShader::ImageInstance m_imageData;
bool m_dirty = true;
BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) {
m_imageData.SetMetrics(imgDef, offset);
}
};
struct CTextRenderBuffer::BooPrimitiveMark { struct CTextRenderBuffer::BooPrimitiveMark {
Command m_cmd; Command m_cmd;
u32 m_bindIdx; u32 m_bindIdx;
@ -47,13 +22,13 @@ struct CTextRenderBuffer::BooPrimitiveMark {
case Command::CharacterRender: { case Command::CharacterRender: {
BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx]; BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx];
CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx]; CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx];
inst.m_mulColor.a() = opacity; inst.m_mulColor.w = opacity;
fc.m_dirty = true; fc.m_dirty = true;
break; break;
} }
case Command::ImageRender: { case Command::ImageRender: {
BooImage& img = rb.m_images[m_bindIdx]; BooImage& img = rb.m_images[m_bindIdx];
img.m_imageData.m_color.a() = opacity; img.m_imageData.m_color.w = opacity;
img.m_dirty = true; img.m_dirty = true;
break; break;
} }
@ -72,84 +47,30 @@ CTextRenderBuffer::~CTextRenderBuffer() = default;
CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = default; CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = default;
void CTextRenderBuffer::CommitResources() { void CTextRenderBuffer::CommitResources() {
if (m_committed) if (m_committed) {
return; return;
}
m_committed = true; m_committed = true;
/* Ensure font textures are ready outside transaction */ m_uniBuf = hsh::create_dynamic_uniform_buffer<CTextSupportShader::Uniform>();
for (BooFontCharacters& chs : m_fontCharacters)
chs.m_font->GetTexture();
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory);
auto uBufInfo = m_uniBuf.getBufferInfo();
decltype(uBufInfo) uBufInfo2;
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); m_uniBuf2 = hsh::create_dynamic_uniform_buffer<CTextSupportShader::Uniform>();
uBufInfo2 = m_uniBuf2.getBufferInfo();
} }
for (BooFontCharacters& chs : m_fontCharacters) { for (BooFontCharacters& chs : m_fontCharacters) {
chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount); CTextSupportShader::BuildCharacterShaderBinding(*this, chs, m_drawFlags);
auto iBufInfo = chs.m_instBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
size_t unioffs[] = {size_t(uBufInfo.second)};
size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
boo::ObjToken<boo::ITexture> texs[] = {chs.m_font->GetTexture()};
chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), nullptr,
iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
uniforms[0] = uBufInfo2.first.get();
unioffs[0] = size_t(uBufInfo2.second);
chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), nullptr,
iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
} }
}
for (BooImage& img : m_images) { for (BooImage& img : m_images) {
img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1); CTextSupportShader::BuildImageShaderBinding(*this, img, m_drawFlags);
auto iBufInfo = img.m_instBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
size_t unioffs[] = {size_t(uBufInfo.second)};
size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size());
for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge);
img.m_dataBinding.push_back(ctx.newShaderDataBinding(
CTextSupportShader::SelectImagePipeline(m_drawFlags), nullptr, iBufInfo.first.get(), nullptr, 1, uniforms,
unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
} }
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
uniforms[0] = uBufInfo2.first.get();
unioffs[0] = size_t(uBufInfo2.second);
img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size());
for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
img.m_dataBinding2.push_back(ctx.newShaderDataBinding(
CTextSupportShader::GetImageAdditiveOverdrawPipeline(), nullptr, iBufInfo.first.get(), nullptr, 1,
uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
}
}
}
return true;
} BooTrace);
} }
void CTextRenderBuffer::SetMode(EMode mode) { void CTextRenderBuffer::SetMode(EMode mode) {
if (mode == EMode::BufferFill) { if (mode == EMode::BufferFill) {
m_images.reserve(m_imagesCount); m_images.reserve(m_imagesCount);
for (BooFontCharacters& fc : m_fontCharacters) for (BooFontCharacters& fc : m_fontCharacters) {
fc.m_charData.reserve(fc.m_charCount); fc.m_charData.reserve(fc.m_charCount);
} }
}
m_activeFontCh = -1; m_activeFontCh = -1;
x0_mode = mode; x0_mode = mode;
} }
@ -167,58 +88,55 @@ void CTextRenderBuffer::Render(const zeus::CColor& col, float time) {
const zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); const zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true);
const zeus::CMatrix4f mat = proj * mv; const zeus::CMatrix4f mat = proj * mv;
m_uniBuf.access() = CTextSupportShader::Uniform{mat, col}; m_uniBuf.load({mat, col});
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
zeus::CColor colPremul = col * col.a(); zeus::CColor colPremul = col * col.a();
colPremul.a() = col.a(); colPremul.a() = col.a();
m_uniBuf2.access() = CTextSupportShader::Uniform{mat, colPremul}; m_uniBuf2.load({mat, colPremul});
} }
for (BooFontCharacters& chs : m_fontCharacters) { for (BooFontCharacters& chs : m_fontCharacters) {
if (chs.m_charData.size()) { if (!chs.m_charData.empty()) {
if (chs.m_dirty) { if (chs.m_dirty) {
std::memmove(chs.m_instBuf.access(), chs.m_charData.data(), chs.m_instBuf.load(chs.m_charData);
sizeof(CTextSupportShader::CharacterInstance) * chs.m_charData.size());
chs.m_dirty = false; chs.m_dirty = false;
} }
CGraphics::SetShaderDataBinding(chs.m_dataBinding); chs.m_dataBinding.draw_instanced(0, 4, chs.m_charData.size());
CGraphics::DrawInstances(0, 4, chs.m_charData.size());
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
CGraphics::SetShaderDataBinding(chs.m_dataBinding2); chs.m_dataBindingOverdraw.draw_instanced(0, 4, chs.m_charData.size());
CGraphics::DrawInstances(0, 4, chs.m_charData.size());
} }
} }
} }
for (BooImage& img : m_images) { for (BooImage& img : m_images) {
if (img.m_dirty) { if (img.m_dirty) {
*img.m_instBuf.access() = img.m_imageData; img.m_instBuf.load(img.m_imageData);
img.m_dirty = false; img.m_dirty = false;
} }
const int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size(); const int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size();
CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]); img.m_dataBinding[idx].draw_instanced(0, 4, 1);
CGraphics::DrawInstances(0, 4, 1);
if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]); img.m_dataBindingOverdraw[idx].draw_instanced(0, 4, 1);
CGraphics::DrawInstances(0, 4, 1);
} }
} }
} }
void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) { void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) {
if (x0_mode == EMode::AllocTally) if (x0_mode == EMode::AllocTally) {
m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0}); m_primitiveMarks.emplace_back<BooPrimitiveMark>({Command::ImageRender, m_imagesCount++, 0});
else } else {
m_images.emplace_back(image, offset); m_images.emplace_back(image, offset);
}
} }
void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) { void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) {
if (m_activeFontCh == UINT32_MAX) if (m_activeFontCh == UINT32_MAX) {
return; return;
}
BooFontCharacters& chs = m_fontCharacters[m_activeFontCh]; BooFontCharacters& chs = m_fontCharacters[m_activeFontCh];
if (x0_mode == EMode::AllocTally) if (x0_mode == EMode::AllocTally) {
m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++}); m_primitiveMarks.emplace_back<BooPrimitiveMark>({Command::CharacterRender, m_activeFontCh, chs.m_charCount++});
else { } else {
const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch); const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch);
CTextSupportShader::CharacterInstance& inst = chs.m_charData.emplace_back(); CTextSupportShader::CharacterInstance& inst = chs.m_charData.emplace_back();
@ -265,18 +183,18 @@ std::pair<zeus::CVector2i, zeus::CVector2i> CTextRenderBuffer::AccumulateTextBou
for (const BooFontCharacters& chars : m_fontCharacters) { for (const BooFontCharacters& chars : m_fontCharacters) {
for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) { for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) {
ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x())); ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x));
ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z())); ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z));
ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x())); ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x));
ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z())); ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z));
} }
} }
for (const BooImage& imgs : m_images) { for (const BooImage& imgs : m_images) {
ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x())); ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x));
ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z())); ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z));
ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x())); ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x));
ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z())); ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z));
} }
return ret; return ret;

View File

@ -22,6 +22,31 @@ class CTextExecuteBuffer;
using CTextColor = zeus::CColor; using CTextColor = zeus::CColor;
struct BooFontCharacters {
TLockedToken<CRasterFont> m_font;
hsh::dynamic_owner<hsh::vertex_buffer<CTextSupportShader::CharacterInstance>> m_instBuf;
hsh::binding m_dataBinding;
hsh::binding m_dataBindingOverdraw;
std::vector<CTextSupportShader::CharacterInstance> m_charData;
u32 m_charCount = 0;
bool m_dirty = true;
BooFontCharacters(const CToken& token) : m_font(token) {}
};
struct BooImage {
CFontImageDef m_imageDef;
hsh::dynamic_owner<hsh::vertex_buffer<CTextSupportShader::ImageInstance>> m_instBuf;
std::vector<hsh::binding> m_dataBinding;
std::vector<hsh::binding> m_dataBindingOverdraw;
CTextSupportShader::ImageInstance m_imageData;
bool m_dirty = true;
BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) {
m_imageData.SetMetrics(imgDef, offset);
}
};
class CTextRenderBuffer { class CTextRenderBuffer {
friend class CGuiTextSupport; friend class CGuiTextSupport;
friend class CTextSupportShader; friend class CTextSupportShader;
@ -42,7 +67,7 @@ public:
enum class EMode { AllocTally, BufferFill }; enum class EMode { AllocTally, BufferFill };
private: private:
EMode x0_mode; EMode x0_mode{};
#if 0 #if 0
std::vector<TToken<CRasterFont>> x4_fonts; std::vector<TToken<CRasterFont>> x4_fonts;
std::vector<CFontImageDef> x14_images; std::vector<CFontImageDef> x14_images;
@ -58,11 +83,7 @@ private:
#else #else
/* Boo-specific text-rendering functionality */ /* Boo-specific text-rendering functionality */
hsh::dynamic_owner<hsh::uniform_buffer<CTextSupportShader::Uniform>> m_uniBuf, m_uniBuf2; hsh::dynamic_owner<hsh::uniform_buffer<CTextSupportShader::Uniform>> m_uniBuf, m_uniBuf2;
struct BooFontCharacters;
std::vector<BooFontCharacters> m_fontCharacters; std::vector<BooFontCharacters> m_fontCharacters;
struct BooImage;
std::vector<BooImage> m_images; std::vector<BooImage> m_images;
struct BooPrimitiveMark; struct BooPrimitiveMark;
@ -73,7 +94,7 @@ private:
zeus::CColor m_main; zeus::CColor m_main;
zeus::CColor m_outline = zeus::skBlack; zeus::CColor m_outline = zeus::skBlack;
CGuiWidget::EGuiModelDrawFlags m_drawFlags; CGuiWidget::EGuiModelDrawFlags m_drawFlags{};
bool m_committed = false; bool m_committed = false;
void CommitResources(); void CommitResources();