Teksturowanie - OpenGL

0

Pisze obecnie program w OpenGL i niestety nie daję rady sobie z teksturowaniem. Chciałam wczytać teksturę z pliku, tylko nie wiem jak to zrobić. Nie zajmuję się tym na co dzień i po przeczytaniu wielu stron internetowych nadal nie wiem jak to zrobić. Mam narysowany prostokąt :

void earth::glDrawSquare(void)
{
	glBegin( GL_QUADS );
		glTexCoord2f( 0.0f, 1.0f ); 
		glVertex3f( -1.0f, 1.0f, 0.0f );

		glTexCoord2f( 0.0f, 0.0f ); 
		glVertex3f( -1.0f, -1.0f, 0.0f );

		glTexCoord2f( 1.0f, 0.0f ); 
		glVertex3f( 1.0f, -1.0f, 0.0f );

		glTexCoord2f( 1.0f, 1.0f ); 
		glVertex3f( 1.0f, 1.0f, 0.0f );
	glEnd( );
}

Czy jest może jakiś szablon jak pisać programy z teksturowaniem w C++? Nie wiem w ogóle gdzie zamieścić ten plik (trawa.bmp). I czego potrzebuję jeszcze, by to miało ręce i nogi? Na razie jest to po prostu kolorowy prostokąt...

Proszę o jakieś porady:)

0

Cała zabawa z teksturowaniem sprowadza się do kilku kroków.

  1. Załadowanie tekstury z pliku do pamięci. OpenGL nie potrafi tego zrobić jako że służy tylko i wyłącznie do renderowania. Zasadniczo masz 2 drogi:

    • skorzystać z gotowej biblioteki do czytania obrazków. Polecam nagłówek SDL_Image z SDL-a. Czytanie bitmapy sprowadza się tam do wywołania IMG_Load.
      Kiedyś używałem FreeImage, też dawało rade.
    • napisać własny loader bitmap/targi. Na pewno bardziej czasochłonne, jeśli uczysz się OpenGL-a to IMO szkoda czasu na babranie się z ładowaniem obrazków.
  2. Przesłanie danych tekstury do OpenGL-a. Używasz glGenTextures do wygenerowania id tekstury, następnie dowiązujesz teksture przez glBindTexture. Mając dane tekstury: zawartość, wysokość, szerokość, format wywołujesz glTexImage2D.

  3. Rendering. Tutaj wystarczy tylko bind-ować wcześniej wygenerowany identyfikator.

W telegraficznym skrócie wygląda to mniej więcej tak. Co do szczegółów, z tego co widzę tutaj są całkiem niezłe tutki:
http://www.nullterminator.net/gltexture.html
http://www.gamedev.net/page/resources/_/technical/opengl/opengl-texture-mapping-an-introduction-r947

1
yurai napisał(a):

Polecam nagłówek SDL_Image z SDL-a. Czytanie bitmapy sprowadza się tam do wywołania IMG_Load.

Sam nagłówek niewiele da :D SDL_image podobnie jak SDL_mixer to osobne binarki. Po co dokładać tyle zależności? Skoro chce ładować tekstury z pliku BMP, to najlepiej niech użyje SDL_LoadBMP z SDL.h. Ładowałem tym nawet 32bitowe pliki bmp z kanałem alpha ;) Minimalizm, użyje biblioteki SDL do obsługi okna, klawiatury, myszy i ładowania tekstur, a to wszystko w jednej bibliotece SDL.dll ;)

Jak używa mało tekstur i nie ma to być nie wiadomo jaki arcydzieło programistyczne, zastanowiłbym się nad ładowaniem tesktury dla OpenGL z odpowiednio utworzonej tablicy, GIMP potrafi zapisać obrazy do pliku nagłówkowego w języku C.

Pamiętaj, że tekstury powinny mieć wymiary potęgi dwójki, np. 32, 64, 128, 256, 512 itd.

0

Z tego wszystkiego widzę, że jednak sobie nie poradzę:P Ale dziękuję za odpowiedzi;)

0

@tenshia: nie podałaś żadnej informacji jaki system operacyjny, czym otwierasz okno, czy program ma być przenośny, i jaki kompilator.
Takie informacje są ważne przy wybieraniu bibliotek.

0

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;
}
0

Wszystko kompiluję w visual studio. Spróbowałam w ten sposób coś oteksturować (chyba już na wiele sposobów), jednak wciąż coś jest nie tak. W najlepszym przypadku obiekt oteksturowany staje się niewidoczny(ale istnieje, bo spełnia swoje funkcje). Nie wiem co jest nie tak. Na pewno nie jest to skomplikowane, gdyż chciałam nałożyć teksturę na obiekt 2D i to w dodatku na prostokąty i kwadraty. :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1