Sprite texture

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?

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);

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?

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.

Thank you, that works great.

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

What is your parameter for texture filter mode GL_LINEAR? Try with GL_NEAREST. For better result try with mipmap.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,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); 

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.

It’s a bit of a mess, I got the image loading code from somewhere else and took it apart. :stuck_out_tongue:

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), &texture[0]);				// Generate 3 Textures (sizeof(Texture)=3 ID's)

		hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[0]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
		if (hBMP)												// Does The Bitmap Exist?
		{														// If So...
			GetObject(hBMP,sizeof(BMP), &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_FILTER,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, &pfd)) == 0)
			{
				MessageBox::Show("ChoosePixelFormat Failed");
				return 0;
			}
			 
			// make that match the device context's current pixel format 
			if(SetPixelFormat(hdc, iPixelFormat, &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;
		}

	};
}


In your loadGLTextures function, add this:


 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

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

Thanks for the help. I also figured out that 100x100 is no good size. It needed to be 128x128. :slight_smile: