Jak ładować tekstury za pomocą SFML dla OpenGL?

9

Patrzę na samouczek mapowania tekstur NeHe . Wygląda na to, że po prostu ładowanie tekstury jest zbyt skomplikowane.

Czy istnieje sposób załadowania tekstury w SFML, a następnie użycia jej w Open GL? Używam SFML do mojego okienkowania.

Darestium
źródło

Odpowiedzi:

16

Witamy w OpenGL, gdzie szybkie rzeczy są dostępne za darmo, a te łatwe stają się trudne.

Jeśli uważasz, że próbka jest długa i skomplikowana, „tylko do załadowania tekstury”, to jeszcze nic nie widziałeś. Poczekaj, aż będziesz musiał załadować tekstury DDS, przetworzyć tekstury HDR, wesprzeć mapy kubaturowe, renderować do tekstury itp.

Ładowanie tekstury w OpenGL składa się z dwóch komponentów:

  • Pobieranie danych z formatu obrazu. Możesz załadować teksturę z pliku lub wygenerować ją proceduralnie. To nie ma znaczenia, o ile uzyskasz niezłą gamę informacji o kolorze.

  • Umieszczanie danych na karcie wideo. Dane muszą przejść z RAM systemowej do RAM wideo.

Pierwsza część powinna być łatwa, ponieważ SFML jest wyposażony w standardowy moduł ładujący obrazy.

sf::Image img_data;
if (!img_data.LoadFromFile("images/avatar.png"))
{
    LOG_ERROR("Could not load '%s'.", "images/avatar.png");
    return false;
}

Następnie będziemy musieli wygenerować obiekt tekstury OpenGL.

GLuint texture_handle;
glGenTextures(1, &texture_handle);

Istnieje wiele opcji wiązania tekstury. Istnieją trzy główne typy: 1D, 2D i 3D i masz wsparcie dla map sześciennych (+ X, -X, + Y, -Y, + Z, -Z). Jednak w 99% przypadków będziesz potrzebować tekstury 2D.

glBindTexture(GL_TEXTURE_2D, texture_handle);

Teraz dochodzimy do interesującej części. Prześlijmy nasze dane na kartę wideo.

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_RGBA,
    img_data.GetWidth(), img_data.GetHeight(),
    0,
    GL_RGBA, GL_UNSIGNED_BYTE, img_data.GetPixelsPtr()
);

Wreszcie możemy ustawić szereg parametrów tekstury. Odpowiadają na takie pytania, jak: co zrobić, jeśli użyjemy współrzędnej tekstury, która jest poza zakresem (0,0, 1,0)? Czy owijamy się wokół ( GL_REPEAT), czy nic nie robimy ( GL_CLAMP)? Można ich również użyć do wyjaśnienia na karcie wideo, że chcemy zastosować interpolację liniową w naszych teksturach.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

A teraz powinieneś być w stanie związać teksturę za pomocą glBindTexturei użyć jej do rysowania teksturowanych siatek.

knight666
źródło
mmm, próbowałem to zrobić, a dostaję tylko biały sześcian: pastebin.com/nVQFAMRJ
Darestium
Spróbuj wprowadzić glEnable(GL_TEXTURE2D);funkcję init.
knight666
Wspaniale, działa! Dzięki! BTW, co robi ta funkcja? Włączyć teksturowanie?
Darestium
Tak, włącza obiekt tekstury 2D, aby mógł odbierać dane tekstury. Musisz włączyć go tylko raz podczas inicjalizacji, ale często jest to zapominane podczas kopiowania kodu do nowego projektu. Ja wliczony w cenę. ;)
knight666
Bardzo miłe wytłumaczenie. Możesz pisać tutoriale!
danijar
2

SFML 2.0+ jeszcze bardziej ułatwia ładowanie tekstury;

sf::Texture texLid;
std::string image2="images/top.jpg";
if (!texLid.loadFromFile(image2))
{
    std::cout << "Could not load" << image2;
    char c;
    std::cin>>c;
    return false;
}


glEnable(GL_TEXTURE_2D);//tell OpenGL to use textures when drawing

sf::Texture::bind(&texLid);//select this texture for OpenGL rendering
Rozpoznać
źródło