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.
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.