2012-05-10 21 views
6

Tôi có một số mã trong OpenGL để hiển thị hình ảnh YUV trên chế độ xem OpenGL. Chương trình hoạt động mà không có vấn đề gì khi chạy trên thẻ nvidia, nhưng nó tạo ra lỗi khi chạy trên Intel HD 3000, thật đáng buồn là máy đích. Điểm mà lỗi được tạo ra được đánh dấu trong mã.Opengl GL_QUADS tạo lỗi 0x506

Các chương trình shader là

// Vertex Shader 
#version 120 
void main() { 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

// fragment shader 
#version 120 
uniform sampler2D texY; 
uniform sampler2D texU; 
uniform sampler2D texV; 
void main() { 
    vec4 color; 
    float y = texture2D(texY, gl_TexCoord[0].st).r; 
    float u = texture2D(texU, gl_TexCoord[0].st).r; 
    float v = texture2D(texV, gl_TexCoord[0].st).r; 
    color.r = (1.164 * (y - 0.0625)) + (1.596 * (v - 0.5)); 
    color.g = (1.164 * (y - 0.0625)) - (0.391 * (u - 0.5)) - (0.813 * (v - 0.5)); 
    color.b = (1.164 * (y - 0.0625)) + (2.018 * (u - 0.5)); 
    color.a = 1.0; 
    gl_FragColor = color; 
}; 

Sau đó, tôi chạy chương trình như thế này:

GLuint textures[3]; 
glGenTextures(3, textures); 

glBindTexture(GL_TEXTURE_2D, textures[YTEX]); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glBindTexture(GL_TEXTURE_2D, textures[UTEX]); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glBindTexture(GL_TEXTURE_2D, textures[VTEX]); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glBindTexture(GL_TEXTURE_2D, 0); 

GLsizei size = width * height; 

GLvoid *y = yuv_buffer; 
GLvoid *u = (GLubyte *)y + size; 
GLvoid *v = (GLubyte *)u + (size >> 2); 

glUseProgram(program_id); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, textures[0]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, 
      GL_UNSIGNED_BYTE, y); 
glUniform1i(glGetUniformLocation(program_id, "texY"), 0); 

glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, textures[1]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, 
      GL_LUMINANCE, GL_UNSIGNED_BYTE, u); 
glUniform1i(glGetUniformLocation(program_id, "texU"), 1); 

glActiveTexture(GL_TEXTURE2); 
glBindTexture(GL_TEXTURE_2D, textures[2]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, 
      GL_LUMINANCE, GL_UNSIGNED_BYTE, u); 
glUniform1i(glGetUniformLocation(program_id, "texV"), 2); 

glBegin(GL_QUADS); 
glTexCoord2f(texLeft, texTop); 
glVertex2i(left, top); 
glTexCoord2f(texLeft, texBottom); 
glVertex2i(left, bottom); 
glTexCoord2f(texRight, texBottom); 
glVertex2i(right, bottom); 
glTexCoord2f(texRight, texTop); 
glVertex2i(right, top); 
glEnd(); 

// glError() returns 0x506 here 

glBindTexture(GL_TEXTURE_2D, 0); 
glActiveTexture(GL_TEXTURE0); 

glUseProgram(0); 

cập nhật kể từ khi lỗi xảy ra với bộ đệm khung hình, tôi phát hiện ra chúng được sử dụng như thế này: khi chương trình được khởi tạo, bộ đệm khung được tạo như sau:

glViewport(0, 0, (GLint)width, (GLint)height); 

glGenFramebuffers(1, &fbo_id); 
glGenTextures(1, &fbo_texture); 
glGenRenderbuffers(1, &rbo_id); 

glBindTexture(GL_TEXTURE_2D, fbo_texture); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, 
      GL_RGBA, GL_UNSIGNED_BYTE, 0); 
glBindTexture(GL_TEXTURE_2D, 0); 

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id); 
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); 
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); 

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id); 
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
          GL_TEXTURE_2D, fbo_texture, 0); 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
          GL_RENDERBUFFER_EXT, rbo_id); 

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 

glPushAttrib(GL_TEXTURE_BIT); 

glBindTexture(GL_TEXTURE_2D, m_frameTexture->texture()); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glPopAttrib(); 

Ảnh YUV được ghép nối bằng các lát, được lắp ráp bằng cách hiển thị trong fbo này. Bất cứ khi nào một khung bắt đầu, điều này được thực hiện:

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 
glDrawBuffer(GL_BACK); 

glViewport(0, 0, (GLint)width, (GLint)height); 

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_id); 

Sau đó, đoạn mã trên được thực thi, và sau khi tất cả các gạch đã được lắp ráp với nhau

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 
glPushAttrib(GL_VIEWPORT_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT); 
glViewport(0, 0, width, height); 

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
glClear(GL_COLOR_BUFFER_BIT); 

glMatrixMode(GL_PROJECTION); 
glPushMatrix(); 

glLoadIdentity(); 
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0); 

glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadIdentity(); 

glEnable(GL_TEXTURE_2D); 
glDisable(GL_DEPTH_TEST); 

glBindTexture(GL_TEXTURE_2D, fbo_texture); 

