PDA

View Full Version : Texture Mapped Fonts from Beginning OpenGL Book



Robbie
04-19-2012, 10:13 AM
I'm using the code from Chapter 11 of the Beginning OpenGL Game Programming book in line with a previous example from the same book that's using vertex buffer objects...I'm having a hard time getting the fonts to display on the same screen as my regular geometry...and I'm pretty sure it has something to do with the setting up of the VBO's and GLIdentities and Matrices in the TextureMappedFont.cpp module conflicting with my regular VBO rendering process.

Is anyone here familiar with that book that would like to take a look at my code for me? I've got two problems...

I can either make the call to m_font->printString before or after my existing glDrawElements in render and see the text but not my elements. Or I can comment out the call to m_font->printString and see the elements...

Either way...if the block in init that gets the GL_VIEWPORT and initializes the TextureMappedFont object is called, I can not debug the application...debugger says "Could not initialize the application" but the exe runs just fine outside of debugging.

Any ideas?

Robbie
04-20-2012, 05:41 AM
Here's some code if anyone is interested in helping...

I have two apparently competing bits...here's the texturemappedfont object, and it's unmodified from the sample except to change the directory of the font files to the current directory.



#ifdef WIN32
#include <windows.h>
#endif

#include "texturemappedfont.h"
#include <GL/glu.h>

TextureMappedFont::TextureMappedFont(const string&amp; textureName, int screenWidth, int screenHeight, float fontSize)
{
m_textureName = textureName;
m_shaderProgram = new GLSLProgram("font.vert", "font.frag");
m_screenWidth = screenWidth;
m_screenHeight = screenHeight;
m_fontSize = fontSize;
}

bool TextureMappedFont::initialize()
{
if (!m_texture.load(m_textureName)) {
std::cerr << "Couldn't load the font texture" << std::endl;
return false;

}

glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, m_texture.getWidth(),
m_texture.getHeight(), GL_RGB, GL_UNSIGNED_BYTE, m_texture.getImageData());


float vertices [] = {
0.0f, 0.0f,
m_fontSize, 0.0f,
m_fontSize, m_fontSize,
0.0f, m_fontSize
};

glGenBuffers(1, &amp;m_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, &amp;vertices[0], GL_STATIC_DRAW);

//Just initialize with something for now, the tex coords are updated
//for each character printed
float texCoords [] = {
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f
};

glGenBuffers(1, &amp;m_texCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, &amp;texCoords[0], GL_DYNAMIC_DRAW);

if (!m_shaderProgram->initialize()) {
std::cerr << "The shader program could not be initialized" << std::endl;
return false;
}

m_shaderProgram->bindAttrib(0, "a_Vertex");
m_shaderProgram->bindAttrib(1, "a_TexCoord0");
m_shaderProgram->linkProgram();

m_shaderProgram->sendUniform("texture0", 0);

return true;
}

void TextureMappedFont::printString(const string&amp; str, float x, float y)
{
static float modelviewMatrix[16];
static float projectionMatrix[16];

m_shaderProgram->bindShader();

setOrthoMode();

float texCoords[8];

glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);

glBindTexture(GL_TEXTURE_2D, m_textureID);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glTranslatef(x, y, 0.0); //Position our text
for(string::size_type i = 0; i < str.size(); ++i)
{
const float oneOverSixteen = 1.0f / 16.0f;

int ch = int(str[i]);
float xPos = float(ch % 16) * oneOverSixteen;
float yPos = float(ch / 16) * oneOverSixteen;

texCoords[0] = xPos;
texCoords[1] = 1.0f - yPos - oneOverSixteen;

texCoords[2] = xPos + oneOverSixteen;
texCoords[3] = 1.0f - yPos - oneOverSixteen;

texCoords[4] = xPos + oneOverSixteen;
texCoords[5] = 1.0f - yPos - 0.001f;

texCoords[6] = xPos;
texCoords[7] = 1.0f - yPos - 0.001f;

glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 8, &amp;texCoords[0]);

glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glVertexAttribPointer((GLint)0, 2, GL_FLOAT, GL_FALSE, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
glVertexAttribPointer((GLint)1, 2, GL_FLOAT, GL_FALSE, 0, 0);

glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);

m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);

glDrawArrays(GL_QUADS, 0, 4);

glTranslatef(m_fontSize * 0.80f, 0, 0); //Move along a bit for the next character
}

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);

unsetOrthoMode();
}

void TextureMappedFont::setOrthoMode()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, m_screenWidth, 0, m_screenHeight, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}

void TextureMappedFont::unsetOrthoMode()
{
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}


And here's the pertinent calls in my code.



bool ReactionTime::init(int width, int height)
{
// Init OpenGL
if (!glGenBuffers || !glBindBuffer || !glBufferData || !glDrawRangeElements)
{
std::cerr << "VBOs are not supported by your graphics card" << std::endl;
return false;
}

screenWidth = width;
screenHeight = height;

glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.3f, 1.0f);

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

currentStage = RESET;

plotArrows(CROSS);
genBuffers();
updateProjection();

// If this code is present, I cannot debug, but my drawn elements do appear if the printstring call is commented out of render
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
m_font = new TextureMappedFont("font.tga", viewport[2], viewport[3], 25.0f);
if (!m_font->initialize()) {
std::cerr << "Could not initialize the font" << std::endl;
return false;
}

//Return success
return true;
}
void ReactionTime::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Load the identity matrix (reset to the default position and orientation)
glLoadIdentity();

updateProjection();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glDrawElements(GL_TRIANGLE_FAN, m_indices.size(), GL_UNSIGNED_INT, 0);

//the following line causes ONLY the text to be displayed, not my drawn elements, even if it's disabled via if statement...if this line is present, the drawelements above does nothing
m_font->printString("Simple Reaction Time Task", 0, 0);
}
void ReactionTime::genBuffers()
{
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glGenBuffers(MAX_BUFFERS, &amp;m_vbos[0]);
glBindBuffer(GL_ARRAY_BUFFER, m_vbos[VERTEX_BUFFER]); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_vertices.size(), &amp;m_vertices[0], GL_DYNAMIC_DRAW); //Send the data to OpenGL

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbos[INDEX_BUFFER]); //Bind the index buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * m_indices.size(), &amp;m_indices[0], GL_DYNAMIC_DRAW); //Send the data to OpenGL

glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_colors.size(), &amp;m_colors[0], GL_DYNAMIC_DRAW); //Send the data to OpenGL

//Bind the color array, and set the color pointer to point at it
glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]);
glColorPointer(3, GL_FLOAT, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, m_vbos[VERTEX_BUFFER]);
glVertexPointer(3, GL_FLOAT, 0, 0);

}
void ReactionTime::rebufferData()
{
glBindBuffer(GL_ARRAY_BUFFER, m_vbos[VERTEX_BUFFER]); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_vertices.size(), &amp;m_vertices[0], GL_DYNAMIC_DRAW); //Send the new data to OpenGL

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbos[INDEX_BUFFER]); //Bind the index buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * m_indices.size(), &amp;m_indices[0], GL_DYNAMIC_DRAW); //Send the new data to OpenGL

glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]); //Bind the color buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_colors.size(), &amp;m_colors[0], GL_DYNAMIC_DRAW); //Send the data to OpenGL


}
void ReactionTime::updateProjection()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

float screenAspect, left, right, bottom, top;

screenAspect = (float) screenWidth / screenHeight;

left = 0;
right = 0;
bottom = -8;
top = 8;

left -= (screenAspect * 8);
right = (screenAspect * 8);

glOrtho(left, right, top, bottom, 1.0, 100.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}


I left out the prepare routine and the plotarrows routine. prepare just decides which symbol gets drawn based on the task logic and calls plotarrows which sets up the vertices and the indices and the colors...

I can only display either text from the texturemappedfont object or my symbology from the GL_TRIANGLE_FAN...

Any help would be greatly appreciated it...I'm sure it's just some mode that's getting toggled or switches and clearing everything else when the text is shown, but I don't know what.

Robbie
04-23-2012, 05:11 AM
Anybody have any ideas on this?