2011-07-09 25 views
5

Tôi đã cố gắng tìm ra cách glTexImage2D hoạt động và thấy một số kết quả kỳ lạ từ một số mã khá rõ ràng. Mã của tôi chỉ đơn giản là vẽ một vòng tròn thô thành một mảng không có chiều dài 256 * 256 và sau đó gửi dữ liệu đó ra để trở thành một kết cấu. Các kết cấu hiển thị tuy nhiên được chuyển ra như biến thể của màu đỏ và màu cam không có vấn đề gì kết hợp Tôi chọn bên trong vòng lặp tạo hình ảnh của tôi:Kết quả lẻ bằng cách sử dụng glTexImage2D

unsigned* data = new unsigned[256*256]; 
for (int y = 0; y < 256; ++y) 
    for (int x = 0; x < 256; ++x) 
     if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75) 
      data[256*y + x] = ((156 << 24) | (256 << 16) | (156 << 8) | (200 << 0)); 
     else 
      data[256*y + x] = 0; // I'd expect this to be transparent and the above to be slightly transparent and green, but it's red somehow. 

glBindTexture(GL_TEXTURE_2D, texid); 
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_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data); 

tùy chọn OpenGL:

glEnable(GL_TEXTURE_2D); 
glShadeModel(GL_SMOOTH); 
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
glClearDepth(1.0f); 
glEnable(GL_DEPTH_TEST); 
glDepthFunc(GL_LEQUAL); 
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
//glBlendFunc(GL_SRC_ALPHA, GL_ONE); 
//glEnable(GL_BLEND); 
//glDisable(GL_CULL_FACE); 

glGenTextures(1, &leaf[0]); 
    createLeaf(leaf[0]); // createLeaf(GLuint& texid) is posted entirely above 

Phần còn lại của mã không làm gì nhưng hiển thị kết cấu trên một quad đơn trong cửa sổ. (x64 win7)

Chỉnh sửa: Tôi đã thử giải pháp của Rickard chính xác và tôi vẫn đang nhận được vòng tròn màu tím.

+0

Khi bạn vẽ kết cấu, nó trông giống như một vòng tròn? Tôi tò mò nếu nó chỉ là màu sắc của kết cấu đó là tắt hoặc nếu toàn bộ kết cấu chỉ là sắp ra như rác. – nil

Trả lời

13
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data); 

Đầu tiên là những điều tích cực. Bạn sử dụng định dạng nội bộ có kích thước (GL_RGBA8, chứ không phải GL_RGBA). Điều này rất tốt; cứ làm thế. Bạn có một sự hiểu biết rõ ràng về sự khác biệt giữa định dạng nội bộ (GL_RGBA8) và định dạng truyền pixel (GL_RGBA). Điều này cũng tốt.

Vấn đề là vấn đề này. Bạn đã nói với OpenGL rằng dữ liệu của bạn là một luồng các byte chưa ký. Nhưng đó là không phải luồng luồng chưa ký; đó là một luồng không có số không được ký. Đó là cách bạn khai báo data, đó là cách bạn đã điền data. Vậy tại sao bạn lại nói dối với OpenGL?

Vấn đề là với màu sắc của bạn. Đây là một trong các giá trị màu của bạn:

((156 << 24) | (256 << 16) | (156 << 8) | (200 << 0)) 

Đầu tiên, 256 không phải là màu hợp lệ. 256 trong hex là 0x100, là hai byte, không phải là một byte.

Các số nguyên unsigned bạn sẽ nhận được từ này là:

0x9D009CC8 

Nếu chúng được dự định được màu RGBA theo thứ tự, sau đó màu đỏ là 0x9D, xanh lá cây là 0x00, màu xanh là 0x9C, và alpha là 0xC8.

Bây giờ, vì có lẽ bạn đang làm việc trên một máy tính ít về cuối nhỏ, mà 4 byte được lưu trữ lộn, như thế này:

0xC89C009D 

Khi bạn nói với OpenGL để giả vờ rằng đây là một mảng byte (mà nó không phải là), bạn đang mất đi sự biến đổi nhỏ gọn. Vì vậy, OpenGL thấy mảng byte bắt đầu bằng 0xC8, vì vậy đó là giá trị màu đỏ. Và cứ thế.

Bạn cần nói cho OpenGL biết bạn đang thực sự làm gì: bạn đang lưu trữ bốn giá trị không dấu 8 bit trong một số nguyên không dấu 32 bit duy nhất. Để làm điều này, sử dụng như sau:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (GLvoid*)data); 

Các GL_UNSIGNED_INT_8_8_8_8 nói rằng bạn đang ăn OpenGL một mảng các số nguyên 32-bit unsigned (mà bạn đang có). 8 bit đầu tiên của số nguyên 32 bit là màu đỏ, số nguyên thứ hai là màu xanh lục, màu thứ ba là màu xanh và số thứ tư là alpha.

Vì vậy, để hoàn toàn sửa chữa mã của bạn, bạn cần điều này:

