add 3D text render (WIP)
This commit is contained in:
parent
c5ca9128e9
commit
b3ab037115
@ -117,6 +117,22 @@ void Batch3D::texture(const Texture* new_texture){
|
||||
new_texture->bind();
|
||||
}
|
||||
|
||||
void Batch3D::sprite(
|
||||
const glm::vec3& pos,
|
||||
const glm::vec3& up,
|
||||
const glm::vec3& right,
|
||||
float w,
|
||||
float h,
|
||||
int atlasRes,
|
||||
int index,
|
||||
glm::vec4 tint
|
||||
) {
|
||||
float scale = 1.0f / static_cast<float>(atlasRes);
|
||||
float u = (index % atlasRes) * scale;
|
||||
float v = 1.0f - ((index / atlasRes) * scale) - scale;
|
||||
sprite(pos, up, right, w, h, UVRegion(u, v, u+scale, v+scale), tint);
|
||||
}
|
||||
|
||||
void Batch3D::sprite(
|
||||
const glm::vec3& pos,
|
||||
const glm::vec3& up,
|
||||
|
||||
@ -57,6 +57,16 @@ public:
|
||||
const UVRegion& uv,
|
||||
const glm::vec4& tint
|
||||
);
|
||||
void sprite(
|
||||
const glm::vec3& pos,
|
||||
const glm::vec3& up,
|
||||
const glm::vec3& right,
|
||||
float w,
|
||||
float h,
|
||||
int atlasRes,
|
||||
int index,
|
||||
glm::vec4 tint
|
||||
);
|
||||
void xSprite(
|
||||
float w,
|
||||
float h,
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include <utility>
|
||||
#include "Texture.hpp"
|
||||
#include "Batch2D.hpp"
|
||||
#include "Batch3D.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
|
||||
inline constexpr uint GLYPH_SIZE = 16;
|
||||
inline constexpr uint MAX_CODEPAGES = 10000; // idk ho many codepages unicode has
|
||||
@ -35,41 +37,76 @@ bool Font::isPrintableChar(uint codepoint) const {
|
||||
}
|
||||
}
|
||||
|
||||
int Font::calcWidth(const std::wstring& text, size_t length) {
|
||||
int Font::calcWidth(const std::wstring& text, size_t length) const {
|
||||
return calcWidth(text, 0, length);
|
||||
}
|
||||
|
||||
int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) {
|
||||
int Font::calcWidth(const std::wstring& text, size_t offset, size_t length) const {
|
||||
return std::min(text.length()-offset, length) * glyphInterval;
|
||||
}
|
||||
|
||||
static inline void drawGlyph(
|
||||
Batch2D* batch, int x, int y, uint c, int glyphSize
|
||||
Batch2D& batch,
|
||||
const glm::vec3& pos,
|
||||
const glm::vec2& offset,
|
||||
uint c,
|
||||
int glyphSize,
|
||||
const Camera*
|
||||
) {
|
||||
batch->sprite(x, y, glyphSize, glyphSize, 16, c, batch->getColor());
|
||||
batch.sprite(
|
||||
pos.x + offset.x,
|
||||
pos.y + offset.y,
|
||||
glyphSize,
|
||||
glyphSize,
|
||||
16,
|
||||
c,
|
||||
batch.getColor()
|
||||
);
|
||||
}
|
||||
|
||||
void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y) {
|
||||
static inline void drawGlyph(
|
||||
Batch3D& batch,
|
||||
const glm::vec3& pos,
|
||||
const glm::vec2& offset,
|
||||
uint c,
|
||||
int glyphSize,
|
||||
const Camera* camera
|
||||
) {
|
||||
batch.sprite(
|
||||
pos + camera->right * offset.x + camera->up * offset.y,
|
||||
camera->up, camera->right,
|
||||
glyphSize * 0.5f,
|
||||
glyphSize * 0.5f,
|
||||
16,
|
||||
c,
|
||||
glm::vec4(1.0f)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Batch>
|
||||
static inline void draw_text(
|
||||
const Font& font,
|
||||
Batch& batch,
|
||||
std::wstring_view text,
|
||||
const glm::vec3& pos,
|
||||
float glyphInterval,
|
||||
float lineHeight,
|
||||
const Camera* camera
|
||||
) {
|
||||
uint page = 0;
|
||||
uint next = MAX_CODEPAGES;
|
||||
int init_x = x;
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
do {
|
||||
for (uint c : text){
|
||||
if (!isPrintableChar(c)) {
|
||||
if (!font.isPrintableChar(c)) {
|
||||
x += glyphInterval;
|
||||
continue;
|
||||
}
|
||||
uint charpage = c >> 8;
|
||||
if (charpage == page){
|
||||
Texture* texture = nullptr;
|
||||
if (charpage < pages.size()) {
|
||||
texture = pages[charpage].get();
|
||||
}
|
||||
if (texture == nullptr){
|
||||
texture = pages[0].get();
|
||||
}
|
||||
batch->texture(texture);
|
||||
drawGlyph(batch, x, y, c, lineHeight);
|
||||
batch.texture(font.getPage(charpage));
|
||||
drawGlyph(batch, pos, glm::vec2(x, y), c, lineHeight, camera);
|
||||
}
|
||||
else if (charpage > page && charpage < next){
|
||||
next = charpage;
|
||||
@ -78,6 +115,49 @@ void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y) {
|
||||
}
|
||||
page = next;
|
||||
next = MAX_CODEPAGES;
|
||||
x = init_x;
|
||||
x = 0.0f;
|
||||
} while (page < MAX_CODEPAGES);
|
||||
}
|
||||
|
||||
const Texture* Font::getPage(int charpage) const {
|
||||
Texture* texture = nullptr;
|
||||
if (charpage < pages.size()) {
|
||||
texture = pages[charpage].get();
|
||||
}
|
||||
if (texture == nullptr){
|
||||
texture = pages[0].get();
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Font::draw(
|
||||
Batch2D& batch, std::wstring_view text, int x, int y, float scale
|
||||
) const {
|
||||
draw_text(
|
||||
*this,
|
||||
batch,
|
||||
text,
|
||||
glm::vec3(x, y, 0),
|
||||
glyphInterval * scale,
|
||||
lineHeight * scale,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
void Font::draw(
|
||||
Batch3D& batch,
|
||||
const Camera& camera,
|
||||
std::wstring_view text,
|
||||
const glm::vec3& pos,
|
||||
float scale
|
||||
) const {
|
||||
draw_text(
|
||||
*this,
|
||||
batch,
|
||||
text,
|
||||
pos,
|
||||
glyphInterval * scale,
|
||||
lineHeight * scale,
|
||||
&camera
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,10 +3,13 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include "typedefs.hpp"
|
||||
|
||||
class Texture;
|
||||
class Batch2D;
|
||||
class Batch3D;
|
||||
class Camera;
|
||||
|
||||
enum class FontStyle {
|
||||
none,
|
||||
@ -30,18 +33,28 @@ public:
|
||||
/// @param text selected text
|
||||
/// @param length max substring length (default: no limit)
|
||||
/// @return pixel width of the substring
|
||||
int calcWidth(const std::wstring& text, size_t length=-1);
|
||||
int calcWidth(const std::wstring& text, size_t length=-1) const;
|
||||
|
||||
/// @brief Calculate text width in pixels
|
||||
/// @param text selected text
|
||||
/// @param offset start of the substring
|
||||
/// @param length max substring length
|
||||
/// @return pixel width of the substring
|
||||
int calcWidth(const std::wstring& text, size_t offset, size_t length);
|
||||
int calcWidth(const std::wstring& text, size_t offset, size_t length) const;
|
||||
|
||||
/// @brief Check if character is visible (non-whitespace)
|
||||
/// @param codepoint character unicode codepoint
|
||||
bool isPrintableChar(uint codepoint) const;
|
||||
|
||||
void draw(Batch2D* batch, std::wstring_view text, int x, int y);
|
||||
void draw(Batch2D& batch, std::wstring_view text, int x, int y, float scale=1) const;
|
||||
|
||||
void draw(
|
||||
Batch3D& batch,
|
||||
const Camera& camera,
|
||||
std::wstring_view text,
|
||||
const glm::vec3& pos,
|
||||
float scale = 1
|
||||
) const;
|
||||
|
||||
const Texture* getPage(int page) const;
|
||||
};
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "graphics/core/PostProcessing.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "graphics/core/Font.hpp"
|
||||
#include "ParticlesRenderer.hpp"
|
||||
#include "ChunksRenderer.hpp"
|
||||
#include "ModelBatch.hpp"
|
||||
@ -405,6 +406,29 @@ void WorldRenderer::renderHands(
|
||||
skybox->unbind();
|
||||
}
|
||||
|
||||
void WorldRenderer::renderTexts(
|
||||
const DrawContext& context,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
bool hudVisible
|
||||
) {
|
||||
const auto& assets = *engine->getAssets();
|
||||
auto& shader = assets.require<Shader>("ui3d");
|
||||
auto& font = assets.require<Font>("normal");
|
||||
shader.uniformMatrix("u_projview", camera.getProjView());
|
||||
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||
batch3d->begin();
|
||||
std::wstring string = L"Segmentation fault (core dumped)";
|
||||
font.draw(
|
||||
*batch3d,
|
||||
camera,
|
||||
string,
|
||||
glm::vec3(0, 100, 0) -
|
||||
camera.right * (font.calcWidth(string, string.length()) * 0.5f)
|
||||
);
|
||||
batch3d->flush();
|
||||
}
|
||||
|
||||
void WorldRenderer::draw(
|
||||
const DrawContext& pctx,
|
||||
Camera& camera,
|
||||
@ -441,6 +465,7 @@ void WorldRenderer::draw(
|
||||
DrawContext ctx = wctx.sub();
|
||||
ctx.setDepthTest(true);
|
||||
ctx.setCullFace(true);
|
||||
renderTexts(ctx, camera, settings, hudVisible);
|
||||
renderLevel(ctx, camera, settings, delta, pause);
|
||||
// Debug lines
|
||||
if (hudVisible) {
|
||||
|
||||
@ -80,6 +80,13 @@ class WorldRenderer {
|
||||
const EngineSettings& settings,
|
||||
float fogFactor
|
||||
);
|
||||
|
||||
void renderTexts(
|
||||
const DrawContext& context,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
bool hudVisible
|
||||
);
|
||||
public:
|
||||
std::unique_ptr<ParticlesRenderer> particles;
|
||||
|
||||
|
||||
@ -194,9 +194,9 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
int y = pos.y+slotSize-16;
|
||||
|
||||
batch->setColor({0, 0, 0, 1.0f});
|
||||
font->draw(batch, text, x+1, y+1);
|
||||
font->draw(*batch, text, x+1, y+1);
|
||||
batch->setColor(glm::vec4(1.0f));
|
||||
font->draw(batch, text, x, y);
|
||||
font->draw(*batch, text, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -201,10 +201,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) {
|
||||
if (i < cache.lines.size()-1) {
|
||||
view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset);
|
||||
}
|
||||
font->draw(batch, view, pos.x, pos.y + i * totalLineHeight);
|
||||
font->draw(*batch, view, pos.x, pos.y + i * totalLineHeight);
|
||||
}
|
||||
} else {
|
||||
font->draw(batch, text, pos.x, pos.y);
|
||||
font->draw(*batch, text, pos.x, pos.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,6 +47,6 @@ void Plotter::draw(const DrawContext* pctx, Assets* assets) {
|
||||
batch->setColor({1,1,1,0.2f});
|
||||
string = util::to_wstring(y / multiplier, 3);
|
||||
}
|
||||
font->draw(batch, string, pos.x+dmwidth+2, pos.y+dmheight-y-labelsInterval);
|
||||
font->draw(*batch, string, pos.x+dmwidth+2, pos.y+dmheight-y-labelsInterval);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user