Issue with texture loading using the DevIl library - opengl

I am working with the DevIl library and trying to use it to load a texture to OpenGL to apply to a sprite. The code is directly out of the C# Game Programming for Serious Game Design book (if that helps). The problem I'm having is with the Il.ilLoadImage call. Even when I pass it null, it doesn't throw an image not found error, and the sprite just shows up dark grey (instead of white) when the form pops up.
public void LoadTexture(string textureId, string path)
{
int devilId = 0;
Il.ilGenImages(1, out devilId);
Il.ilBindImage(devilId);
if (!Il.ilLoadImage(path))
{
System.Diagnostics.Debug.Assert(false, "Could not open file [" + path + "].");
}
//Flip the files before passing them to OpenGl
Ilu.iluFlipImage();
int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH);
int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT);
int openGLId = Ilut.ilutGLBindTexImage();
System.Diagnostics.Debug.Assert(openGLId != 0);
Il.ilDeleteImages(1, ref devilId);
_textureDatabase.Add(textureId, new Texture(openGLId, width, height));
}

DevIL is, rather nonsensically, based on OpenGL's API and general structure. As such, the typical way that errors are reported is with ilGetError. If you want to make sure a function succeeded or not, you should use that.

Related

Copy Freetype Bitmap into Magick::Image at specific offset

In my game engine, I have a texture loading API which wraps low level libraries like OpenGL, DirectX, etc. This API uses Magick++ because I found it to be a convenient cross-platform solution and allows me to create procedural textures fairly easily.
I'm now adding a text rendering system using freetype where I want to use this texture API to dynamically generate a texture atlas for any given font where all the glyphs are stored horizontally adjacent.
I have been able to get this to work in the past by buffering the bitmaps directly into OpenGL. But now I want to accomplish this in a platform independent way, using this API.
I've looked around for a few examples but I can't find anything quite like what I'm after so if there are any magick++ experts around, I'd really appreciate some pointers.
So in simple terms: I've got a freetype bitmap and I want to be able to copy its pixel buffer to a specific offset inside a Magick::Image.
This code might help to clarify:
auto texture = e6::textures->create(e6::texture::specification{}, [name, totalWidth, maxHeight](){
// Initialises Freetype
FT_Face face;
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
}
if (int error = FT_New_Face(ft, path(name.c_str()).c_str(), 0, &face)) {
std::cout << "Failed to initialise fonts: " << name << std::endl;
throw std::exception();
}
// Sets the size of the font
FT_Set_Pixel_Sizes(face, 0, 100);
unsigned int cursor = 0; // Keeps track of the horizontal offset.
// Preallocate an image buffer
// totalWidth and maxHeight is the size of the entire atlas
Magick::Image image(Magick::Geometry(totalWidth, maxHeight), "BLACK");
image.type(Magick::GrayscaleType);
image.magick("BMP");
image.depth(8);
image.modifyImage();
Magick::Pixels view(image);
// Loops through a subset of the ASCII codes
for (uint8_t c = 32; c < 128; c++) {
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
std::cout << "Failed to load glyph: " << c << std::endl;
continue;
}
// Just for clarification...
unsigned int width = face->glyph->bitmap.width;
unsigned int height = face->glyph->bitmap.rows;
unsigned char* image_data = face->glyph->bitmap.buffer;
// This is the problem part.
// How can I copy the image_data into `image` at the cursor position?
cursor += width; // Advance the cursor
}
image.write(std::string(TEXTURES) + "font-test.bmp"); // Write to filesystem
// Clean up freetype
FT_Done_Face(face);
FT_Done_FreeType(ft);
return image;
}, "font-" + name);
I tried using a pixel cache which the documentation demonstrates:
Magick::Quantum *pixels = view.get(cursor, 0, width, height);
*pixels = *image_data;
view.sync();
But this leaves me with a completely black image, I think because the image_data goes out of scope.
I was hoping there'd be a way to modify the image data directly but after a lot of trial and error, I ended up just creating an image for each glyph and compositing them together:
...
Magick::Image glyph (Magick::Geometry(), "BLACK");
glyph.type(MagickCore::GrayscaleType);
glyph.magick("BMP");
glyph.depth(8);
glyph.read(width, height, "R", Magick::StorageType::CharPixel, image_data);
image.composite(glyph, cursor, 0);
cursor += width;
At the very least, I hope this helps to prevent someone else going down the same rabbit hole I did.

Exception "Texture cannot be null" Direct X

I am coding a 2D Game using DirectX11 and DirectXTK.
I did a class Framework that initializes both the window displayed for the game and initializes DirectX. These initializations work correctly. Then, I decided to draw some backgrounds, etc in the window, but after a while it exits on an exception. I did a try{ ... } catch(){ } block, which tells me that "Texture cannot be null". However, i could not find which texture it is talking about, even by debbugging and checking all the values.
I decided to separate the different elements i was drawing in the window, to see where the problem might come from... So now i have 3 draw methods :
Draw(DWORD &elapsedTime);
DrawBackground(DWORD &elapsedTime);
DrawCharacter(DWORD &elapsedTime);
The Draw(DWORD &elapsedTime) method calls both DrawBackground() and DrawCharacter() methods.
Here is my Draw Method :
void Framework::Draw(DWORD * elapsedTime)
{
// Clearing the Back Buffer
immediateContext->ClearRenderTargetView(renderTargetView, Colors::Aquamarine);
//Clearing the depth buffer to max depth (1.0)
immediateContext->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); //immediateContext is a ID3D11DeviceContext*
CommonStates states(d3dDevice); //d3dDevice is a ID3D11Device*
sprites.reset(new SpriteBatch(immediateContext));
sprites->Begin(SpriteSortMode_Deferred, states.NonPremultiplied());
DrawBackground1(elapsedTime);
DrawCharacter(elapsedTime);
sprites->End();
//Presenting the back buffer to the front buffer
swapChain->Present(0, 0);
}
By debugging i am almost sure that the exception comes from both DrawBackground() and DrawCharacter(). Indeed, when I comment those in the Draw method, i have no error, but as soon as i put one it sets the exception after displaying what i want during a few seconds.
Here is the method DrawBackground() for example :
void Framework::DrawBackground1(DWORD * elpasedTime)
{
RECT *try1 = new RECT();
try1->bottom = 0; try1->left = 0; try1->right = (int)WIDTH; try1->bottom = (int)HEIGHT;
ID3D11ShaderResourceView * texture2 = nullptr;
ID3D11ShaderResourceView * textureRV = nullptr;
CreateDDSTextureFromFile(d3dDevice, L"../Images/backgrounds/set2_background.dds", nullptr, &textureRV);
CreateDDSTextureFromFile(d3dDevice, L"../Images/backgrounds/set3_tiles.dds", nullptr, &texture2);
sprites->Draw(textureRV, XMFLOAT2(0, 0), try1, Colors::White);
sprites->Draw(texture2, XMFLOAT2(0, 0), try1, Colors::CornflowerBlue);
}
So as soon as i uncomment this method (or any DrawCharacter(), which follows the same steps), the window displays what i expect it to for a few seconds, but then i get the exception "Texture cannot be null". I also noticed that the method DrawCharacter() lets the window displaying what i want longer than the method DrawBackground(), whose texture is way bigger than the character's one.
I'm not sure if this information is useful but i think that maybe this might be linked to the size of the texture ?
Would you notice anything that i did wrong in this code ? Why would a texture be considered null while it does display it for a while ? I've been looking for answers for a few hours now, some help would be amazing please !
Thank you
I noticed that you create two new ID3D11ShaderResourceView every iteration without Release-ing the old ones. You could try by creating the ShaderResourceViews only once and storing them as global variables, or you could try by ->Release() them after the sprites->Draw(...) calls.