GLuint* data = new GLuint[256*256]; //Use OpenGL's types 
for (int y = 0; y < 256; ++y) 
    for (int x = 0; x < 256; ++x) 
     if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75) 
      data[256*y + x] = ((0x9C << 24) | (0xFF << 16) | (0x9C << 8) | (0xC8 << 0)); 
     else 
      data[256*y + x] = 0; // I'd expect this to be transparent and the above to be slightly transparent and green, but it's red somehow. 

glBindTexture(GL_TEXTURE_2D, texid); 
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_BASE_LEVEL, 0); //Always set the base and max mipmap levels of a texture. 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (GLvoid*)data); 

// Tôi hy vọng điều này sẽ được minh bạch và ở trên để thể hơi trong suốt và màu xanh lá cây, nhưng nó màu đỏ bằng cách nào đó.

Alpha không có nghĩa là trong suốt; nó có nghĩa là không có gì cả trừ khi bạn cho nó một ý nghĩa. Alpha chỉ thể hiện độ trong suốt nếu bạn sử dụng trộn và thiết lập chế độ hòa trộn làm cho alpha thấp làm cho mọi thứ trong suốt. Nếu không, nó có nghĩa là không có gì cả.

+0

Cảm ơn! Tôi có kinh nghiệm với C++, nhưng đây là buổi chiều đầu tiên của tôi với OpenGL. Tôi không thể tin rằng tôi đã sử dụng 256 để có nghĩa là 0xff, ahhh! Nếu bạn có một giây ở đây: Tôi chỉ thực hiện việc biên dịch chéo giữa linux và windows, cả trên phần cứng x86/x64. Giải pháp của Rickard có sử dụng một mảng char chưa ký không được tương thích với các thiết bị lớn vì nó chỉ truyền tất cả trong khoảng trống không? Tôi đoán bạn cũng có thể làm cho nó vượt qua tương thích bằng cách xác định nó trong định dạng nội bộ ([?] Không phải cái gì tôi khá hiểu trước khi thực sự). Nhưng nếu (<< 24) có nghĩa là một cái gì đó khác nhau trên mỗi, mã của bạn sẽ làm việc bất kể? – Thomas

+1

@Thomas: Anh ấy đang sử dụng ký tự, là các byte. Do đó, không có vấn đề về cuối kỳ. Vấn đề cuối cùng chỉ xảy ra khi bạn xử lý những thứ đa byte. Ông điền vào dữ liệu theo thứ tự byte, sau đó nói với OpenGL rằng dữ liệu theo thứ tự byte. Không có vấn đề gì. –

2

Nếu tôi ở đâu để làm điều tương tự như bạn, tôi sẽ sử dụng một mảng ký tự chưa ký thay vì int chưa ký với chiều dài gấp 4 lần.

unsigned char* data = new unsigned char[256*256*4]; 
for (int y = 0; y < 256; ++y) 
    for (int x = 0; x < 256; ++x) 
     if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75){ 
      data[(256*y + x)*4+0] = 156; 
      data[(256*y + x)*4+1] = 256; 
      data[(256*y + x)*4+2] = 156; 
      data[(256*y + x)*4+3] = 200; 
     }else{ 
      data[(256*y + x)*4+0] = 0; 
      data[(256*y + x)*4+1] = 0; 
      data[(256*y + x)*4+2] = 0; 
      data[(256*y + x)*4+3] = 0; 
     } 

glBindTexture(GL_TEXTURE_2D, texid); 
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_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data); 

Nhưng mã của bạn có vẻ phù hợp với tôi và tôi không chắc liệu mã ở trên có thay đổi gì không. Nếu kết quả tương tự, sau đó thử thay đổi GL_RGBA8 thành GL_RGBA. Và loại biến thể của texid là gì. Tôi alwas gọi glBindTexture với một GLuint bởi refrense (& texid) nhưng nếu texid của bạn là một con trỏ đến một GLuint (GLuint * texid;) thì tôi đoán rằng một phần là ok. (Chỉnh sửa: Chỉ cần nhận ra rằng im sai về phần cuối cùng, tôi đã suy nghĩ về glGenTexture và không glBindTexture)

+0

Cảm ơn! Mã của bạn cũng có ý nghĩa, nhưng tôi không thấy làm thế nào có thể là bất kỳ khác nhau với các chức năng glTexImage2D kể từ khi tôi đúc nó đến (void) đầu tiên. Trong mọi trường hợp, tôi thấy kết quả tương tự với mã của bạn. – Thomas

+1

A vừa thử cả hai của bạn và mã của tôi và cả hai tạo ra một vòng tròn lên trong conner quyền. Các màu sắc giống nhau cho mỗi pixel nhưng khác nhau giữa các mã (của tôi là màu hồng và màu đỏ của bạn). Tôi havent sử dụng các nhà khai thác bitwise rất nhiều nhưng tôi sẽ đoán rằng 256 của bạn nên được một 255 thay vì kể từ 256 cần 9 bit để lưu trữ. – Rickard

+0

Ah! Đó thực sự là nó! Tôi chỉ nhìn thẳng vào đó. Cảm ơn! – Thomas

Các vấn đề liên quan