2008-10-15 20 views
8

Tôi có dữ liệu hình ảnh và tôi muốn có một hình ảnh phụ để sử dụng như một kết cấu mờ.openGL SubTexturing

glGenTextures(1, &m_name); 
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldName); 
glBindTexture(GL_TEXTURE_2D, m_name); 
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, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

Tôi làm cách nào để có được hình ảnh phụ của hình ảnh đó được tải dưới dạng kết cấu. Tôi nghĩ rằng nó có một cái gì đó để làm với việc sử dụng glTexSubImage2D, nhưng tôi không có đầu mối làm thế nào để sử dụng nó để tạo ra một kết cấu mới mà tôi có thể tải. Gọi điện:

glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, xWidth, yHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

không có gì mà tôi có thể xem và gọi glCopyTexSubImage2D chỉ là một phần của bộ đệm khung của tôi. Cảm ơn

Trả lời

27

Chỉnh sửa: Sử dụng glPixelStorei. Bạn sử dụng nó để đặt GL_UNPACK_ROW_LENGTH thành chiều rộng (tính bằng pixel) của toàn bộ hình ảnh. Sau đó, bạn gọi glTexImage2D (hoặc bất kỳ thứ gì), chuyển nó tới con trỏ tới pixel đầu tiên của ảnh con và chiều rộng và chiều cao của ảnh con.

Đừng quên khôi phục GL_UNPACK_ROW_LENGTH thành 0 khi bạn đã hoàn tất.

Ie:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
char *subimg = (char*)m_data + (sub_x + sub_y*img_width)*4; 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, subimg); 
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 

Hoặc, nếu bạn bị dị ứng với con trỏ toán:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, sub_x); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, sub_y); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); 

Edit2: Vì lợi ích của sự hoàn chỉnh, tôi phải chỉ ra rằng nếu bạn đang sử dụng OpenGL-ES thì bạn không nhận được GL_UNPACK_ROW_LENGTH. Trong trường hợp này, bạn có thể hoặc là (a) trích xuất các subimage vào một mới đệm cho mình, hoặc (b) ...

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTES, NULL); 

for(int y = 0; y < sub_height; y++) 
{ 
    char *row = m_data + ((y + sub_y)*img_width + sub_x) * 4; 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, sub_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row); 
} 
+0

Về cơ bản tôi có hình ảnh (dưới dạng dữ liệu thô) và tôi muốn sử dụng một phần của hình ảnh đó làm kết cấu. Tôi biết làm thế nào để tải toàn bộ hình ảnh như là một kết cấu, nhưng không biết làm thế nào để sử dụng chỉ là một chút của nó. – DavidG

+0

Đã trả lời câu trả lời này. Nếu bạn có một hình ảnh trong bộ nhớ, nó được lưu trữ bằng cách nào đó. Nếu bạn sử dụng glTexImage2D (... GL_RGBA, GL_UNSIGNED_BYTE) để tải, thì có một byte cho R, G, B và giá trị alpha. Các hình ảnh được lưu trữ với pixel (0, 0) bắt đầu ở vị trí 0. Pixel x ở hàng y bắt đầu ở hình ảnh [width * y + x] [0] – mstrobl

+0

vì tôi đang sử dụng OpenGL ES, tôi đã kết thúc tùy chọn u đã cho, đó là giải nén subimage vào một bộ đệm mới. Thật đáng buồn trên thiết bị nó không còn hoạt động, vì vậy tôi sẽ làm lại kết cấu để tôi không cần phải giải quyết vấn đề. – DavidG

1

Đối với những người bị mắc kẹt với OpenGL ES 1.1/2.0 vào năm 2018 và sau đó, tôi đã làm một số xét nghiệm với các phương pháp khác nhau làm thế nào để cập nhật một phần của kết cấu từ dữ liệu hình ảnh (hình ảnh có cùng kích thước với kết cấu).

Phương pháp 1: Sao chép toàn bộ hình ảnh với glTexImage2D:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Cách 2: Sao chép toàn bộ hình ảnh với glTexSubImage2D:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Phương pháp 3: Sao chép hình ảnh một phần, từng dòng trong một vòng lặp:

auto *ptr = m_Pixels + (x + y * mWidth) * 4; 
for(int i = 0; i < h; i++, ptr += mWidth * 4) { 
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 
} 

Phương pháp 4: Sao chép toàn bộ chiều rộng của hình ảnh, nhưng theo chiều dọc sao chép chỉ là một phần trong đó đã thay đổi:

auto *ptr = m_Pixels + (y * mWidth) * 4; 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, mWidth, h, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 

Và đây là kết quả của thử nghiệm được thực hiện trên máy tính, bởi 100000 lần cập nhật các phần khác nhau của kết cấu khoảng 1/5 kích thước của toàn bộ kết cấu.

  • Phương pháp 1 - 38.17 sec
  • Cách 2 - 26.09 giây
  • Phương pháp 3-54,83 giây - chậm nhất
  • Phương pháp 4-5,93 giây - chiến thắng

Không ngạc nhiên, phương pháp 4 là nhanh nhất, như chỉ nó sao chép một phần của hình ảnh, và hiện nó chỉ với một hàm gọi đến hàm glTex ...().