Rounded corners with C++

I'm looking for some c++ drawing graphics library to create rounded corners with anti-aliasing option for dynamic keyboard key creator. I've already tested OpenCV and Magick++ functions but the result was not so good. Can anyone help me with this?
This is a sample of one code to create a rounded corner with Magick++ library
void create_rounded_image (int size, int border) {
Magick::Image image_bk (Magick::Geometry (size, size), Magick::Color ("black"));
image_bk.strokeColor ("white");
image_bk.fillColor ("white");
image_bk.strokeWidth(1);
image_bk.draw (DrawableCircle(size, size, size*0.3, size*0.3));
image_bk.write ("rounded.png");
}
This is the result I'm getting
This is the result I'm looking for
Googling some online documentation, I found:
strokeAntiAlias - bool - Enable or disable anti-aliasing when drawing object outlines.
I suggest:
image_bk.strokeAntiAlias(true);
Expanding on Lamar's answer. Magick::Image.strokeAntiAlias and Magick::DrawableStrokeAntiAlias is what you want. But I would suggest using std::list<Drawable> to generate a context stack. This would allow your application to manage what-will-be-drawn independently of image i/o.
using namespace Magick;
size_t size = 405;
size_t border = 6;
std::list<Drawable> ctx;
ctx.push_back(DrawableStrokeAntialias(MagickTrue));
ctx.push_back(DrawableStrokeColor("#CAF99B"));
ctx.push_back(DrawableStrokeWidth(border));
ctx.push_back(DrawableFillColor("#68C77B"));
ctx.push_back(DrawableCircle(size*0.75, size*0.25, size*0.33, size*0.66));
Image image_bk( Geometry(size, size), Color("white"));
image_bk.draw(ctx);

SDL2 does not draw image using texture

