Jump to content
  • Advertisement

Zorbfish

Member
  • Content Count

    335
  • Joined

  • Last visited

Community Reputation

214 Neutral

About Zorbfish

  • Rank
    Member
  1. I've been working on font rendering in OpenGL and have run into a big of a snag. When copying the bitmap generated by the FreeType library into an OpenGL texture the bitmap is not rendered correctly. After many hours of debugging/traces I believe it is related to the format of the texture and possibly that I am not providing the data in the correct alignment; but I am unsure (I have not worked with OpenGL for a LONG time). I'm hoping a few more eyes here can help me pick up on my mistake. Thanks. Here's the example code I was working with: #include <SDL.h> #include <windows.h> #include <GL\GL.h> #include "ft2build.h" #include <freetype/freetype.h> #include <freetype/ftglyph.h> #include <freetype/ftoutln.h> #include <freetype/fttrigon.h> #include FT_FREETYPE_H #include <stdio.h> typedef struct { int width; int height; int xoffset; int yoffset; float texels[4]; } Glyph; int SDL_main(int argc, char *argA[]) { SDL_Event event = {0}; int running = 1; GLuint texture = 0; GLubyte *empty_data = 0; int x = 50; int y = 50; int i, j; int ok = 0; const GLsizei TEXTURE_SIZE = 128; FT_Library lib; FT_Face face; FT_Bitmap *bitmap; FT_Glyph glyph; FT_BitmapGlyph bitmap_glyph; GLubyte* padded_bitmap; int bw = 0; int bh = 0; int texNext = 0; FT_UInt b_glyph = 0; FT_UInt A_glyph = 0; Glyph b, A; FT_Vector kerning = {0}; FILE *test; ok = !FT_Init_FreeType(&lib); if (ok) { FT_New_Face(lib, "Verdana.ttf", 0, &face); FT_Set_Char_Size(face, 16*64, 16*64, 96, 96); } SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_SetVideoMode(800, 600, 24, SDL_OPENGL); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); empty_data = calloc(2 * TEXTURE_SIZE * TEXTURE_SIZE, sizeof(GLubyte)); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_SIZE, TEXTURE_SIZE, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, empty_data); free(empty_data); test = fopen("out.txt", "w"); b_glyph = FT_Get_Char_Index(face, 'b'); FT_Load_Char(face, 'b', FT_LOAD_DEFAULT); FT_Get_Glyph(face->glyph, &glyph); if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); } bitmap_glyph = (FT_BitmapGlyph)glyph; bitmap = &bitmap_glyph->bitmap; bw = bitmap->width; bh = bitmap->rows; /* pad to add alpha */ padded_bitmap = calloc(2 * bw * bh, sizeof(GLubyte)); memset(padded_bitmap, 0, 2*bw*bh*sizeof(GLubyte)); for(j = 0; j < bh; j++) { for(i = 0; i < bw; i++) { padded_bitmap[2 * (i + j * bw)] = 255; padded_bitmap[2 * (i + j * bw) + 1] = bitmap->buffer[(i + j * bw)]; putc(bitmap->buffer[(i + j * bw)] > 128 ? ' ' : '.', test); } putc('\n', test); } putc('\n', test); b.width = bw; b.height = bh; b.texels[0] = 0.0; b.texels[1] = 0.0; b.xoffset = face->glyph->bitmap_left; b.yoffset = face->glyph->bitmap_top; b.texels[2] = b.texels[0] + b.width / (float)TEXTURE_SIZE; b.texels[3] = b.texels[1] + b.height / (float)TEXTURE_SIZE; texNext += bw; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap->width, bitmap->rows, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, padded_bitmap); free(padded_bitmap); A_glyph = FT_Get_Char_Index(face, 'A'); FT_Load_Char(face, 'A', FT_LOAD_DEFAULT); FT_Get_Glyph(face->glyph, &glyph); if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); } bitmap_glyph = (FT_BitmapGlyph)glyph; bitmap = &bitmap_glyph->bitmap; bw = bitmap->width; bh = bitmap->rows; padded_bitmap = calloc(2 * bw * bh, sizeof(GLubyte)); for(j = 0; j < bh; j++) { for(i = 0; i < bw; i++) { padded_bitmap[2 * (i + j * bw)] = 255; padded_bitmap[2 * (i + j * bw) + 1] = bitmap->buffer[i + bitmap->width * j]; putc(bitmap->buffer[(i + j * bw)] > 128 ? ' ' : '.', test); } putc('\n', test); } putc('\n', test); for(j = 0; j < bh; j++) { for(i = 0; i < bw; i++) { padded_bitmap[2 * (i + j * bw)] = 255; padded_bitmap[2 * (i + j * bw) + 1] = bitmap->buffer[i + bitmap->width * j]; putc(padded_bitmap[2 * (i + j * bw) + 1] > 128 ? ' ' : '.', test); } putc('\n', test); } fclose(test); A.width = bw; A.height = bh; A.xoffset = face->glyph->bitmap_left; A.yoffset = face->glyph->bitmap_top; A.texels[0] = (float)texNext / (float)TEXTURE_SIZE; A.texels[1] = (float)0 / (float)TEXTURE_SIZE; A.texels[2] = A.texels[0] + A.width / (float)TEXTURE_SIZE; A.texels[3] = A.texels[1] + A.height / (float)TEXTURE_SIZE; glTexSubImage2D(GL_TEXTURE_2D, 0, texNext, 0, bitmap->width, bitmap->rows, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, padded_bitmap); free(padded_bitmap); glMatrixMode(GL_PROJECTION); glOrtho(0, 800, 600, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glTranslated(0.00735, 0.00735, 0.0); while (running) { glClearColor(0, 0, 1, 0); glClear(GL_COLOR_BUFFER_BIT); SDL_WaitEvent(&event); switch (event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { running = 0; break; } case SDL_QUIT: running = 0; break; default: ; } FT_Get_Kerning(face, A_glyph, b_glyph, FT_KERNING_DEFAULT, &kerning); glBegin(GL_QUADS); /*b*/ glTexCoord2d(b.texels[0], b.texels[1]); glVertex2i(x, y-b.yoffset); glTexCoord2d(b.texels[0], b.texels[3]); glVertex2i(x, y+b.height-b.yoffset); glTexCoord2d(b.texels[2], b.texels[3]); glVertex2i(x+b.width, y+b.height-b.yoffset); glTexCoord2d(b.texels[2], b.texels[1]); glVertex2i(x+b.width, y-b.yoffset); /*A*/ glTexCoord2d(A.texels[0], A.texels[1]); glVertex2i(texNext+(kerning.x>>6)+x, y-A.yoffset); glTexCoord2d(A.texels[0], A.texels[3]); glVertex2i(texNext+(kerning.x>>6)+x, y+A.height-A.yoffset); glTexCoord2d(A.texels[2], A.texels[3]); glVertex2i(texNext+(kerning.x>>6)+x+A.width, y+A.height-A.yoffset); glTexCoord2d(A.texels[2], A.texels[1]); glVertex2i(texNext+(kerning.x>>6)+x+A.width, y-A.yoffset); glEnd(); SDL_GL_SwapBuffers(); } glDeleteTextures(1, &texture); if (ok) { FT_Done_Face(face); FT_Done_FreeType(lib); } SDL_Quit(); return 0; } And here's an ASCII rep of the output. Notice that the Freetype bitmaps are rendering correctly (also I have no idea why 'b' is so messed up): Freetype's returned bitmaps: ......... ......... ......... ......... .. ... .. .... .. ...... . ...... . ...... . ...... . ...... . ...... . ..... .. ... .... ...... ...... ..... ...... ..... ..... ..... . ..... .... .. ..... .... .. .... .... ... .... ... .... .... ... .... ... ... ..... ... .. ... .. .. .. ....... .. . ........ .. . ......... . ......... . What ends up on the screen: ......... ... ...... ........ . ......... .. ... .. .... .. . ..... . ...... . ...... . ...... . ..... . . ...... . ..... .. ... .... . . ... ... ... ............... ...... . ..... ........ . . . . .... ........ .. ...... ....... .... ........ ... ........ .. . ......... .. ......... .. ........ ... ....... .. .. ....... ... . ...... .... . ..... ..... .... ....... ... ........ ... ......... . ......... . ............
  2. Have you tried adding the data from the stack before the call to the environment table? The protected call will inheirit that same environment during the call's scope which should make the data accessible.
  3. Zorbfish

    Calling a Lua script

    You need to store the function created by the load somewhere. When Lua performs the load it actually compiles your file into a function and leaves it on the stack. Calling the script once will consume (pop) that function from the stack so on your next frame it cannot find the function. So what you need to do is after you load the file, store the function somewhere. When you want to call the function make a copy of it (using lua_pushvalue) and then perform your pcall. Hope that helps.
  4. Quote:Original post by geolycosa I read about the lua_newthread() function, which looks like it could solve some of my problems (a new state with it's own stack, but a shared global table), but I'm not clear on weather or not this function actually spawns a new OS thread (which I don't need). No. lua_newthread creates a new coroutine (the Lua equivalent is coroutine.create) . No OS threads are created by Lua because multithreading is not portable and usually unnecessary.
  5. Zorbfish

    Lua as a config file alternative [C++]

    //NOTE: myUsername is a char* (maybe the problem?) Yes. You cannot simply assign a char pointer like that in C. What you need to do is allocate enough space for the string and copy the value from Lua to your new string. void getUsername(lua_State *luaVm) { char *myUsername = {0}; size_t len = 0; /* stack the string and measure its length */ lua_getglobal(luaVm, "UserName"); len = lua_objlen(luaVm, -1); /* allocate and copy */ myUsername = calloc(len, sizeof(char)); strcpy(myUsername, lua_tostring(L, -1); } EDIT: I know you said you are using C++ but a char* is not a C++ string. Just clarifying myself.
  6. Zorbfish

    [Lua] Getting arrays of strings from C?

    Watch your indices, phantom :) Should be lua_gettable(lua_state, -2), or just use lua_rawgeti(lua_State, -1, 0).
  7. Quote:Original post by zer0wolf Which of those specifically would a tester have to download to run your game, if any? lua5_1_2_Win32_bin.zip or lua5_1_2_Win64_bin.zip depending on your platform. I could include the interpreter with the game (its small enough) if testers would prefer that.
  8. I'm in. I'm going to use Lua.
  9. Zorbfish

    ToLua Tutorial

    Well the problem is that for most Lua related projects the manual is treated as the definitive documentation. You didn't mention whether or not you had looked at the manual for toLua, but here it is for reference. An updated version can be found as part of the toLua++ package here. Maybe this would be more useful because I think toLua++ is still actively being developed.
  10. Zorbfish

    Lua + SDL

    That module is outdated. If you check the readme file it clearly states it only works with Lua 4.0. The error output mentions the package module so I assume you are using version 5.1 which is incompatible. There are few options. One, you can download LuaSDL off of LuaForge.net. This is a derivative implementation of the same module. Another option is to use LuaX which is a custom distribution of Lua that includes SDL. Both options will require you to use something other than stock Lua though. I do have a SDL prototype I built for Lua5.1. It was my final project topic I chose for my Computer Science degree. I haven't released it yet because its still lacking real polish but if you're interested pm me and I'll provide you a copy to play with.
  11. Zorbfish

    WWE Chairman gone?

    Considering I had CNN (and CNN Headline news) on in the background while I was coding today and heard it mentioned once I think that's a pretty good indication that this story is going to be largely ignored. The one report just mentioned it in passing and used it as a springboard into a 10 minute segment on why steroids are bad. On the other hand that spoiled twat found Jebus and was released from prison today! I was overjoyed to be informed of that every few minutes...
  12. Zorbfish

    calling a LUA function from C++

    Post all of your C++ code. I assume that you are loading the Lua script before trying to call the function but you did not post those lines so I cannot be sure.
  13. Quote:Original post by future farmer For what it's worth, Atlus is now my favorite game company. Amen. I'm become a huge fan of Atlus as well as Nippon Ichi ever since Kingdom Hearts and Final Fantasy became the only thing keeping Square afloat. Give me a new MegaTen or Disgaea-esque SRPG anyday over what Square Enix is now offering. I guess I've fallen into the niche market for JRPGs now. Slightly Off Topic: Wasn't Level-5 only involved in DQ8 making the engine? I thought that Enix was still pretty much behind the actual game.
  14. lua_pcall's standard behavior when no error function is given is to call debug.traceback and leave that string on the stack. So If you are simply trying to get the stack traceback if a lua_pcall fails its as simple as this: lua_pushcfunction(L, foo); lua_pushnumber(L, 5.3); if (lua_pcall(L, 1, 0, 0) != 0) lua_error(L); As far as indexing is concerned it means you pass the stack position of where you pushed an error function. /* stack the debug.traceback function */ lua_getglobal(L, "debug"); lua_getfield(L, -1, "traceback"); lua_remove(L, -2); lua_pushcfunction(L, foo); lua_pushnumber(L, 5.3); if (lua_pcall(L, 1, 0, -3) != 0) { /* do something */ } If the pcall fails debug.traceback (at stack pos -3) will get called. Hope that helps.
  15. Zorbfish

    Hi I need some advice

    If you are only having problems with building Lua why not use the prebuilt binaries offered by LuaBinaries?. Members of the Lua team have provided this option for a few years and I've never had a problem using them.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!