nitro404

Members
  • Content count

    12
  • Joined

  • Last visited

Community Reputation

103 Neutral

About nitro404

  • Rank
    Member
  1. Oh wow, well I hadn't realized it, but my text rendering function was re-enabling blending when I thought it was entirely disabled from the init code. I feel pretty silly about that now. Glad it's fixed though, thanks a lot for the help!
  2. weird errors in c++ project

    Would be much more helpful if you indicated the line(s) these errors are occurring on, not really sure where I'm looking.
  3. Hello! I'm looking for some help with a little issue I'm having rendering geometry in my OpenGL engine. Not entirely sure what the issue is, but objects appear translucent when they should be entirely opaque. I've quadruple checked my OpenGL init calls, and everything seems to be correct, even referencing it against other projects which use OpenGL. Also worth noting that draw order seems to affect this, which makes no sense. Namely, if I draw object 1, then draw object 2, you can't see 2 through 1, but you can see 1 through 2. There are some screenshots in the following album for more clarification: [url="http://imgur.com/a/JsvL5"]http://imgur.com/a/JsvL5[/url] I thought it might be an issue with culling, blending or depth testing.. but all of that seems to be set up properly too. Disabling the Skybox fixes the behaviour on the first cube, but if you look through the second cube into the first, the issue reappears, as previously mentioned. Also worth noting that I'm using SDL with GLEW (although no shaders are currently active). This is probably a simple issue (or at least I hope so and I'm just completely blind), so if anyone has any thoughts or can help in any way with respect to this issue, it would be greatly appreciated. Thank you! OpenGL Initialization Calls: [code] if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0) { return false; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, settings->verticalSync ? 1 : 0); if((m_graphics = SDL_SetVideoMode(settings->windowWidth, settings->windowHeight, 0, SDL_OPENGL | (settings->fullScreen ? SDL_FULLSCREEN : 0))) == NULL) { return false; } glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glViewport(0, 0, settings->windowWidth, settings->windowHeight); [/code] Draw Function (with unnecessary code omitted): [code] void Game::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glEnable(GL_CULL_FACE); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(70.0f, (GLfloat) settings->windowWidth / (GLfloat) settings->windowHeight, 0.1f, 10000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // draw skybox // setup camera // draw cubes glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, settings->windowWidth, settings->windowHeight, 0); // draw text stuff SDL_GL_SwapBuffers(); } [/code]
  4. Found the solution to all my issues finally, after consulting some friends. Turns out Visual Studio 2008 on Windows 7 would use the operating system's version of OpenGL, and when I ran it from the EXE it used the local OpenGL32.dll which was either out of date, or built for the wrong platform. So, removing this DLL fixed all framerate issues, and now runs no problem after defaulting to the operating system's OpenGL32.dll. Hopefully this helps anyone else who runs into this issue!
  5. Singletons definitely help, so long as you implement them properly. For example, I use a "variation" of this, wherein my "Game" object contains static pointers to various modules (including itself), such as: Settings Manager, Resource Manager, World, Console, Menu, etc. If you first create the different "modules", and initialize them later, this will allow them to access each other without really needing to worry about dependencies, if it makes any sense. Anyways, it works well for me.
  6. The best GUI

    I would also second Qt, I think it's fantastic. There is also an extensive library available at your disposal. See: http://doc.qt.nokia.com/5.0-snapshot/qtcore.html Qt is perfectly fine for desktop programs, you will want to look into QtCreator as well if you choose to use it.
  7. http://new.livestream.com/ http://www.fraps.com/
  8. Not as far as I know, I'm using glLists for my SkyBox, and standard OpenGL stuff for the rest, see code below. The only strange thing I'm doing is using SDL_ttf which uses SDL_Surface to blit text which I convert to an OpenGL texture. Irregardless, I don't think any of this should be an issue if it works perfectly fine from Visual Studio 2008, right? Edit: Furthermore, there are no problems on Windows XP when running from either VS2008 or EXE. So why is it such a problem on Windows 7? I'm using platform independent libraries (ie. no STL), so I'm still completely baffled. SkyBox Load: [code] bool SkyBox::load() { if(m_loaded) { return true; } for(int i=0;i<6;i++) { m_textures[i] = Game::resources->getTexture(m_textureNames[i]); if(m_textures[i] == NULL) { return false; } if(!m_textures[i]->load()) { return false; } } m_skyBoxList = glGenLists(6); float width = (float) (m_textures[0]->getWidth() - 1) / (float) m_textures[0]->getWidth(); // left side glNewList(m_skyBoxList, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(1 - width, width); glVertex3d(-0.5, 0.5, 0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(-0.5, -0.5, 0.5); glTexCoord2d(width, 1 - width); glVertex3d(-0.5, -0.5, -0.5); glTexCoord2d(width, width); glVertex3d(-0.5, 0.5, -0.5); glEnd(); glEndList(); // right side glNewList(m_skyBoxList + 1, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(1 - width, width); glVertex3d(0.5, 0.5, -0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(0.5, -0.5, -0.5); glTexCoord2d(width, 1 - width); glVertex3d(0.5, -0.5, 0.5); glTexCoord2d(width, width); glVertex3d(0.5, 0.5, 0.5); glEnd(); glEndList(); // front side glNewList(m_skyBoxList + 2, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(1 - width, width); glVertex3d(-0.5, 0.5, -0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(-0.5, -0.5, -0.5); glTexCoord2d(width, 1 - width); glVertex3d(0.5, -0.5, -0.5); glTexCoord2d(width, width); glVertex3d(0.5, 0.5, -0.5); glEnd(); glEndList(); // back side glNewList(m_skyBoxList + 3, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(1 - width, width); glVertex3d(0.5, 0.5, 0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(0.5, -0.5, 0.5); glTexCoord2d(width, 1 - width); glVertex3d(-0.5, -0.5, 0.5); glTexCoord2d(width, width); glVertex3d(-0.5, 0.5, 0.5); glEnd(); glEndList(); // top side glNewList(m_skyBoxList + 4, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(width, 1 - width); glVertex3d(-0.5, 0.5, 0.5); glTexCoord2d(width, width); glVertex3d(-0.5, 0.5, -0.5); glTexCoord2d(1 - width, width); glVertex3d(0.5, 0.5, -0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(0.5, 0.5, 0.5); glEnd(); glEndList(); // bottom side glNewList(m_skyBoxList + 5, GL_COMPILE); glBegin(GL_POLYGON); glTexCoord2d(width, 1 - width); glVertex3d(-0.5, -0.5, -0.5); glTexCoord2d(width, width); glVertex3d(-0.5, -0.5, 0.5); glTexCoord2d(1 - width, width); glVertex3d(0.5, -0.5, 0.5); glTexCoord2d(1 - width, 1 - width); glVertex3d(0.5, -0.5, -0.5); glEnd(); glEndList(); m_loaded = true; return true; } [/code] SkyBox Draw: [code] void SkyBox::draw() { if(!m_loaded) { return; } glDisable(GL_DEPTH_TEST); glLoadIdentity(); glRotated(Game::camera->getRotation().x, 1, 0, 0); glRotated(Game::camera->getRotation().y, 0, 1, 0); for(int i=0;i<6;i++) { m_textures[i]->activate(); glCallList(m_skyBoxList + i); } glEnable(GL_DEPTH_TEST); } [/code] Game Draw: [code] void Game::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // set up 3d rendering glEnable(GL_TEXTURE_2D); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(70.0f, (GLfloat) settings->windowWidth / (GLfloat) settings->windowHeight, 0.1f, 10000.0f); glMatrixMode(GL_MODELVIEW); // render skybox if(skyBox != NULL) { skyBox->draw(); } // render world if(mainShader != NULL) { mainShader->activate(); } glPushMatrix(); camera->setup(); glScalef(100, 100, 100); glBegin(GL_POLYGON); // left glVertex3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 0.0f); // right glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, -1.0f, 0.0f); glVertex3f(0.0f, -1.0f, -1.0f); glVertex3f(0.0f, 0.0f, -1.0f); // front glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glVertex3f(0.0f, -1.0f, 0.0f); // back glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(0.0f, -1.0f, -1.0f); // top glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 0.0f, 0.0f); // bottom glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glEnd(); glPopMatrix(); if(mainShader != NULL) { mainShader->deactivate(); } // set up 2d rendering glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, settings->windowWidth, settings->windowHeight, 0); // render hud / gui elements displayFPS(); menu->draw(); console->draw(); SDL_GL_SwapBuffers(); } [/code] Font Draw / Load: [code] void Font::drawTextHelper(int x, int y, const char * text) const { if(!m_loaded) { return; } glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBindTexture(GL_TEXTURE_2D, m_texture); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslated(x, y, 0); glListBase(m_font - 32); glCallLists(strlen(text), GL_BYTE, text); glPopMatrix(); } bool Font::load() { if(m_loaded) { return true; } QString fontPath = QString("%1/Fonts/%2").arg(Game::settings->dataDirectoryName).arg(m_fileName); QFileInfo fontFile(fontPath); if(!fontFile.exists()) { return false; } QByteArray bytes = fontPath.toLocal8Bit(); TTF_Font * fontData; if(!(fontData = TTF_OpenFont(bytes.data(), m_size))) { return false; } SDL_Color colour = {255, 255, 255, 255}; SDL_Surface * character; QVector characters; int maxWidth = -1; int maxHeight = -1; char data[2]; data[1] = '\0'; for(int i=0;i<128;i++ ) { data[0] = (char) (i + 32); character = TTF_RenderText_Blended(fontData, data, colour); characters.push_back(character); if(maxWidth < 0 || maxWidth < character->w) { maxWidth = character->w; } if(maxHeight < 0 || maxHeight < character->h) { maxHeight = character->h; } } m_horizontalSpacing = maxWidth; m_verticalSpacing = maxHeight; int width = 1, tempWidth = maxWidth * 16; int height = 1, tempHeight = maxHeight * 8; while(width < tempWidth) { width *= 2; } while(height < tempHeight) { height *= 2; } SDL_Surface * temp = SDL_CreateRGBSurface(0, width, height, 32, #if SDL_BYTEORDER == SDL_BIG_ENDIAN 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #else 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #endif ); SDL_Rect sourceArea, destArea; int x = 0; int y = 0; for(int i=0;i<128;i++) { sourceArea.x = 0; sourceArea.y = 0; sourceArea.w = characters[i]->w; sourceArea.h = characters[i]->h; destArea.x = maxWidth * x; destArea.y = maxHeight * y; destArea.w = characters[i]->w; destArea.h = characters[i]->h; SDL_SetAlpha(characters[i], 0, 0); SDL_BlitSurface(characters[i], &sourceArea, temp, &destArea); x++; if(x == 16) { x = 0; y++; } } glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); m_font = glGenLists(128); x = 0; y = 0; float w = (float) maxWidth / (float) (temp->w); float h = (float) maxHeight / (float) (temp->h); for(int i=0;i<128;i++) { glNewList(m_font + i, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f((w * x), ((h * y))); glVertex2i(0, 0); glTexCoord2f((w * x) + w, ((h * y))); glVertex2i(maxWidth, 0); glTexCoord2f((w * x) + w, ((h * y) + h)); glVertex2i(maxWidth, maxHeight); glTexCoord2f((w * x), ((h * y) + h)); glVertex2i(0, maxHeight); glEnd(); glTranslated(maxWidth, 0, 0); glEndList(); x++; if(x == 16) { x = 0; y++; } } for(int i=0;i<128;i++) { SDL_FreeSurface(characters[i]); } SDL_FreeSurface(temp); m_loaded = true; return true; } [/code]
  9. Oh dear, I feel ashamed for implementing that wrong. Thanks for the reply! Although this did not fix my previous issues (slow framerate, shaders unsupported), it did fix my input handling and bizarre behaviours I was experiencing with my camera which I had yet to solve, so thanks! Still looking for a solution, though. I just can't figure what's so different with the execution of the game between being run from Visual Studio 2008 vs. from the compiled release executable.
  10. Hello! I've been working on a project off and on in SDL for a number of months now, and I've had an issue from the start that I recently had some time to try and debug. I've been developing on Windows XP until this past week, so it was not really an issue until now. Basically, my SDL bases game works perfectly fine on any Windows XP machine (ie. normal frame rate, shaders work no problem), but I initially noticed that if I ran the executable on Windows 7, the frame rate would only be 10-15 for no reason (on super high-end machines, ie. Phenom II X6 / 5970) but this was strictly a Windows 7 issue as indicated by testing on several different machines. Upon further investigation I realized that if I run the game from within Visual Studio 2008 on a Windows 7 machine it works perfectly (ie. 7000+ FPS w/o vsync), but as soon as I ran it from the executable instead, the frame rate would once again be between 10 and 15, and if shaders were being used via GLEW, the program would simply exit because GLEW 2.0 was unavailable. tldr; SDL OpenGL game, works fine on XP, on Win7 works fine in VS2008 but EXE limited to 10 fps and shaders wont work Honestly not sure what the issue could possibly be and has been baffling me for some time. If anyone has any suggestions or input, it would be greatly appreciated. It almost seems like SDL is somehow switching to software mode or some limited version of OpenGL. Also worth mentioning that the only things being rendered is some text (generated and rendered via lists) and a very simple skybox with 1024x1024 textures for each side. My game is using SDLmain and a number of libraries, including: SDL SDL_ttf GLEW FreeImage Qt FMOD Ex FBX SDK Bullet Physics Thanks for reading. Some code, if it helps any: Main.cpp: [CODE] #include "Game.h" int main(int argc, char * argv[]) { Game * game = new Game(); if(!game->init()) { return -1; } game->run(); delete game; return 0; } [/CODE] OpenGL Setup: [CODE] bool Game::init() { if(m_initialized) { return false; } settings->load(); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) == -1) { return false; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, settings->verticalSync ? 1 : 0); m_graphics = SDL_SetVideoMode(settings->windowWidth, settings->windowHeight, 0, SDL_OPENGL | (settings->fullScreen ? SDL_FULLSCREEN : 0)); SDL_WM_SetCaption("Game", NULL); QString iconPath; iconPath.append(QString("%1/Icons/Block.bmp").arg(settings->dataDirectoryName)); QByteArray iconPathBytes = iconPath.toLocal8Bit(); m_icon = SDL_LoadBMP(iconPathBytes.data()); SDL_WM_SetIcon(m_icon, NULL); glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glMatrixMode(GL_MODELVIEW); glViewport(0, 0, settings->windowWidth, settings->windowHeight); if(glewInit() != GLEW_OK) { return false; } if(!GLEW_VERSION_2_0) { return false; } etc. [/CODE] Game Loop: [CODE] void Game::run() { if(!m_initialized) { return; } m_running = true; SDL_Event event; static unsigned int lastTime = SDL_GetTicks(); unsigned int currentTime = SDL_GetTicks(); do { if(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: if(!console->isActive()) { menu->handleInput(event); } if(!menu->isActive()) { console->handleInput(event); } break; case SDL_MOUSEMOTION: if(!console->isActive() && !menu->isActive() && SDL_GetAppState() & SDL_APPMOUSEFOCUS && SDL_GetAppState() & SDL_APPINPUTFOCUS && SDL_GetAppState() & SDL_APPACTIVE) { camera->handleInput(event); } break; case SDL_QUIT: m_running = false; break; default: break; } } if(m_running) { currentTime = SDL_GetTicks(); update(currentTime - lastTime); draw(); lastTime = currentTime; } } while(m_running); } [/CODE]
  11. Finally solved all of the problems I was having after much frustration. Here's my solution code to anyone who has run into the same problems I have - hopefully it is helpful: Font.h [code] #ifndef FONT_H #define FONT_H #include "SDL/SDL.h" #include "SDL/SDL_OpenGL.h" #include "SDL/SDL_TTF.h" #include "Utilities.h" class Font { public: Font(const char * id, const char * filename, int size); Font(const Font & f); Font & operator = (const Font & f); virtual ~Font(); const char * getID() const; const char * getFilename() const; int getSize() const; int getHorizontalSpacing(); int getVerticalSpacing(); void drawText(int x, int y, const char * format, ...) const; bool load(); bool unload(); bool isLoaded() const; bool operator == (const Font & f) const; bool operator != (const Font & f) const; protected: char * m_id; char * m_filename; int m_size; int m_horizontalSpacing; int m_verticalSpacing; GLuint m_texture; GLuint m_font; bool m_loaded; }; #endif // FONT_H [/code] Font.cpp [code] #include "Game.h" #include "Font.h" Font::Font(const char * id, const char * filename, int size) : m_loaded(false) { if(id == NULL) { m_id = new char[1]; m_id[0] = '\0'; } else { m_id = strtrimcpy(id); } if(filename == NULL) { m_filename = new char[1]; m_filename[0] = '\0'; } else { m_filename = strtrimcpy(filename); } m_size = (size < 1) ? 1 : size; } Font::Font(const Font & f) { m_id = new char[strlen(f.m_id) + 1]; strcpy_s(m_id, strlen(f.m_id) + 1, f.m_id); m_filename = new char[strlen(f.m_filename) + 1]; strcpy_s(m_filename, strlen(f.m_filename) + 1, f.m_filename); m_size = f.m_size; } Font & Font::operator = (const Font & f) { unload(); delete [] m_id; delete [] m_filename; m_id = new char[strlen(f.m_id) + 1]; strcpy_s(m_id, strlen(f.m_id) + 1, f.m_id); m_filename = new char[strlen(f.m_filename) + 1]; strcpy_s(m_filename, strlen(f.m_filename) + 1, f.m_filename); m_size = f.m_size; return *this; } Font::~Font() { unload(); delete [] m_id; delete [] m_filename; } const char * Font::getID() const { return m_id; } const char * Font::getFilename() const { return m_filename; } int Font::getSize() const { return m_size; } int Font::getHorizontalSpacing() { return m_horizontalSpacing; } int Font::getVerticalSpacing() { return m_verticalSpacing; } void Font::drawText(int x, int y, const char * format, ...) const { if(!m_loaded) { return; } char text[256]; va_list args; va_start(args, format); vsprintf_s(text, 256, format, args); va_end(args); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBindTexture(GL_TEXTURE_2D, m_texture); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslated(x, y, 0); glListBase(m_font - 32); glCallLists(strlen(text), GL_BYTE, text); glPopMatrix(); } bool Font::load() { if(m_loaded) { return true; } QString fontPath = QString(Game::settings->dataDirectory); fontPath.append("/Fonts/"); fontPath.append(m_filename); QFileInfo fontFile(fontPath); if(!fontFile.exists()) { return false; } QByteArray bytes = fontPath.toLocal8Bit(); TTF_Font * fontData; if(!(fontData = TTF_OpenFont(bytes.data(), m_size))) { return false; } SDL_Color colour = {255, 255, 255, 255}; SDL_Surface * character; QVector<SDL_Surface *> characters; int maxWidth = -1; int maxHeight = -1; char data[2]; data[1] = '\0'; for(int i=0;i<128;i++ ) { data[0] = (char) (i + 32); character = TTF_RenderText_Blended(fontData, data, colour); characters.push_back(character); if(maxWidth < 0 || maxWidth < character->w) { maxWidth = character->w; } if(maxHeight < 0 || maxHeight < character->h) { maxHeight = character->h; } } m_horizontalSpacing = maxWidth; m_verticalSpacing = maxHeight; int width = 1, tempWidth = maxWidth * 16; int height = 1, tempHeight = maxHeight * 8; while(width < tempWidth) { width *= 2; } while(height < tempHeight) { height *= 2; } SDL_Surface * temp = SDL_CreateRGBSurface(0, width, height, 32, #if SDL_BYTEORDER == SDL_BIG_ENDIAN 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #else 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #endif ); SDL_Rect sourceArea, destArea; int x = 0; int y = 0; for(int i=0;i<128;i++) { sourceArea.x = 0; sourceArea.y = 0; sourceArea.w = characters[i]->w; sourceArea.h = characters[i]->h; destArea.x = maxWidth * x; destArea.y = maxHeight * y; destArea.w = characters[i]->w; destArea.h = characters[i]->h; SDL_SetAlpha(characters[i], 0, 0); SDL_BlitSurface(characters[i], &sourceArea, temp, &destArea); x++; if(x == 16) { x = 0; y++; } } glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); m_font = glGenLists(128); x = 0; y = 0; float w = (float) maxWidth / (float) (temp->w); float h = (float) maxHeight / (float) (temp->h); for(int i=0;i<128;i++) { glNewList(m_font + i, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f((w * x), ((h * y))); glVertex2i(0, 0); glTexCoord2f((w * x) + w, ((h * y))); glVertex2i(maxWidth, 0); glTexCoord2f((w * x) + w, ((h * y) + h)); glVertex2i(maxWidth, maxHeight); glTexCoord2f((w * x), ((h * y) + h)); glVertex2i(0, maxHeight); glEnd(); glTranslated(maxWidth, 0, 0); glEndList(); x++; if(x == 16) { x = 0; y++; } } for(int i=0;i<128;i++) { SDL_FreeSurface(characters[i]); } SDL_FreeSurface(temp); m_loaded = true; return true; } bool Font::unload() { if(!m_loaded) { return true; } glDeleteLists(m_font, 128); glDeleteTextures(1, &m_texture); m_loaded = false; return true; } bool Font::isLoaded() const { return m_loaded; } bool Font::operator == (const Font & f) const { return _stricmp(m_id, f.m_id) == 0 && _stricmp(m_filename, f.m_filename) == 0 && m_size == f.m_size; } bool Font::operator != (const Font & f) const { return !operator == (f); } [/code]
  12. Okay, so I'm attempting to create dynamic font loading from TTF files using SDL_TTF / SDL / OpenGL. (Also note I am using the QtCore library as well.) The general idea of what my code is doing is as follows: Loading: 1) Generate font path and attempt to load the font using SDL_TTF 2) Render 128 characters to individual SDL_Surfaces, from character 32 to 160 3) Keep track of the size of the largest characters 4) Create a new surface to render all 128 characters onto based on the largest width and height (also make sure it is a power of 2 to prevent scaling) 5) Iterate over all 128 of the characters, rendering to them to the full surface (16x8) 6) Create an OpenGL texture from the data contained in the full surface 7) Create an OpenGL list of all of the characters for ease of use when rendering text later Rendering: 1) Generate output text data based on format string and arguments passed in 2) Use glCallLists to render the string using the previously generated font data It's been somewhat successful so far, but I have hit two major snags: 1) SDL_Surfaces store pixel data upside down. I've read about this issue online, but have not found any simple solutions to this. I ultimately did find some code to flip the texture upside-down, but it seemed like an unnecessary amount of code to do so - and it still didn't fix the problem. In short, if I blit to an SDL_Surface, then attempt to make an OpenGL texture out of it, the image is upside-down when rendered. And since I'm generating the image on runtime, having an upside-down input file is not an option. 2) The text shows up yellow instead of white, as specified by the SDL_Color struct. I also found others online who had this same issue, but have not managed to find a solution. When the temp SDL_Surface is allocated, I had to change the RGBA masks to BGRA instead of the usual RGBA / ABGR depending on what endian SDL is using in order to have anything show up at all. I'm not sure if I horribly messed this up or not, but it's the only thing that produces any results thus far. I also tried SDL_DisplayFormat on the surface I was generating, but no matter what I change the RGBA masks to after that, there is no output. I have attached a quad displaying the full image output at the bottom as well as relevant source code. If anyone has any advice / tips / hints / suggestions / solutions / etc. to this problem, they would be tremendously appreciated. I'll gladly surf around the forums and help other people out as well afterwards, seeing as how this is my first post. Thanks so much! Edit: I just realized the texture co-ordinates are semi wrong when generating the lists, they're for a 16x16 grid, but the one I'm using is 16x8. They also don't account for non-perfect fit textures (ie. whitespace on the "top" and "right" to make the texture a power of 2, to prevent automatic scaling). Font Loading: [code] bool Font::load() { if(m_loaded) { return true; } QString fontPath = QString(Game::settings->dataDirectory); fontPath.append("/Fonts/"); fontPath.append(m_filename); QFileInfo fontFile(fontPath); if(!fontFile.exists()) { return false; } QByteArray bytes = fontPath.toLocal8Bit(); TTF_Font * fontData; if(!(fontData = TTF_OpenFont(bytes.data(), m_size))) { return false; } SDL_Color colour = {255, 255, 255, 255}; SDL_Surface * character; QVector<SDL_Surface *> characters; int maxWidth = -1; int maxHeight = -1; char data[2]; data[1] = '\0'; for(int i=0;i<128;i++ ) { data[0] = (char) (i + 32); character = TTF_RenderText_Blended(fontData, data, colour); characters.push_back(character); if(maxWidth < 0 || maxWidth < character->w) { maxWidth = character->w; } if(maxHeight < 0 || maxHeight < character->h) { maxHeight = character->h; } } int width = 1, tempWidth = maxWidth * 16; int height = 1, tempHeight = maxHeight * 8; while(width < tempWidth) { width *= 2; } while(height < tempHeight) { height *= 2; } SDL_Surface * temp = SDL_CreateRGBSurface(0, width, height, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff); SDL_Rect sourceArea, destArea; int x = 0; int y = 0; for(int i=0;i<128;i++) { sourceArea.x = 0; sourceArea.y = 0; sourceArea.w = characters[i]->w; sourceArea.h = characters[i]->h; destArea.x = maxWidth * x; destArea.y = maxHeight * y; destArea.w = characters[i]->w; destArea.h = characters[i]->h; SDL_BlitSurface(characters[i], &sourceArea, temp, &destArea); x++; if(x == 16) { x = 0; y++; } } glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp->pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); m_font = glGenLists(128); float cx, cy; for(int i=0;i<128;i++) { cx = (float) (i % 16) / 16.0f; cy = (float) (i / 16) / 16.0f; glNewList(m_font + i, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f(cx, 1 - cy - 0.0625f); glVertex2i(0, m_size); glTexCoord2f(cx + 0.0625f, 1 - cy - 0.0625f); glVertex2i(m_size, m_size); glTexCoord2f(cx + 0.0625f, 1 - cy ); glVertex2i(m_size, 0 ); glTexCoord2f(cx, 1 - cy ); glVertex2i(0, 0 ); glEnd(); glTranslated(10, 0, 0); glEndList(); } for(int i=0;i<128;i++) { SDL_FreeSurface(characters[i]); } SDL_FreeSurface(temp); m_loaded = true; return true; } [/code] Text Drawing: [code] void Font::drawText(int x, int y, const char * format, ...) const { if(!m_loaded) { return; } char text[256]; va_list args; va_start(args, format); vsprintf_s(text, 256, format, args); va_end(args); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBindTexture(GL_TEXTURE_2D, m_texture); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslated(x, y, 0); glListBase(m_font - 32); glCallLists(strlen(text), GL_BYTE, text); glPopMatrix(); } [/code] Output: [attachment=4116:font_texture.png]