I was developing a game earlier and came across a bit of an issue! I had started the game with single images. Each texture had it's own file. It was a bit into it that I realized how much of an idiot I was to do that, and tried to switch over to using one picture that contains all the textures ( they're quite small anyway ). Now, a problem arose. When a larger image than my original texture ( 10 x 10 ) is loaded in, it's almost as if it's not being displayed with the nearest neighbor sizing algorithm. What I get is a blurred image. Also it's flipped... Why are either of these issues happening?
Code and images below.
Here is the first showing a sprite sheet containing text and symbols. (It's quite small, 100 x 100 ) http://imgur.com/HU5zEAO.jpg
This is what I get when the program is run. http://i.imgur.com/HeVPdPy.jpg
Here is the main.cpp file
#include <GL/glew.h>
#include <GL/glut.h>
#include "spritesheet_class.h"
#include "load_img.h"
GLuint TextSheet;
Spritesheet Test;
void LoadFiles()
{
GLuint TextSheet = LoadTexture( "davetica.png", 100, 100, 0 );
Test.SetTex( TextSheet, 100, 100, 10, 10 );
}
void Reshape( int width, int height )
{
glViewport( 0, 0, (GLsizei)width, (GLsizei)height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0f, width, 0.0f, height, 1.0f, 100.0f );
glMatrixMode( GL_MODELVIEW );
}
void Display()
{
glClear( GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glTranslatef( 0.0f, 0.0f, -1.0f );
Test.DrawSprite( 1, 0, 0, 400, 400 );
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowPosition( 200, 100 );
glutInitWindowSize( 512, 512 );
glutCreateWindow( "Sprite Sheets" );
glutDisplayFunc( Display );
glutIdleFunc( Display );
glutReshapeFunc( Reshape );
LoadFiles();
glutMainLoop();
}
Now here is the class header in which I write the Spritesheet class.
#ifndef SPRITESHEET_CLASS_H_INCLUDED
#define SPRITESHEET_CLASS_H_INCLUDED
#include "load_img.h"
class Spritesheet
{
public:
void SetTex( GLuint Tex, int ImgW, int ImgH, int HorzAm, int VertAm );
void DrawSprite( int spriteNum, int xLoc, int yLoc, int width, int height );
private:
GLuint Texture;
int imageWidth, imageHeight, horiAm, vertAm;
};
void Spritesheet::SetTex( GLuint Tex, int ImgW, int ImgH, int HorzAm, int VertAm )
{
imageWidth = ImgW;
imageHeight = ImgH;
horiAm = HorzAm;
vertAm = VertAm;
Texture = Tex;
}
void Spritesheet::DrawSprite( int spriteNum, int xLoc, int yLoc, int width, int height )
{
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, Texture );
glBegin( GL_QUADS );
glTexCoord2f( 1.0f, 0.0f );
glVertex2f( xLoc, yLoc );
glTexCoord2f( 1.0f, 1.0f );
glVertex2f( xLoc, yLoc+height );
glTexCoord2f( 0.0f, 1.0f );
glVertex2f( xLoc+width, yLoc+height );
glTexCoord2f( 0.0f, 0.0f );
glVertex2f( xLoc+width, yLoc );
glEnd();
glDisable( GL_TEXTURE_2D );
}
#endif // SPRITESHEET_CLASS_H_INCLUDED
Finally, if you need this, here is the file that handles the LoadImage function in which I use to load and format the textures.
#ifndef LOAD_IMG_H_INCLUDED
#define LOAD_IMG_H_INCLUDED
#include <iostream>
#include <stbimg.h>
#include <string>
bool loadCorrectly = true;
using namespace std;
GLuint LoadTexture( const char *filename, int w, int h, int n )
{
unsigned char *data = stbi_load( filename, &w, &h, &n, 4 );
GLuint texture;
if( data == NULL )
{
cout << "ERROR: '"<< filename << "' HAS BEEN MODIFIED OR IS MISSING." << endl;
return 0;
}else
{
cout << "Loaded: '" << filename << "' successfully." << endl;
}
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, w, h,GL_RGBA, GL_UNSIGNED_BYTE, data );
free( data );
return texture;
}
EDIT: I found out the issue. My image was not a square of two, so therefore it was not displaying properly.
Your images are flipped because you have not flipped them to be oriented properly. It sounds tautological, but OpenGL's coordinate system maps textures down to up where (0,0) is in the bottom left and (1,1) is in the top right. Fixing this is a textbook type of exercise.
You need to call glActiveTexture(GL_TEXTURE0)
to make subsequent gl*
calls know which texture they're modifying (ie make that texture active). The initial value is GL_TEXTURE0
but I'd still put it in so that you don't end up with potential problems down the line.
I know it's not part of your question, but you're using OpenGL code that's been deprecated for 7 years. As a general suggestion, you should switch to the programmable pipeline. Here's a link to ogldev to the basics in modern OpenGL, or at least some of it is 4.0+. Some is in the 3's but shaders are better than FFP. Here's another short few from Swiftless. Basically search for OpenGL 4.0 or later and the Googles will guide you. It's a steeper learning curve but it is worth it.
I have only ever encountered this with DDS (DXT) files, in which the blocks needed to be flipped to prevent them being upside down. I had to do this in code, but the alternative is to simply flip the image in an image program.
To be honest though, I don't use PNG files in OpenGL and I think the last time I used PNG was with XNA some time ago.
I found this here: Flipping OpenGL texture It's a different language but you both seem to have the same problem.
I'd also look into this function and see if it is capable of flipping the data
stbi_load( filename, &w, &h, &n, 4 );
Either that, or you have to do it yourself or use something else to import PNG images.
I did notice an answer on that link which suggests you can flip the matrix during rendering using glMatrixMode(GL_TEXTURE), but I imagine this isn't something you want to do.
Good luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With