glBegin(GL_QUADS); 
glTexCoord2i(0, 0); 
glVertex2f(renderLeft, renderTop); 
glTexCoord2i(0, 1); 
glVertex2f(renderLeft, renderTop + renderHeight); 
glTexCoord2i(1, 1); 
glVertex2f(renderLeft + renderWidth, renderTop + renderHeight); 
glTexCoord2i(1, 0); 
glVertex2f(renderLeft + renderWidth, renderTop); 
glEnd(); 

glPopMatrix(); 

glMatrixMode(GL_PROJECTION); 
glPopMatrix(); 
glPopAttrib(); 
+1

Chạy dưới gDEBugger. Bất kỳ hoạt động nào trong số đó có thể thất bại, bạn không thể chỉ gọi glError một lần ở một nơi được chọn ngẫu nhiên. –

+0

Tôi có glGetError trên toàn bộ chương trình. Tôi chỉ đơn giản hóa mã ở đây. Tôi biết nó không chính xác ở đó. – Sambatyon

+0

0x506 là GL_INVALID_FRAMEBUFFER_OPERATION, có thể là một cá trích đỏ. Bạn đang sử dụng bất kỳ FBO nào trong mã của bạn? – luke

Trả lời

1

Tôi đã giải quyết được sự cố. Đó là một vấn đề mở rộng làm cho đối tượng bộ đệm render biến mất. Tôi về cơ bản thay đổi này

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id); 
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); 
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); 

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id); 
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
          GL_TEXTURE_2D, fbo_texture, 0); 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
          GL_RENDERBUFFER_EXT, rbo_id); 

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 

cho điều này

glBindRenderbuffer(GL_RENDERBUFFER, rbo_id); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 
glBindRenderbuffer(GL_RENDERBUFFER, 0); 

glBindFramebuffer(GL_FRAMEBUFFER, fbo_id); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
          GL_TURE_2D, fbo_texture, 0); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
          GL_RENDERBUFFER, rbo_id); 

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 

và sau đó nó làm việc. Tôi vẫn tự hỏi chính xác vấn đề là gì, nhưng đến giờ tôi vẫn hài lòng với kết quả. Đặc biệt cảm ơn @luke, người trả lời đã giúp xác định vị trí chính xác của vấn đề.

+0

Bạn đang sử dụng một cái gì đó như GLEW để kéo chức năng mở rộng? Tôi là một chút ngạc nhiên rằng gl * EXT chức năng/hằng số cư xử khác với các phiên bản gl *, nhưng tôi vui vì bạn đã nhận nó làm việc. Nếu bạn tìm ra sự khác biệt là gì, hãy đăng bài về nó. – luke

+0

yup, tôi đang sử dụng GLEW, tôi cũng ngạc nhiên về hành vi đó, nhưng tôi không thể phàn nàn nếu mọi thứ hoạt động. Tôi hy vọng tôi có thể có thời gian để thực sự hiểu được vấn đề là gì. – Sambatyon

0

Chính xác, chỉ huy những gì đặt ra lỗi? Hãy thử thay thế GL_QUADS bằng GL_TRIANGLE_FAN.

+0

Sử dụng TRIANGLE_FAN để vẽ nhiều hơn một quad trong một lô sẽ dẫn đến quads được kết nối với nhau, mà vít lên texturing * badly *. Tốt hơn là nên sử dụng hai hình tam giác trên mỗi hình vuông và vẽ bằng các hình tam giác. –

+0

Điều này là dành cho một quad, tất nhiên :) Chỉ để tìm ra vấn đề. – demi

1

glGetError mã lỗi "dính" và không tự động bị xóa. Nếu một cái gì đó ở đầu chương trình của bạn tạo ra lỗi OpenGL VÀ bạn kiểm tra mã lỗi 1000 cuộc gọi opengl sau đó, lỗi sẽ vẫn còn ở đây. Vì vậy, nếu bạn muốn hiểu những gì thực sự xảy ra, hãy kiểm tra lỗi sau mỗi cuộc gọi OpenGL, hoặc gọi glGetError trong một vòng lặp, cho đến khi tất cả các mã lỗi được trả lại (như tài liệu OpenGL gợi ý).

+0

Như tôi đã đề cập trong các ý kiến ​​ở trên, tôi có glGetError trên tất cả các chương trình, gần như sau mỗi báo cáo. Thực tế, nhiều câu lệnh ở đây được gọi từ các hàm khác hoặc trong các phương thức của các lớp khác, tôi chỉ viết nó ở đây như thế để làm cho nó dễ đọc. – Sambatyon

+0

@Samatyon: * "Tôi chỉ viết nó ở đây như thế" * Vì vậy, thay vì đoạn mã tạo ra vấn đề, bạn đã viết một số đoạn mã khác. "Tuyệt quá". * "gần như sau mỗi tuyên bố" * theo luật Murphy của bạn * "gần như" * có nghĩa là không có lỗi kiểm tra ngay sau khi câu lệnh gây ra sự cố. Vì bạn không nói ** dòng nào ** làm cho glGetError trả về mã lỗi, điều đó có nghĩa là bạn không kiểm tra lỗi sau mỗi câu lệnh. – SigTerm

