Przykład absolutnie nieprawidłowej, nieoptymalnej funkcji ładującej teksturę, działającej tylko pod Windows,
i kompilującej się tylko pod Visual Studio z powodu braku nagłówka i libki pod MinGW.
Nieprawidłowej, bo brak jakiejkolwiek kontroli błędów; przy braku pliku program się wywali.
Nieoptymalnej, bo CoInitialize i CoCreateInstance należy wykonać raz dla całego programu, a nie dla każdej tekstury osobno.
Za to postarałem się skrócić kod maksymalnie.
przykład użycia:
GLuint tex;
...
glEnable(GL_TEXTURE_2D);
tex = LoadTexture(L"c:\\pp\\trawa.png"); // rozmiar np. 128x128 px. może być JPEG.
przykład rysowania:
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_TRIANGLES);
glTexCoord2i(0,1); glVertex2d(0, 1.0);
glTexCoord2i(1,0); glVertex2d(-0.5, -0.5);
glTexCoord2i(0,0); glVertex2d(0.5, -0.5);
glEnd();
i właściwa funkcja:
#include <wincodec.h>
#pragma comment(lib, "windowscodecs.lib")
#define GL_GENERATE_MIPMAP 0x8191
GLuint LoadTexture(wchar_t *filename)
{
IWICImagingFactory *factory;
IWICBitmapDecoder *decoder;
IWICBitmapFrameDecode *frame;
IWICFormatConverter *bmp;
unsigned int width, height;
HRESULT init = CoInitialize(NULL);
CoCreateInstance(CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&factory);
factory->CreateDecoderFromFilename(filename, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
decoder->GetFrame(0, &frame);
factory->CreateFormatConverter(&bmp);
bmp->Initialize(frame, GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeNone, NULL, 0, WICBitmapPaletteTypeCustom);
bmp->GetSize(&width, &height);
size_t row_size = 4 * width;
size_t data_size = row_size * height;
unsigned char *data = (unsigned char*)malloc(data_size);
unsigned char *scanline = data + data_size;
for (unsigned int i=0; i<height; i++)
{
scanline -= row_size;
WICRect rect = {0, i, width, 1};
bmp->CopyPixels(&rect, row_size, row_size, scanline);
}
bmp->Release();
frame->Release();
decoder->Release();
factory->Release();
if (SUCCEEDED(init))
CoUninitialize();
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
free(data);
return texture;
}