PDA

View Full Version : Sprite texture



Mr.Byteside
08-11-2010, 12:23 PM
I want to load a big image which contains smaller images of letters. The size of the letters is different. How do I get a specific parts of the texture onto my quads?

ZbuffeR
08-11-2010, 12:45 PM
By setting texture coordinates for each vertex.
Say if you have 4*4=16 regular small images on a big texture, you can access each (i,j) letter between glTexCoord2f(i/4.0,j/4); and glTexCoord2f((i+1)/4.0,(j+1)/4);

Mr.Byteside
08-11-2010, 02:38 PM
Sorry, I don't understand the i,j part.

For example I have the image you said, see attachment.

I use this for the whole texture:



glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0); glVertex3f(50, 50, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(75, 50, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(75, 75, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(50, 75, 0.0);
glEnd();


How do I get the first M? Or the sixth M?

ZbuffeR
08-11-2010, 02:59 PM
With (i,j) I meant the M situated on column number i and row number j, said number going from 0 to 3, starting from lower left corner.

So to texture with the first M (orange) :


i = 0;
j = 0;
glBegin(GL_QUADS);
glTexCoord2f(i/4.0,j/4.0); glVertex3f(50, 50, 0.0);
glTexCoord2f((i+1)/4.0,j/4.0); glVertex3f(75, 50, 0.0);
glTexCoord2f((i+1)/4.0,(j+1)/4.0); glVertex3f(75, 75, 0.0);
glTexCoord2f(i/4.0, (j+1)/4.0); glVertex3f(50, 75, 0.0);
glEnd();

This resolves to :


glBegin(GL_QUADS);
glTexCoord2f(0.0 , 0.0 ); glVertex3f(50, 50, 0.0);
glTexCoord2f(0.25, 0.0 ); glVertex3f(75, 50, 0.0);
glTexCoord2f(0.25, 0.25); glVertex3f(75, 75, 0.0);
glTexCoord2f(0.0 , 0.25); glVertex3f(50, 75, 0.0);
glEnd();


For M4 (green one bottom right) just set i=3 and j=0.
For M6 (the one right above purple) just set i=1 and j=1.

Etc, I hope it was clear.

Mr.Byteside
08-13-2010, 06:19 AM
Thank you, that works great.

Small problem is that the result looks a bit blurred. How do I fix this?

trinitrotoluene
08-13-2010, 06:28 AM
What is your parameter (http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml) for texture filter mode GL_LINEAR? Try with GL_NEAREST. For better result try with mipmap.

Mr.Byteside
08-13-2010, 07:31 AM
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_NEAREST_MIPMAP_NEAREST);

But it's still a bit 'moved/blurred'.

Can't I get the 'real' pixels?

I also have this as initialization, does that matter?:



glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, 454, 100, 0, 0, 1);
glDisable(GL_DEPTH_TEST);
glMatrixMode (GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);

trinitrotoluene
08-13-2010, 07:50 AM
What is the original size of your texture image? Did you try also with GL_NEAREST with no mipmap. Can you post a screen shot or better attach a the source code of an example program to verify.

oops: I did not see the previous attachment!, but a source code example should be nice.

Mr.Byteside
08-13-2010, 10:15 AM
It's a bit of a mess, I got the image loading code from somewhere else and took it apart. :P

I hope it's useful.

The OpenGL part is working in a .net program.




#pragma once

#include <windows.h>
//#include <GL/glut.h>
//#include <GL/gl.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include "resource.h"

using namespace System::Windows::Forms;


namespace OpenGLForm
{

GLuint texture[1];

void LoadGLTextures() // Creates Textures From Bitmaps In The Resource File
{
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure

// The ID Of The 3 Bitmap Images We Want To Load From The Resource File
byte Texture[]={
IDB_FONT_NORMAL_1
};

glGenTextures(sizeof(Texture), &amp;texture[0]); // Generate 3 Textures (sizeof(Texture)=3 ID's)

hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKE INTRESOURCE(Texture[0]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP) // Does The Bitmap Exist?
{ // If So...
GetObject(hBMP,sizeof(BMP), &amp;BMP); // Get The Object
// hBMP: Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
glBindTexture(GL_TEXTURE_2D, texture[0]); // Bind Our Texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_NEAREST);


// Generate Mipmapped Texture (3 Bytes, Width, Height And Data From The BMP)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // Delete The Bitmap Object

}

}


public ref class COpenGL: public System::Windows::Forms::NativeWindow
{
public:
COpenGL(System::Windows::Forms::Form ^ parentForm, GLsizei iWidth, GLsizei iHeight)
{
CreateParams^ cp = gcnew CreateParams;

// Set the position on the form
cp->X = 86;
cp->Y = 236;
cp->Height = iHeight;
cp->Width = iWidth;

// Specify the form as the parent.
cp->Parent = parentForm->Handle;

// Create as a child of the specified parent and make OpenGL compliant (no clipping)
cp->Style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

// Create the actual window
this->CreateHandle(cp);

m_hDC = GetDC((HWND)this->Handle.ToPointer());

////////////// verandert vanaf hier
if(m_hDC)
{
MySetPixelFormat(m_hDC);
//ReSizeGLScene(iWidth, iHeight);
InitGL();
}

}

static GLint updateTest = 0;


static System::Void Render(System::Void)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glBindTexture(GL_TEXTURE_2D, texture[0]);

float i = 0;
float j = 0;


glBegin(GL_QUADS);
glTexCoord2f(i/4.0 ,(j+1)/4.0) ; glVertex3f(50, 50, 0.0);
glTexCoord2f((i+1)/4.0 ,(j+1)/4.0) ; glVertex3f(75, 50, 0.0);
glTexCoord2f((i+1)/4.0 ,j/4.0) ; glVertex3f(75, 75, 0.0);
glTexCoord2f(i/4.0 ,j/4.0) ; glVertex3f(50, 75, 0.0);
glEnd();

glFlush();
glDisable(GL_TEXTURE_2D);

}

System::Void SwapOpenGLBuffers(System::Void)
{
SwapBuffers(m_hDC) ;
}

private:
HDC m_hDC;
HGLRC m_hglrc;

protected:
~COpenGL(System::Void)
{
this->DestroyHandle();
}

GLint MySetPixelFormat(HDC hdc)
{
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
16, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

GLint iPixelFormat;

// get the device context's best, available pixel format match
if((iPixelFormat = ChoosePixelFormat(hdc, &amp;pfd)) == 0)
{
MessageBox::Show("ChoosePixelFormat Failed");
return 0;
}

// make that match the device context's current pixel format
if(SetPixelFormat(hdc, iPixelFormat, &amp;pfd) == FALSE)
{
MessageBox::Show("SetPixelFormat Failed");
return 0;
}

if((m_hglrc = wglCreateContext(m_hDC)) == NULL)
{
MessageBox::Show("wglCreateContext Failed");
return 0;
}

if((wglMakeCurrent(m_hDC, m_hglrc)) == NULL)
{
MessageBox::Show("wglMakeCurrent Failed");
return 0;
}


return 1;
}

bool InitGL(GLvoid) // All setup for opengl goes here
{
glClearColor(0.9375f, 0.9375f, 0.9375f, 1); // Black background

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, 454, 100, 0, 0, 1);
glDisable(GL_DEPTH_TEST);

LoadGLTextures(); // Load The Textures From Our Resource File

return TRUE;
}

};
}

trinitrotoluene
08-14-2010, 04:29 PM
In your loadGLTextures function, add this:


glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_NEAREST);


Your Texture mag filter was not set and by default it is GL_LINEAR.

Mr.Byteside
08-15-2010, 03:31 AM
Thanks for the help. I also figured out that 100x100 is no good size. It needed to be 128x128. :)