+0

YOu không muốn tôi đặt gần năm trăm dòng lệnh gọi không sử dụng, xử lý sự kiện và mọi thứ. Hãy nói rằng tôi khá chắc chắn lỗi là chính xác có – Sambatyon

7

giá trị của status sau gì:

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 

Nếu giá trị là bất cứ điều gì khác hơn là GL_FRAMEBUFFER_COMPLETE, OpenGL có thể sẽ nghẹt thở khi nó cố gắng đọc từ FBO.

glCheckFramebufferStatus docs mô tả các giá trị (lỗi) khác mà nó có thể trả về và nguyên nhân gây ra lỗi.

Quan tâm đặc biệt có thể là:

Nếu framebuffer hiện ràng buộc không đệm khung hoàn chỉnh, sau đó nó là một lỗi để cố gắng sử dụng vùng đệm khung cho văn bản hoặc đọc. Điều này có nghĩa rằng render lệnh (glDrawArrays và glDrawElements) cũng như các lệnh đọc framebuffer (glReadPixels, glCopyTexImage2D, và glCopyTexSubImage2D) sẽ tạo ra GL_INVALID_FRAMEBUFFER_OPERATION lỗi nếu gọi trong khi framebuffer không đệm khung hoàn chỉnh.

(tôi nhấn mạnh)

chỉnh sửa dựa trên ý kiến ​​của bạn:

Để diễn giải GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT docs wrt:

Không phải tất cả các điểm tập tin đính kèm đệm khung là tập tin đính kèm đệm khung hoàn chỉnh. Điều này có nghĩa rằng một trong những điều sau đây xảy ra:

  • Ít nhất một điểm gắn với một renderbuffer hoặc kết cấu gắn liền có đối tượng trực thuộc không còn tồn tại hoặc có một hình ảnh gắn liền với một chiều rộng hoặc chiều cao của zero,
  • Điểm đính kèm màu có hình ảnh không thể hiển thị màu được đính kèm. Các định dạng có thể hiển thị màu bao gồm GL_RGBA4, GL_RGB5_A1 và GL_RGB565.
  • Điểm đính kèm chiều sâu có hình ảnh không thể hiển thị chi tiết được đính kèm. GL_DEPTH_COMPONENT16 là định dạng có thể hiển thị chiều sâu duy nhất.
  • Điểm đính kèm stencil có đính kèm hình ảnh không được stencil. GL_STENCIL_INDEX8 là định dạng stencil-renderable duy nhất.

Chúng tôi có thể loại trừ 2 dấu đầu dòng cuối cùng, vì nó không xuất hiện mà bạn đang sử dụng các tệp đính kèm chiều sâu hoặc stencil. Điều này khiến hai cuộc gọi để kiểm tra:

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_texture, 0); 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo_id); 

Từ opengl.org wiki on FBOs:

Bạn nhận được GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT khi bất kỳ file đính kèm là 'đầy đủ'. Tiêu chí để hoàn thành là:

  • Đối tượng nguồn cho hình ảnh vẫn tồn tại và có cùng loại được đính kèm.
  • Hình ảnh có chiều rộng và chiều cao khác 0.
  • Lớp cho tệp đính kèm kết cấu 3D hoặc mảng ít hơn độ sâu của kết cấu.
  • Định dạng của hình ảnh phải khớp với các yêu cầu của điểm đính kèm, như được định nghĩa ở trên. định dạng màu renderable cho file đính kèm màu vv

Các wiki nói về GL_COLOR_ATTACHMENTi:

Những điểm tập tin đính kèm chỉ có thể có hình ảnh bị ràng buộc đối với họ với định dạng màu renderable. Tất cả các định dạng hình ảnh nén không phải là có thể hiển thị màu và do đó không thể được đính kèm với FBO.

Kiểm tra kỹ xem fbo_texture và rbo_id vẫn hợp lệ và chiều cao/chiều rộng của chúng không bằng 0. Cuối cùng, nó có thể là định dạng của fbo_texture. Bạn đã đặt nó thành GL_RGBA8, nhưng các tài liệu cho biết các tùy chọn hợp lệ bao gồm GL_RGBA4, GL_RGB5_A1 và GL_RGB565. Tôi không chắc chắn có hay không loại trừ tất cả các định dạng khác (như GL_RGBA8 của bạn). Wiki dường như gợi ý rằng mọi định dạng không nén đều hoạt động. Hãy thử chuyển nó sang GL_RGBA4, và xem nó có hoạt động không.

+0

Điều đó đã giúp bằng cách nào đó, tôi nhận được GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT này bây giờ tôi phải tìm ra điều đó có nghĩa là gì;) – Sambatyon

+0

người đàn ông, sự giúp đỡ của bạn đã được tuyệt vời. Tôi chỉ thấy rằng bộ đệm render không hợp lệ glIsRenderbuffer (rbo_id) trả về 0. Câu hỏi bây giờ là, làm thế nào điều đó xảy ra ngay từ đầu, và làm thế nào để ngăn chặn nó xảy ra. – Sambatyon

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