I have been attempting to get a simple SDL2 program up to display an image and then exit. I have this code:
/* compile with `gcc -lSDL2 -o main main.c` */
#include <SDL2/SDL.h>
#include <SDL2/SDL_video.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_timer.h>
int main(void){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * w = SDL_CreateWindow("Hi", 0, 0, 640, 480, 0);
SDL_Renderer * r = SDL_CreateRenderer(w, -1, 0);
SDL_Surface * s = SDL_LoadBMP("../test.bmp");
SDL_Texture * t = SDL_CreateTextureFromSurface(r, s);
SDL_FreeSurface(s);
SDL_RenderClear(r);
SDL_RenderCopy(r, t, 0, 0);
SDL_RenderPresent(r);
SDL_Delay(2000);
SDL_DestroyTexture(t);
SDL_DestroyRenderer(r);
SDL_DestroyWindow(w);
SDL_Quit();
}
I am aware that I have omitted the normal checks that each function succeeds - they all do succeed, they were removed for ease of reading. I am also aware I have used 0 rather than null pointers or the correct enum values, this also is not the cause of the issue (as the same issue occurs when I correctly structure the program, this was a quick test case drawn up to test the simplest case)
The intention is that a window appear and shows the image (which is definitely at that directory), wait for a couple of seconds and exit. The result, however, is that the window appears correctly but the window is filled with black.
An extra note SDL_ShowSimpleMessageBox() appears to work correctly. I don't know how this relates to the rest of the framework though.
I'll just clear this, you wanted to make a texture, do it directly to ease control, plus this gives you better control over the image, try using this code, fully tested, and working, all you wanted was for the window to show the image and close within 2 seconds right?. If the image doesn't load then it's your image's location.
/* compile with `gcc -lSDL2 -o main main.c` */
#include <SDL.h>
#include <SDL_image.h>
#include <iostream> //I included it since I used cout
int main(int argc, char* argv[]){
bool off = false;
int time;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * w = SDL_CreateWindow("Hi", 0, 0, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer * r = SDL_CreateRenderer(w, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture * s = NULL;
s = IMG_LoadTexture(r, "../test.bmp"); // LOADS A TEXTURE DIRECTLY FROM THE IMAGE
if (s == NULL)
{
cout << "FAILED TO FIND THE IMAGE" << endl; //we did this to check if IMG_LoadTexture found the image, if it showed this message in the cmd window (the black system-like one) then it means that the image can't be found
}
SDL_Rect s_rect; // CREATES THE IMAGE'S SPECS
s_rect.x = 100; // just like the window, the x and y values determine it's displacement from the origin which is the top left of your window
s_rect.y = 100;
s_rect.w = 640; //width of the texture
s_rect.h = 480; // height of the texture
time = SDL_GetTicks(); //Gets the current time
while (time + 2000 < SDL_GetTicks()) //adds 2 seconds to the past time you got and waits for the present time to surpass that
{
SDL_RenderClear(r);
SDL_RenderCopy(r, s, NULL, &s_rect); // THE NULL IS THE AREA YOU COULD USE TO CROP THE IMAGE
SDL_RenderPresent(r);
}
SDL_DestroyTexture(s);
SDL_DestroyRenderer(r);
SDL_DestroyWindow(w);
return 0; //returns 0, closes the program.
}
if you wanted to see a close button on the window and want it to take effect then create an event then add it to the while area to check if it's equal to SDL_Quit();, I didn't include it since you wanted it to immediately close within 2 seconds, thus, rendering the close button useless.
HAPPY CODING :D
When using SDL_RENDERER_SOFTWARE for the renderer flags this worked. Also it worked on a different machine. Guess there must be something screwed up with my configuration, although I'm not sure what it is because I'm still getting no errors shown. Ah well, mark as solved.
I believe this to be (not 100% sure, but fairly sure), due to this line of code:
SDL_Renderer * r = SDL_CreateRenderer(w, -1, 0);
According to the SDL wiki article SDL_CreateRenderer, the parameters required for the arguments that you are passing in are as follows:
SDL_Window* window
int index
Uint32 flags
You are passing in the pointer to the window correctly, as well as the index correctly, but the lack of a flag signifies to SDL that SDL should use the default renderer.
Most systems have a default setting for applications for which renderer should be used, and this can be modified on a application by application basis. If no default setting is provided for a specific application, the render look up immediately checks the default render settings list. The SDL wiki briefly refers to this list by the following line at the bottom of the remarks section:
"Note that providing no flags gives priority to available SDL_RENDERER_ACCELERATED renderers."
What's not explained here in the wiki is that the "renderers" the wiki is referring to comes from the default renderer list.
This leads me to believe that you have either changed a setting somewhere in the course of history of your computer, or elsewhere in you visual studio settings that is resulting in no list to be found. Therefore you must explicitly inform SDL which renderer to use because of your machine settings. Otherwise using an argument of 0 should work just fine. In the end this doesn't hurt as it's better to be explicit in your code rather than implicit if at all possible.
(That said, all of my deductions are based off of the fact that I am assuming that everything you said that works, works. If this is not true, then the issue could be because of a vast variety of reasons due to the lack of error checking.)

Text rendering terribly slow

I'm using FTGL library to render text in my C++, OpenGL application, but I find it terribly slow, even though it is said to be fast and efficient library for this.
Even for small amounts of text, performance drop is visible, but when I try to render few lines of text, FPS drops from 350~ to 30~:
Yes, I already know that FPS isn't a good way to check efficiency, yet in this case there shouldn't be so big difference.
I found a function which allows me to make FTGL use display lists internally in order to increase speed, but it appears to be turned on by default. Anyway I tried using it, but it gave me nothing. So I thought that maybe it's somehow corrupted, or I don't understand it quite well, so I decided to put rendering text into my own display lists, but difference is either so slight that I can't even see it, or there's no difference.
bool TFontManager::renderWrappedText(font_ptr font, int lineLength, const TPoint& position, const std::string& text) {
if(font == nullptr) {
return false;
}
string key = sizeToString(font->FaceSize()); // key to look for it in map
key.append(TUtil::intToString(lineLength));
key.append(text);
GLuint displayListId = getDisplayListId(key); // get display list id from internal map
if(displayListId != 0) { // if display list id was found in map, i can call it
glCallList(displayListId);
return true;
}
// if id was not found, i'm creating new display list
FTSimpleLayout simpleLayout;
simpleLayout.SetLineLength((float)lineLength);
simpleLayout.SetFont(font.get());
displayListId = glGenLists(1);
glNewList(displayListId, GL_COMPILE);
glPushMatrix();
glTranslatef(position.x, position.y, 0.0f);
simpleLayout.Render(TUtil::stringToWString(text).c_str(), -1, FTPoint(), FTGL::RENDER_FRONT | FTGL::RENDER_BACK); // according to visual studio's profiler, bottleneck is inside this function. more exactly in drawing textured quads when i looked into FTGL code.
glPopMatrix();
glEndList();
m_textDisplayLists[key] = displayListId;
glCallList(displayListId);
return true;
}
I checked with breakpoints in debug mode - it creates display list only once, later it only calls previously created one.
What might be the reason for such slow rendering? How may I speed it up?
Edit:
I'm using FTTextureFont (which uses one texture per glyph). According to this FTGL tutorial, I should rather use FTBufferFont, because it uses only one texture per line. Buffer font should be faster, but after I tried it it's uglier and even slower (6 fps whereas texture font gave me 30 fps).
Edit2:
This is how I create my fonts:
font_ptr TFontManager::getFont(const std::string& filename, int size) {
string fontKey = filename;
fontKey.append(sizeToString(size));
FontIter result = fonts.find(fontKey);
if(result != fonts.end()) {
return result->second; // Found font in list
}
// If font wasn't found, create a new one and store it in list of fonts
font_ptr font(new FTTextureFont(filename.c_str()));
font->UseDisplayList(true);
if(font->Error()) {
string message = "Failed to open font";
message.append(filename);
TError::showMessage(message);
return nullptr;
}
if(!font->FaceSize(size)) {
string message = "Failed to set font size";
TError::showMessage(message);
return nullptr;
}
fonts[fontKey] = font;
return font;
}
Edit3:
This is function taken from FTGL library source code which renders glyph in FTTextureFont. It uses the same texture for separate glyphs, just with other coordinates, so this shouldn't be a problem.
const FTPoint& FTTextureGlyphImpl::RenderImpl(const FTPoint& pen,
int renderMode)
{
float dx, dy;
if(activeTextureID != glTextureID)
{
glBindTexture(GL_TEXTURE_2D, (GLuint)glTextureID);
activeTextureID = glTextureID;
}
dx = floor(pen.Xf() + corner.Xf());
dy = floor(pen.Yf() + corner.Yf());
glBegin(GL_QUADS);
glTexCoord2f(uv[0].Xf(), uv[0].Yf());
glVertex2f(dx, dy);
glTexCoord2f(uv[0].Xf(), uv[1].Yf());
glVertex2f(dx, dy - destHeight);
glTexCoord2f(uv[1].Xf(), uv[1].Yf());
glVertex2f(dx + destWidth, dy - destHeight);
glTexCoord2f(uv[1].Xf(), uv[0].Yf());
glVertex2f(dx + destWidth, dy);
glEnd();
return advance;
}
Rendering typography from normal typeface files is a pretty computationally intensive operation. The font glyphs are read as a set of splines that are used to generate character boundaries which are tessellated and fed into the graphics pipeline. I'm not highly familiar with FreeType2 but I have used FTGL. You should be using a FontAtlas to render type. A FontAtlas is a regular texture atlas (much like a sprite sheet) that is rendered once for each font size and then stored for future glyph renders.
Check out this link for more information on the process:
http://antongerdelan.net/opengl4/freetypefonts.html
This should greatly improve performance. Although you may lose out on some font-rendering flexibility.