/** * Compile the shader from file 'filename', with error handling */ int Shader::loadShader(string fileName){ GLint link_ok = GL_FALSE; GLuint vs, fs; string vsName = fileName+".v.glsl"; string fsName = fileName+".f.glsl"; if ((vs = createShader(vsName.c_str(), GL_VERTEX_SHADER)) == 0) return 0; if ((fs = createShader(fsName.c_str(), GL_FRAGMENT_SHADER)) == 0) return 0; program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if (!link_ok) { logWar("glLinkProgram:"); printShaderLog(program); glDeleteShader(vs); glDeleteShader(fs); return -1; } glDeleteShader(vs); glDeleteShader(fs); loadVars(); return 0; }
Text::Text(FT_Face face, int height){ c = new glyphData[256]; color = glm::vec4(0.0f,0.0f,0.0f,1.0f); cIndex = 0; GLuint vs, fs; GLint compile_ok = GL_FALSE, link_ok = GL_FALSE; if(FileSystem::getInstance()->openFile("text.v.glsl") == -1){ logErr("Error opening text.v.glsl"); return; } if(FileSystem::getInstance()->openFile("text.f.glsl") == -1){ logErr("Error opening text.f.glsl"); return; } const char* source = FileSystem::getInstance()->getFileData("text.v.glsl"); if (source == NULL){ logErr("Error data text.v.glsl"); return; } vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &source, NULL); glCompileShader(vs); compile_ok = GL_FALSE; glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok); if(compile_ok == GL_FALSE){ logErr("text.v.glsl"); printShaderLog(vs); glDeleteShader(vs); return; } source = FileSystem::getInstance()->getFileData("text.f.glsl"); if(source == NULL){ logErr("Error data text.f.glsl"); return; } fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &source, NULL); glCompileShader(fs); compile_ok = GL_FALSE; glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok); if(compile_ok == GL_FALSE){ logErr("text.v.glsl"); printShaderLog(fs); glDeleteShader(fs); return; } programText = glCreateProgram(); glAttachShader(programText, vs); glAttachShader(programText, fs); glLinkProgram(programText); glDeleteShader(vs);//these are marked to delete but until they are attached to the program, they will remain glDeleteShader(fs); glGetProgramiv(programText, GL_LINK_STATUS, &link_ok); if(!link_ok){ logWar("glLinkProgram:"); return; } std::string attributeName = "coord"; attribute_coord = glGetAttribLocation(programText, attributeName.c_str()); if(attribute_coord == -1){ logErr("Could not bind attribute %s\n", attributeName.c_str()); return; } attributeName = "tex"; uniform_tex = glGetUniformLocation(programText, attributeName.c_str()); if(uniform_tex == -1){ logErr("Could not bind uniform %s\n", attributeName.c_str()); return; } attributeName = "color"; uniform_color = glGetUniformLocation(programText, attributeName.c_str()); if(uniform_color == -1){ logErr("Could not bind uniform %s\n", attributeName.c_str()); return; } attributeName = "pvmMatrix"; uniform_pvmMatrix = glGetUniformLocation(programText, attributeName.c_str()); if(uniform_pvmMatrix == -1){ logErr("Could not bind uniform %s\n", attributeName.c_str()); return; } vbo = 0; FT_Set_Pixel_Sizes(face, 0, height); FT_GlyphSlot g = face->glyph; int roww = 0; int rowh = 0; w = 0; h = 0; memset(c, 0, sizeof(glyphData) * 256); /* Find minimum size for a texture holding all visible ASCII characters */ for(int i = 32; i < 256; i++){ if(FT_Load_Char(face, i, FT_LOAD_RENDER)){ logErr("Loading character %c failed!\n", i); continue; } if(roww + g->bitmap.width + 1 >= MAXWIDTH){ w = std::max(w, roww); h += rowh; roww = 0; rowh = 0; } roww += g->bitmap.width + 1; rowh = std::max(rowh, g->bitmap.rows); } maxHeight = rowh; w = std::max(w, roww); h += rowh; /* Create a texture that will be used to hold all ASCII glyphs */ glActiveTexture(GL_TEXTURE0); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); /* We require 1 byte alignment when uploading texture data */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* Clamping to edges is important to prevent artifacts when scaling */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); /* Linear filtering usually looks best for text */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* Paste all glyph bitmaps into the texture, remembering the offset */ int ox = 0; int oy = 0; rowh = 0; for(int i = 32; i < 256; i++){ if(FT_Load_Char(face, i, FT_LOAD_RENDER)){ logErr("Loading character %c failed!\n", i); continue; } if(ox + g->bitmap.width + 1 >= MAXWIDTH){ oy += rowh+1; rowh = 0; ox = 0; } glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer); c[i].ax = g->advance.x >> 6; c[i].ay = g->advance.y >> 6; c[i].bw = g->bitmap.width; c[i].bh = g->bitmap.rows; c[i].bl = g->bitmap_left; c[i].bt = g->bitmap_top; c[i].tx = ox / (float)w; c[i].ty = oy / (float)h; rowh = std::max(rowh, g->bitmap.rows); ox += g->bitmap.width + 1; } logErr("Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024); atlasWidth = w; atlasHeight = h; }
Texture::Texture(Image* image){ eraseProtection = false; xRatio = 1.0f; yRatio = 1.0f; nonPowerOfTwo = false; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//);GL_NEAREST glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GLint internalFormat = GL_RGB; format = GL_RGB; logInf("image w:%i h:%i format:%i",image->width,image->height,image->bytes_per_pixel); xSquare = getNextPowerOf2(image->width); ySquare = getNextPowerOf2(image->height); widthOriginal = image->width; heightOriginal = image->height; if(image->bytes_per_pixel == Image::RGBA){ internalFormat = GL_RGBA; format = GL_RGBA; } if(xSquare != image->width || ySquare != image->height){ nonPowerOfTwo = true; logWar("the current image isn't a power of two w:%i h:%i the image will be of w:%i h:%i and cropped", image->width, image->height, xSquare, ySquare); xRatio = (float)image->width / xSquare; yRatio = (float)image->height / ySquare; glTexImage2D(GL_TEXTURE_2D, // target 0, // level, 0 = base, no minimap, internalFormat, // internalformat xSquare, // width ySquare, // height 0, // border, always 0 in OpenGL ES format, // format GL_UNSIGNED_BYTE, // type 0); glTexSubImage2D(GL_TEXTURE_2D, // target 0, // level, 0 = base, no minimap, 0, //xoffset 0, //yoffset image->width, // width image->height, // height format, // format GL_UNSIGNED_BYTE, // type image->pixel_data); return; } glTexImage2D(GL_TEXTURE_2D, // target 0, // level, 0 = base, no minimap, internalFormat, // internalformat image->width, // width image->height, // height 0, // border, always 0 in OpenGL ES format, // format GL_UNSIGNED_BYTE, // type image->pixel_data); }