2013-06-15 35 views
8

Tôi đang học OpenGL trong C++ bằng cách sử dụng hướng dẫn NeHe, nhưng tôi đang cố gắng để làm chúng với thư viện FreeImage, thay vì Glaux hoặc SOIL. Điểm tốt tôi thấy trong việc sử dụng FreeImage là nó là bản cập nhật cuối cùng vào tháng 10 năm ngoái, trong khi SOIL chưa được cập nhật trong 5 năm. Vấn đề tôi có là tôi không thể tải kết cấu chính xác.Làm cách nào để tải họa tiết lên OpenGL bằng thư viện FreeImage?

Đây là mã của tôi:

static GLuint texture = 0; 
if (texture == 0) 
{ 
    FIBITMAP* bitmap = FreeImage_Load(
     FreeImage_GetFileType("textures/test/nehe_06.png", 0), 
     "textures/test/nehe_06.png"); 

    glGenTextures(1, &texture); 

    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    glTexImage2D(GL_TEXTURE_2D, 0, 3, FreeImage_GetWidth(bitmap), FreeImage_GetHeight(bitmap), 
     0, GL_RGB, GL_UNSIGNED_BYTE, FreeImage_ConvertTo32Bits(bitmap)); 

    FreeImage_Unload(bitmap); 
} 

Sử dụng mã này, kết cấu tôi nhận được là sai: nó là màu đen, với dấu chấm màu và dải, và thay đổi hình ảnh cho kết quả tương tự, vì vậy tôi giả Tôi m không tải kết cấu chính xác.

Tôi đã cố gắng trao đổi các bit màu đỏ và màu xanh (đọc rằng FreeImage tải trong BGR) mà không có kết quả tốt hơn. Cuối cùng, nếu tôi thay đổi * FreeImage_ConvertTo32Bits (bitmap) * bằng * FreeImage_GetBits (bitmap) * Tôi nhận được một segfault.

Tôi đang làm gì sai?

Trả lời

17

Có hai vấn đề với mã của bạn - một là bạn đang chuyển đổi sang hình ảnh thành 32 bit nhưng bạn chỉ định định dạng kết cấu 24 bit cho openGL (GL_RGB). Thứ hai là bạn đang truyền đối tượng FreeImage đến kết cấu thay vì các bit được chuyển đổi.

Bạn cần phải làm một cái gì đó giống như thay vì

FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap); 
int nWidth = FreeImage_GetWidth(pImage); 
int nHeight = FreeImage_GetHeight(pImage); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 
    0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage)); 

FreeImage_Unload(pImage); 
+0

này sẽ không làm việc cho tất cả hình ảnh do yêu cầu sắp xếp scanline. –

+0

@SergeyK. Với pixel 32 bit, mọi kích thước quét đều được căn chỉnh 4 byte. Trong tình huống nào bạn nghĩ nó sẽ không hoạt động? –

13

Để mở rộng câu trả lời trước đây:

FreeImage_GetBits() hàm sẽ trả về một con trỏ đến dữ liệu được lưu trong một định dạng FreeImage-nội. Trong đó mỗi đường quét thường được căn chỉnh với ranh giới 4 byte. Điều này sẽ làm việc tốt trong khi bạn có sức mạnh của hai kết cấu. Tuy nhiên, đối với kết cấu NPOT, bạn sẽ cần chỉ định sắp xếp giải nén chính xác cho OpenGL.

Có một chức năng trong FreeImage mà sẽ cho phép bạn để có được unaligned mảng đóng gói chặt chẽ các điểm ảnh: FreeImage_ConvertToRawBits()