Nie wiem, ale tu masz ładowacz tekstur mojego pomysłu, korzystający z WIC (Windows Imaging Component).
Kod używa smartpointerów z Visuala (to jest to _COM_SMARTPTR_TYPEDEF), jeśli używasz GCC to trzeba by przerobić.
Kopiuj
#pragma once
#include <wincodec.h>
#include <comdef.h>
_COM_SMARTPTR_TYPEDEF(IWICImagingFactory, __uuidof(IWICImagingFactory));
_COM_SMARTPTR_TYPEDEF(IWICBitmapDecoder, __uuidof(IWICBitmapDecoder));
_COM_SMARTPTR_TYPEDEF(IWICBitmapFrameDecode, __uuidof(IWICBitmapFrameDecode));
_COM_SMARTPTR_TYPEDEF(IWICBitmapSource, __uuidof(IWICBitmapSource));
_COM_SMARTPTR_TYPEDEF(IWICFormatConverter, __uuidof(IWICFormatConverter));
_COM_SMARTPTR_TYPEDEF(IWICBitmapFlipRotator, __uuidof(IWICBitmapFlipRotator));
struct CoInit
{
CoInit() { hr = CoInitialize(NULL); }
~CoInit() { if (SUCCEEDED(hr)) CoUninitialize(); }
HRESULT hr;
};
class CTexLoader
{
public:
CTexLoader();
GLuint LoadTexture(const char *fileName);
private:
CoInit coinit;
IWICImagingFactoryPtr factory;
CTexLoader(CTexLoader&) = delete;
};
Kopiuj
#include "ctexloader.h"
#include <cstdint>
#include <string>
#include <iterator>
#include <vector>
using namespace std;
CTexLoader::CTexLoader()
{
factory.CreateInstance(CLSID_WICImagingFactory1);
}
GLuint CTexLoader::LoadTexture(const char *fileName)
{
wstring wFileName(fileName, fileName+strlen(fileName));
IWICBitmapDecoderPtr decoder;
factory->CreateDecoderFromFilename(
wFileName.c_str(),
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
&decoder);
if (!decoder)
return 0;
IWICBitmapFrameDecodePtr frame;
decoder->GetFrame(0, &frame);
IWICBitmapSourcePtr source;
frame.QueryInterface(IID_PPV_ARGS(&source));
WICPixelFormatGUID format;
source->GetPixelFormat(&format);
if (format != GUID_WICPixelFormat32bppBGRA)
{
IWICFormatConverterPtr converter;
factory->CreateFormatConverter(&converter);
converter->Initialize(
frame,
GUID_WICPixelFormat32bppBGRA,
WICBitmapDitherTypeErrorDiffusion,
(IWICPalette*)NULL,
0.0,
WICBitmapPaletteTypeCustom);
converter.QueryInterface(IID_PPV_ARGS(&source));
}
UINT w, h;
source->GetSize(&w, &h);
vector<uint32_t> bitmap;
bitmap.resize(w * h);
IWICBitmapFlipRotatorPtr flip;
factory->CreateBitmapFlipRotator(&flip);
flip->Initialize(source, WICBitmapTransformFlipVertical);
flip.QueryInterface(IID_PPV_ARGS(&source));
source->CopyPixels(NULL, w*4, w*h*4, (BYTE*)bitmap.data());
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, bitmap.data());
glBindTexture(GL_TEXTURE_2D, 0);
return texture;
}
Oryginalny kod używał biblioteki MFC, postarałem się usunąć zależności.
Używa się mniej-więcej tak:
Kopiuj
CTexLoader texLoader;
t1 = texLoader.LoadTexture("t1a.png");
t2 = texLoader.LoadTexture("t2a.png");
Powinno ładować PNG, JPG, TIFF i inne popularne formaty.
Kontroli błędów w kodzie prawie brak, jak ci zwraca 0 to musisz poszukać dlaczego.