streamlined text rendering

This commit is contained in:
devZoGok
2026-07-11 11:02:57 +03:00
parent 72b9007693
commit e29dad91d3
7 changed files with 41 additions and 166 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ namespace vb01{
-1,
-1
);
root->initTextureDataOnGpu(glyph.data, pixelHeight, pixelHeight, glyph.bufferId, glyph.layerId, false, glyph.size.x, glyph.size.y);
root->initTextureDataOnGpu(glyph.data, pixelHeight, pixelHeight, glyph.bufferId, glyph.layerId, false, true, glyph.size.x, glyph.size.y);
glyphs.push_back(glyph);
}
+1 -1
View File
@@ -6,7 +6,7 @@ in flat int ID;
out vec4 FragColor;
struct GuiObjectData{
float pos[3], scale[3];
float pos[3], scale[3], size[2];
bool texturingEnabled;
int glyphTexture[2], pastTexture[2], nextTexture[2];
float diffuseColor[4];
+8 -7
View File
@@ -9,7 +9,7 @@ out int ID;
uniform vec2 screen;
struct GuiObjectData{
float pos[3], scale[3];
float pos[3], scale[3], size[2];
bool texturingEnabled;
int glyphTexture[2], pastTexture[2], nextTexture[2];
float diffuseColor[4];
@@ -22,14 +22,15 @@ layout(std430, binding = 0) readonly restrict buffer objSSBO {
void main(){
int id = gl_InstanceID;
vec3 scale = vec3(guiObjData[id].scale[0], guiObjData[id].scale[1], guiObjData[id].scale[2]);
vec3 pos = vec3(guiObjData[id].pos[0], guiObjData[id].pos[1], guiObjData[id].pos[2]);
pos *= scale;
vec3 pos = vec3(guiObjData[id].pos[0], guiObjData[id].pos[1], guiObjData[id].pos[2]) * scale;
vec2 size = vec2(guiObjData[id].size[0], guiObjData[id].size[1]);
vec3 vertPos = vec3(aVert.xy * scale.xy * size.xy, aVert.z);
float x, y;
x = (aVert.x * scale.x + pos.x - screen.x * .5) / (screen.x * .5);
y = (screen.y * .5 - (aVert.y * scale.y + pos.y)) / (screen.y * .5);
gl_Position = vec4(x, y, -(pos.z + aVert.z), 1);
texCoords = vec2(aTexCoords.x, 1.0 - aTexCoords.y);
x = (vertPos.x + pos.x - screen.x * .5) / (screen.x * .5);
y = (screen.y * .5 - (vertPos.y + pos.y)) / (screen.y * .5);
gl_Position = vec4(x, y, -(pos.z + vertPos.z), 1);
texCoords = vec2(aTexCoords.x * size.x, (1.0 - aTexCoords.y) * size.y);
ID = id;
}
+15 -7
View File
@@ -140,7 +140,7 @@ namespace vb01{
}
//TODO check loading of textures with different dimensions
void Root::initTextureDataOnGpu(u8 *data, int width, int height, int &bufferId, int &layerId, bool scene, int w, int h){
void Root::initTextureDataOnGpu(u8 *data, int width, int height, int &bufferId, int &layerId, bool scene, bool singleChannel, int w, int h){
int textureUnitId = -1;
vector<TextureUnitGpuData> &textureData = (scene ? meshTextureData : guiTextureData);
@@ -156,6 +156,8 @@ namespace vb01{
glGenTextures(1, &textureData[textureUnitId].buffer);
}
GLint texelFormat = (singleChannel ? GL_RED : GL_RGB);
for(int i = 0; i < textureData.size(); i++){
TextureUnitGpuData &texData = textureData[i];
@@ -163,7 +165,7 @@ namespace vb01{
u8 background[numPixels]{0};
glBindTexture(GL_TEXTURE_2D_ARRAY, texData.buffer);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RED, texData.width, texData.height, texData.imageData.size() + 1, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, texelFormat, texData.width, texData.height, texData.imageData.size() + 1, 0, texelFormat, GL_UNSIGNED_BYTE, NULL);
int dims[]{texData.width, texData.height};
@@ -171,10 +173,10 @@ namespace vb01{
if(!(texData.subDims[j].first == 0 && texData.subDims[j].second == 0)){
dims[0] = texData.subDims[j].first;
dims[1] = texData.subDims[j].second;
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, j, texData.width, texData.height, 1, texelFormat, GL_UNSIGNED_BYTE, background);
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, j, texData.width, texData.height, 1, GL_RED, GL_UNSIGNED_BYTE, background);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, j, dims[0], dims[1], 1, GL_RED, GL_UNSIGNED_BYTE, texData.imageData[j]);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, j, dims[0], dims[1], 1, texelFormat, GL_UNSIGNED_BYTE, texData.imageData[j]);
}
if(textureUnitId == i){
@@ -187,10 +189,12 @@ namespace vb01{
texData.imageData.push_back(data);
texData.subDims.push_back(make_pair(w, h));
if(!(w == 0 && h == 0)) dims[0] = w, dims[1] = h;
if(!(w == 0 && h == 0)){
dims[0] = w, dims[1] = h;
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerId, texData.width, texData.height, 1, texelFormat, GL_UNSIGNED_BYTE, background);
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerId, texData.width, texData.height, 1, GL_RED, GL_UNSIGNED_BYTE, background);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerId, dims[0], dims[1], 1, GL_RED, GL_UNSIGNED_BYTE, data);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerId, dims[0], dims[1], 1, texelFormat, GL_UNSIGNED_BYTE, data);
}
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, scene ? GL_REPEAT : GL_CLAMP_TO_EDGE);
@@ -288,6 +292,8 @@ namespace vb01{
gui.scale[0] = scale.x;
gui.scale[1] = scale.y;
gui.scale[2] = scale.z;
gui.size[0] = glyph.size.x / size.x;
gui.size[1] = glyph.size.y / size.y;
const Texture::Frame &frame = ((Material::TextureUniform*)charac.material->getUniform("glyphTexture"))->value->getFrame(0);
gui.glyphTexture[0] = frame.bufferId;
@@ -395,6 +401,8 @@ namespace vb01{
gui.pos[0] = pos.x;
gui.pos[1] = pos.y;
gui.pos[2] = pos.z;
gui.size[0] = 1;
gui.size[1] = 1;
gui.glyphTexture[0] = -1;
gui.glyphTexture[1] = -1;
gui.texturingEnabled = texturingEnabled;
+2 -2
View File
@@ -42,7 +42,7 @@ namespace vb01{
void removeSkybox();
void initVertexDataOnGpu(MeshData&, u32&, u32&, u32&, bool);
void initTextureDataOnGpu(int, int);
void initTextureDataOnGpu(u8*, int, int, int&, int&, bool, int = 0, int = 0);
void initTextureDataOnGpu(u8*, int, int, int&, int&, bool, bool = false, int = 0, int = 0);
void updateRenderNodeData(Node*);
void createCubemap(bool, bool, std::string[6], int);
inline Shader* getPhongShader(){return phongShader;}
@@ -104,7 +104,7 @@ namespace vb01{
float a, b, c, near, far, radius;
};
struct GuiData {
float pos[3], scale[3];
float pos[3], scale[3], size[2];
int texturingEnabled, glyphTexture[2], pastTexture[2], nextTexture[2];
float diffuseColor[4];
};
+13 -141
View File
@@ -1,46 +1,16 @@
#include "root.h"
#include "text.h"
#include "shader.h"
#include "texture.h"
#include "node.h"
#include "material.h"
#include "assetManager.h"
#include "glad.h"
#include <glfw3.h>
#include <iostream>
#include <algorithm>
#include <ft2build.h>
#include FT_FREETYPE_H
using namespace std;
namespace vb01{
Text::Text(string fontPath, wstring e, u16 firstChar, u16 lastChar){
font = (FontAsset*)AssetManager::getSingleton()->getAsset(fontPath);
setEntry(e);
//init();
//applyFont(fontPath, firstChar, lastChar);
}
Text::~Text(){
//glDeleteVertexArrays(1, &VAO);
//glDeleteBuffers(1, &VBO);
}
void Text::init(){
//glGenVertexArrays(1, &VAO);
//glGenBuffers(1, &VBO);
//glBindVertexArray(VAO);
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
//glEnableVertexAttribArray(0);
//glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindVertexArray(0);
}
wstring Text::getEntry(){
@@ -57,126 +27,28 @@ namespace vb01{
delete ch.material;
characters.clear();
Vector3 scale = Vector3::VEC_IJK;
for(wchar_t ch : entry){
Material *mat = new Material(Root::getSingleton()->getGuiShader());
mat->addTexUniform("glyphTexture", new Texture(font->path, ch), false, false);
Character charac = Character(ch, mat);
int numChars = characters.size();
if(numChars > 0){
const FontAsset::Glyph &glyph = font->getGlyph(ch);
Vector2 currOffset = Vector2::VEC_ZERO;
if(horizontal)
currOffset = Vector2::VEC_I * (leftToRight ? 1 : -1) * glyph.size.x * scale.x;
else
currOffset = Vector2::VEC_J * glyph.size.y * scale.y;
charac.offset = characters[numChars - 1].offset + currOffset;
}
characters.push_back(charac);
}
}
//TODO ensure destruction of textures when unloading the asset
void Text::applyFont(string fontPath, u16 firstChar, u16 lastChar){
characters.clear();
font = (FontAsset*)AssetManager::getSingleton()->getAsset(fontPath);
for(u16 i = firstChar; i < lastChar; i++){
/*
Glyph c;
c.ch = i;
c.size = Vector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
c.bearing = Vector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
c.advance = face->glyph->advance.x;
c.texId = i;
*/
//characters.push_back(c);
characters.push_back(Character(ch, mat));
}
}
void Text::update(){
//Root *root = Root::getSingleton();
//int width = root->getWidth(), height = root->getHeight();
Vector2 advanceOffset = Vector2::VEC_ZERO;
Vector3 scale = node->getScale();
int numShifts = 6, startId = (leftToRight ? 0 : getLength() - 1);
//material->update();
//Shader *shader = material->getShader();
//shader->setVec2(Vector2(width, height), "screen");
//shader->setVec3(node->getPosition(), "pos");
for(int i = startId; (leftToRight ? (i < getLength()) : (i >= 0)); (leftToRight ? i++ : i--)){
Character &charac = characters[i];
const FontAsset::Glyph &currGlyph = font->getGlyph(charac.ch);
charac.offset = Vector2( (currGlyph.bearing.x + advanceOffset.x), (advanceOffset.y - currGlyph.bearing.y));
//Vector2 advanceOffset = Vector2::VEC_ZERO;
//for(int i = (leftToRight ? 0 : entry.length() - 1); (leftToRight ? (i < entry.length()) : (i >= 0)); (leftToRight ? i++ : i--)){
// Glyph *glyphPtr = getGlyph(entry[i]);
// if(!glyphPtr) continue;
// int glyphTexId = -1;
// for(int j = 0; j < font->glyphTextures.size(); j++)
// if(font->glyphTextures[j].first == glyphPtr->texId){
// glyphTexId = j;
// break;
// }
// Glyph glyph = *glyphPtr;
// prepareGlyphs(glyph, glyphTexId, advanceOffset);
// Vector2 size = glyph.size, bearing = glyph.bearing;
// if(horizontal)
// advanceOffset.x += node->getScale().x * (size.x + bearing.x);
// else
// advanceOffset.y += node->getScale().y * size.y;
//}
if(horizontal)
advanceOffset.x += (currGlyph.advance >> numShifts);
else
advanceOffset.y += currGlyph.size.y + (currGlyph.size.y - currGlyph.bearing.y);
}
}
/*
void Text::prepareGlyphs(Glyph glyph, int glyphTexId, Vector2 advanceOffset){
//Vector3 nodePos = node->getPosition(), scale = node->getScale();
//Vector2 origin = Vector2(nodePos.x, nodePos.y) + (advanceOffset * scale);
//Vector2 size = Vector2(glyph.size.x * scale.x, glyph.size.y * scale.y);
//Vector2 bearing = Vector2(glyph.bearing.x * scale.x, glyph.bearing.y * scale.y);
//float data[] = {
// origin.x + bearing.x, origin.y - bearing.y, 0, 0,
// origin.x + bearing.x + size.x, origin.y - bearing.y, 1, 0,
// origin.x + bearing.x + size.x, origin.y - bearing.y + size.y, 1, 1,
// origin.x + bearing.x + size.x, origin.y - bearing.y + size.y, 1, 1,
// origin.x + bearing.x, origin.y - bearing.y + size.y, 0, 1,
// origin.x + bearing.x, origin.y - bearing.y, 0, 0
//};
////glBindVertexArray(VAO);
////glBindBuffer(GL_ARRAY_BUFFER, VBO);
////glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(data), data);
//int id = 2;
//material->getShader()->setInt(id, "textures[1].pastTexture");
//font->glyphTextures[glyphTexId].second->select(id);
////glDrawArrays(GL_TRIANGLES, 0, 6);
}
*/
/*
Text::Glyph* Text::getGlyph(u16 ch){
Glyph *glyph = nullptr;
for(Glyph &g : characters)
if(g.ch == ch)
glyph = &g;
return glyph;
}
*/
}
+1 -7
View File
@@ -25,7 +25,7 @@ namespace vb01{
};
Text(std::string, std::wstring, u16 = 0, u16 = 256);
~Text();
~Text(){}
void update();
std::wstring getEntry();
void setEntry(std::wstring);
@@ -38,13 +38,7 @@ namespace vb01{
inline Material* getMaterial(){return material;}
inline void setMaterial(Material *mat){this->material = mat;}
inline const std::vector<Character>& getCharacters(){return characters;}
//Glyph* getGlyph(u16);
private:
void init();
void applyFont(std::string, u16, u16 = 256);
void clearFont();
//void prepareGlyphs(Glyph, int, Vector2);
FontAsset *font = nullptr;
Material *material = nullptr;
std::vector<Character> characters;