use uniform buffer, though glitchy
This commit is contained in:
parent
b107dbf57b
commit
b2cfc9ffd8
4 changed files with 123 additions and 77 deletions
|
@ -7,6 +7,8 @@
|
|||
#include "ofMain.h"
|
||||
#include "ofUtils.h"
|
||||
|
||||
#include "shader_catalog.hpp"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#ifdef TARGET_OPENGLES
|
||||
|
@ -429,14 +431,14 @@ class Font {
|
|||
|
||||
// If hinting is enabled, worldSize must be an integer and defines the font size in pixels used for hinting.
|
||||
// Otherwise, worldSize can be an arbitrary floating-point value.
|
||||
Font(FT_Face face, float worldSize = 1.0f, bool hinting = false, GLint bufferTargetType = GL_TEXTURE_2D_ARRAY) :
|
||||
Font(FT_Face face, float worldSize = 1.0f, bool hinting = false, GLint bufferTargetType = GL_TEXTURE_2D_ARRAY, GLuint shaderProgram = 0) :
|
||||
face(face),
|
||||
hinting(hinting),
|
||||
BUFFER_TARGET_TYPE(bufferTargetType),
|
||||
program(shaderProgram),
|
||||
worldSize(worldSize){
|
||||
// TODO: modularize init, so we can initialize with settings and text
|
||||
|
||||
|
||||
if(gl_max_texture_size == -1){
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_texture_size);
|
||||
cout << "GL_MAX_TEXTURE_SIZE: " << ofToString(gl_max_texture_size) << endl;
|
||||
|
@ -463,22 +465,7 @@ class Font {
|
|||
emSize = face->units_per_EM;
|
||||
}
|
||||
|
||||
//int amounters = 0;
|
||||
//for(int i = 0; i < 1024; i++){
|
||||
//testGL(10 + i);
|
||||
//amounters = i + 1;
|
||||
//cout << "added " << ofToString(amounters) << " LOL" << endl;
|
||||
//bool hasError = false;
|
||||
//GLenum err;
|
||||
//while((err = glGetError()) != GL_NO_ERROR){
|
||||
//hasError = true;
|
||||
//// Process/log the error.
|
||||
//}
|
||||
//if(hasError){
|
||||
//cout << "WHOOOPS" << endl;
|
||||
//break;
|
||||
//}
|
||||
//}
|
||||
ubo_curves_index = glGetUniformBlockIndex(program, "curves_t");
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
|
||||
|
@ -492,8 +479,13 @@ class Font {
|
|||
glGenBuffers(1, &glyphBufferName);
|
||||
glGenBuffers(1, &curveBufferName);
|
||||
#else
|
||||
glGenTextures(1, &glyphBufferName);
|
||||
glGenTextures(1, &curveBufferName);
|
||||
if(BUFFER_TARGET_TYPE == GL_TEXTURE_2D_ARRAY){
|
||||
glGenTextures(1, &glyphBufferName);
|
||||
glGenTextures(1, &curveBufferName);
|
||||
}else{
|
||||
glGenTextures(1, &glyphBufferName);
|
||||
glGenBuffers(1, &curveBufferName);
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
@ -526,7 +518,26 @@ class Font {
|
|||
int widthCurveTextureLayer = 0;
|
||||
int previousCurveBufferSize = 0;
|
||||
int bufferCurveSize = (sizeof(BufferCurve) / (sizeof(glm::float32_t) * 1));
|
||||
int shaderCurvesBufferSize = -1;
|
||||
GLint ubo_curves_index;
|
||||
|
||||
void generateCurveBuffers(){
|
||||
int shaderBufferByteSize = sizeof(BufferCurve) * shaderCurvesBufferSize;
|
||||
shaderBufferCurves = bufferCurves;
|
||||
shaderBufferCurves.resize(shaderCurvesBufferSize);
|
||||
|
||||
//cout << "generate curve buffer" << endl
|
||||
//<< "\t shaderBufferByteSize: " << ofToString(shaderBufferByteSize)
|
||||
//<< "\t bufferCurves.size(): " << ofToString(bufferCurves.size())
|
||||
//<< "\t shaderBufferCurves.size(): " << ofToString(shaderBufferCurves.size())
|
||||
//<< endl;
|
||||
|
||||
ubo_curves_index = glGetUniformBlockIndex(program, "curves_t");
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, curveBufferName);
|
||||
glBufferData(GL_UNIFORM_BUFFER, shaderBufferByteSize, shaderBufferCurves.data(), GL_DYNAMIC_DRAW);
|
||||
glUniformBlockBinding(program, ubo_curves_index, 0);
|
||||
|
||||
}
|
||||
void generateCurveTextureLayers(int amountCurves){
|
||||
//cout << "generateCurveTextureLayers()" << endl;
|
||||
int curveBufferSize = amountCurves * bufferCurveSize;
|
||||
|
@ -575,6 +586,11 @@ class Font {
|
|||
}
|
||||
previousCurveBufferSize = curveBufferSize;
|
||||
}
|
||||
void uploadCurveBuffer(){
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, curveBufferName);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(BufferCurve) * bufferCurves.size(), bufferCurves.data());
|
||||
}
|
||||
void uploadCurveTextureLayers(){
|
||||
glActiveTexture(GL_TEXTURE0 + curveBufferUnit);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, curveBufferName);
|
||||
|
@ -673,6 +689,8 @@ class Font {
|
|||
}
|
||||
void prepareGlyphsForText(const std::vector <GlyphIdentity> & variationText,
|
||||
FT_Library & library,
|
||||
shared_ptr <ShaderCatalog> shaderCatalog,
|
||||
shared_ptr <ShaderCatalog::Entry> shader,
|
||||
bool forceChange = false){
|
||||
bool changed = false;
|
||||
|
||||
|
@ -731,13 +749,50 @@ class Font {
|
|||
dirtyBuffers = true;
|
||||
glyphBufferUnit = 1;
|
||||
curveBufferUnit = 2;
|
||||
generateCurveTextureLayers(bufferCurves.size());
|
||||
// Reupload the full buffer contents. To make this even more
|
||||
// dynamic, the buffers could be overallocated and only the added
|
||||
// data could be uploaded.
|
||||
uploadBuffers();
|
||||
if(BUFFER_TARGET_TYPE == GL_UNIFORM_BUFFER){
|
||||
int curvesBufferSize = getUboCurvesBufferSize(bufferCurves);
|
||||
if(curvesBufferSize != shaderCurvesBufferSize){
|
||||
shaderCurvesBufferSize = curvesBufferSize;
|
||||
shaderCatalog->setReplacement("{{CURVES_BUFFER_SIZE}}", std::to_string(shaderCurvesBufferSize));
|
||||
//cout << shaderCatalog->getReplacement("{{CURVES_BUFFER_SIZE}}") << " <<<< _ replacement for curves buffer size " << endl;
|
||||
shaderCatalog->requestUpdate("font_ub", true);
|
||||
shaderCatalog->update();
|
||||
shader = shaderCatalog->get("font_ub");
|
||||
program = shader->program;
|
||||
generateCurveBuffers();
|
||||
uploadBuffers();
|
||||
}else{
|
||||
uploadBuffers();
|
||||
}
|
||||
}else{
|
||||
generateCurveTextureLayers(bufferCurves.size());
|
||||
// Reupload the full buffer contents. To make this even more
|
||||
// dynamic, the buffers could be overallocated and only the added
|
||||
// data could be uploaded.
|
||||
uploadBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
int getUboCurvesBufferSize(const std::vector <BufferCurve> & bc){
|
||||
int actualShaderBufferSize = ceil((bc.size() * 6.0) / 4.0);
|
||||
int thresholdBase = 2048;
|
||||
int n_max = gl_max_uniform_block_size / thresholdBase;
|
||||
for(int i = 0; i < n_max + 1; i++){
|
||||
int levelSize = thresholdBase * i;
|
||||
// prevent flattering around a threshold
|
||||
// when going a level down
|
||||
// but immediately
|
||||
if(actualShaderBufferSize <= levelSize){
|
||||
if(shaderCurvesBufferSize == levelSize + thresholdBase){
|
||||
return shaderCurvesBufferSize;
|
||||
}
|
||||
return levelSize;
|
||||
}
|
||||
}
|
||||
// you want more? well, we don't have it :(
|
||||
return gl_max_uniform_block_size;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
bool initializedGlyphsBufferTexture = false;
|
||||
|
@ -849,35 +904,12 @@ class Font {
|
|||
GL_RG_INTEGER,
|
||||
GL_INT,
|
||||
bufferGlyphs.data());
|
||||
|
||||
//int bufferCurvesSize = bufferCurves.size() * bufferCurveSize;
|
||||
//if(!isPowerOfTwo(bufferCurvesSize)){
|
||||
//bufferCurvesSize = calculateUpperPowerOfTwo(bufferCurvesSize);
|
||||
//}
|
||||
//glActiveTexture(GL_TEXTURE0 + curveBufferUnit);
|
||||
//glBindTexture(GL_TEXTURE_2D, curveBufferName);
|
||||
//if(!initializedCurvesBufferTexture){
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
//GL_NEAREST);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
//GL_NEAREST);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
//initializedCurvesBufferTexture = true;
|
||||
//}
|
||||
//glTexImage2D(GL_TEXTURE_2D,
|
||||
//0,
|
||||
//GL_RG32F,
|
||||
//bufferCurvesSize,
|
||||
//1,
|
||||
//0,
|
||||
//GL_RG,
|
||||
//GL_FLOAT,
|
||||
//bufferCurves.data());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
uploadCurveTextureLayers();
|
||||
if(BUFFER_TARGET_TYPE == GL_TEXTURE_2D_ARRAY){
|
||||
uploadCurveTextureLayers();
|
||||
}else if(BUFFER_TARGET_TYPE == GL_UNIFORM_BUFFER){
|
||||
uploadCurveBuffer();
|
||||
}
|
||||
#endif
|
||||
dirtyBuffers = false;
|
||||
}
|
||||
|
@ -1183,14 +1215,19 @@ class Font {
|
|||
#else
|
||||
glyphsUniformLocation = glGetUniformLocation(program, "glyphs");
|
||||
glUniform1i(glyphsUniformLocation, glyphBufferUnit);
|
||||
curvesUniformLocation = glGetUniformLocation(program, "curves");
|
||||
glUniform1i(curvesUniformLocation, curveBufferUnit);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + glyphBufferUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, glyphBufferName);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + curveBufferUnit);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, curveBufferName);
|
||||
if(BUFFER_TARGET_TYPE == GL_TEXTURE_2D_ARRAY){
|
||||
curvesUniformLocation = glGetUniformLocation(program, "curves");
|
||||
glUniform1i(curvesUniformLocation, curveBufferUnit);
|
||||
glActiveTexture(GL_TEXTURE0 + curveBufferUnit);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, curveBufferName);
|
||||
}else if(BUFFER_TARGET_TYPE == GL_UNIFORM_BUFFER){
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, curveBufferName);
|
||||
glUniformBlockBinding(program, ubo_curves_index, 0);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
#endif
|
||||
|
@ -1428,7 +1465,8 @@ class Font {
|
|||
|
||||
std::vector <BufferGlyph> bufferGlyphs;
|
||||
std::vector <BufferCurve> bufferCurves;
|
||||
std::vector <int> bufferCurveLayerPointers = {0};
|
||||
std::vector <BufferCurve> shaderBufferCurves; // ubo
|
||||
std::vector <int> bufferCurveLayerPointers = {0}; // t2a
|
||||
std::unordered_map <GlyphIdentity, Glyph> glyphs;
|
||||
|
||||
static GLint gl_max_texture_size;
|
||||
|
@ -1446,6 +1484,7 @@ class Font {
|
|||
static std::shared_ptr <Font> loadFont(FT_Library & library,
|
||||
const std::string & filename,
|
||||
GLint bufferTargetType,
|
||||
GLuint shaderProgram,
|
||||
float worldSize = 1.0f,
|
||||
bool hinting = false){
|
||||
std::string error;
|
||||
|
@ -1457,16 +1496,17 @@ static std::shared_ptr <Font> loadFont(FT_Library & library,
|
|||
std::cout << "ofxGPUFont::font.hpp[" << __LINE__ << "] FT loaded " << filename << ": " << error << std::endl;
|
||||
}
|
||||
|
||||
return std::make_shared <Font>(face, worldSize, hinting, bufferTargetType);
|
||||
return std::make_shared <Font>(face, worldSize, hinting, bufferTargetType, shaderProgram);
|
||||
}
|
||||
|
||||
|
||||
static void initializeFont(FT_Library & library,
|
||||
const std::string & filename,
|
||||
shared_ptr <Font> & mainFont,
|
||||
GLuint shaderProgram,
|
||||
GLint bufferTargetType = GL_TEXTURE_2D_ARRAY){
|
||||
cout << "initializeFont" << endl;
|
||||
auto font = loadFont(library, filename, bufferTargetType);
|
||||
auto font = loadFont(library, filename, bufferTargetType, shaderProgram);
|
||||
if(!font){
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ class ShaderCatalog::Impl {
|
|||
if(error != ""){
|
||||
std::cerr << "[shader] " << error << std::endl;
|
||||
}else{
|
||||
std::cerr << "[shader] reloaded " << name << std::endl;
|
||||
//std::cerr << "[shader] reloaded " << name << std::endl;
|
||||
glDeleteProgram(it->second->program);
|
||||
it->second->program = program;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ofxGPUFont {
|
|||
class ShaderCatalog {
|
||||
public:
|
||||
struct Entry {
|
||||
unsigned int program;
|
||||
GLuint program;
|
||||
|
||||
Entry() : program(0){
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue