2012-05-10 2 views
6

У меня есть код в OpenGL, чтобы отобразить изображение YUV в окне просмотра OpenGL. Программа работает без проблем при работе на картах nvidia, но при возникновении ошибки при работе с Intel HD 3000, к сожалению, это целевая машина. Точка, где генерируется ошибка, отмечена в коде.Opengl GL_QUADS производит ошибку 0x506

программа затенения

// 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; 
}; 

Затем я запустить программу, как это:

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); 

обновления поскольку ошибка происходит с буферами кадра, я обнаружил, что они используются как это: когда создается экземпляр программы, создается буфер кадров следующим образом:

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(); 

Изображение YUV поставляется в виде плитки, которые собираются рендерингом в этом fbo. Всякий раз, когда начинается кадр, это выполняется:

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); 

Тогда приведенный выше код выполняется, и после того, как все плитки были собраны вместе

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

Запуск под gDEBugger. Любая из этих операций могла быть неудачной, вы не можете просто вызвать glError один раз в случайно выбранном месте. –

+0

У меня есть glGetError по всей программе. Я просто упрощаю код здесь. Я знаю, что это не так. – Sambatyon

+0

0x506 - GL_INVALID_FRAMEBUFFER_OPERATION, которая может быть красной селедкой. Используете ли вы какие-либо FBOs в своем коде? – luke

ответ

1

Я решил проблему. Это была проблема с расширениями, из-за чего объект буфера визуализации исчез. Я в принципе изменил эту

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); 

для этого

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); 

, а затем он работал. Я все еще задаюсь вопросом, в чем проблема, но до сих пор я доволен результатом. Особая благодарность @luke, который ответил, помог найти точную точку проблемы.

+0

Вы используете что-то вроде GLEW для расширения функций расширения? Я немного удивлен, что gl * EXT функции/константы ведут себя иначе, чем gl * версии, но я рад, что вы его работали. Если вы выясните, в чем разница, сообщите об этом. – luke

+0

yup, я использую GLEW, я тоже был удивлен этим поведением, но я не могу жаловаться, если все работает. Надеюсь, я смогу понять, в чем проблема. – Sambatyon

0

Точно, какая команда вызывает ошибку? Попытайтесь заменить GL_QUADS на GL_TRIANGLE_FAN.

+0

Использование TRIANGLE_FAN для рисования более чем одного квадранта в одной партии приведет к тому, что квадранты будут соединены вместе, что закручивает текстурирование * плохо *. Лучше использовать два треугольника на квадрат и рисовать с помощью TRIANGLES. –

+0

Это для одного квадроцикла, конечно :) Просто чтобы найти проблему. – demi

1

glGetError Код ошибки "stick" и не удаляются автоматически. Если что-то в начале ваша программа генерирует ошибку OpenGL И вы проверите код ошибки 1000 opengl позже, ошибка будет по-прежнему здесь.

Так что, если вы хотите понять, что происходит ДЕЙСТВИТЕЛЬНО, проверьте ошибки после каждого вызова OpenGL или вызовите glGetError в цикле, пока не будут возвращены все коды ошибок (как предлагает документация OpenGL).

+0

Как я упоминал в комментариях выше, у меня есть glGetError по всей программе, почти после каждого из операторов. Фактически, многие из приведенных здесь высказываний вызывают из других функций или находятся в методах других классов, я просто пишу это здесь, чтобы сделать его читаемым. – Sambatyon

+0

@ Samatyon: * «Я просто пишу это здесь» * Итак, вместо фрагмента кода, который создает проблему, вы написали еще один фрагмент кода. "Большой". * «почти после каждого из утверждений» * по закону Мерфи ваш * «почти» * означает, что после утверждения, вызывающего проблему, нет ошибки. Потому что вы не сказали **, какая строка ** заставляет glGetError возвращать код ошибки, это означает, что вы не проверяете ошибку после каждого утверждения. – SigTerm

+0

Я бы не хотел, чтобы я поставил почти пятьсот строк кода вызовов non opengl, обработчиков событий и всего этого. Допустим, я уверен, что ошибка точно там – Sambatyon

7

Что значение status после:

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 

Если значение ничего, кроме GL_FRAMEBUFFER_COMPLETE, OpenGL, вероятно душить, когда он пытается прочитать из FBO.

glCheckFramebufferStatus docs описывает другие значения (ошибки), которые он может вернуть, и что их вызывает.

Особый интерес может быть:

Если в настоящее время связаны фреймбуфера не FrameBuffer полной, то это ошибка, чтобы попытаться использовать видеобуфер для записи или чтения . Это означает, что команды рендеринг (glDrawArrays и glDrawElements), а также команды, которые читают фреймбуфера (glReadPixels, glCopyTexImage2D и glCopyTexSubImage2D) будут генерировать ошибки, если GL_INVALID_FRAMEBUFFER_OPERATION вызываются, когда фреймбуфер не FrameBuffer завершен.

(курсив мой)

редактировать на основе ваших комментариев:

Перефразируя документы WRT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:

Не все точки крепления фреймбуфера являются крепление фреймбуфера завершена. Это означает, что одно из следующих действий происходит:

  • По крайней мере, одну точку присоединения с renderbuffer или текстуры прикрепленного имеет не его присоединенный объект больше не существует или имеет прикрепленное изображение с шириной или высотой нуля,
  • Точка крепления цвета имеет прикрепленное изображение без цвета. Цветопередающие форматы включают GL_RGBA4, GL_RGB5_A1 и GL_RGB565.
  • Точка крепления глубины имеет прикрепленное изображение без глубины. GL_DEPTH_COMPONENT16 - единственный формат, который можно сделать с глубиной.
  • Точка крепления трафарета имеет прикрепленное изображение без трафарета. GL_STENCIL_INDEX8 - единственный формат рендеринга трафаретов.

Мы можем исключить последние 2 пули, потому что, похоже, вы не используете глубинные или трафаретные привязки. Это оставляет два вызова изучить:

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); 

opengl.org wiki on FBOs От:

Вы получаете GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, когда какой-либо из вложений являются «неполными». Критерии для полноты являются:

  • Исходный объект для изображения все еще существует и имеет тот же тип, что был прикреплен с.
  • Изображение имеет ненулевую ширину и высоту.
  • Слой для вложений текстур 3D или массива меньше глубины текстуры.
  • Формат изображения должен соответствовать требованиям точки привязки, как определено выше. Цвет-визуализируемых форматы для цветных приложений и т.д.

Вики говорит GL_COLOR_ATTACHMENTi:

Эти точки крепления могут иметь только изображения, связанные с ними с цветом форматов. Отображаемый Все сжатые форматы изображений не являются цветными и не могут быть прикреплены к FBO.

Двойная проверка того, что fbo_texture и rbo_id по-прежнему действительны и что их высота/ширина не равны 0. Наконец, это может быть формат fbo_texture. У вас установлено значение GL_RGBA8, но документы говорят, что допустимые параметры включают GL_RGBA4, GL_RGB5_A1 и GL_RGB565. Я не уверен, исключает ли это все другие форматы (например, ваш GL_RGBA8). Вики полагают, что любой не сжатый формат должен работать. Попробуйте переключить его на GL_RGBA4 и посмотрите, получится ли это.

+0

Это помогло мне как-то получить этот GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, теперь я должен выяснить, что это значит;) – Sambatyon

+0

человек, ваша помощь прошла отлично. Я просто обнаружил, что буфер визуализации недействителен. GlIsRenderbuffer (rbo_id) возвращает 0. Теперь вопрос заключается в том, как это произошло в первую очередь, и как я могу предотвратить его. – Sambatyon

Смежные вопросы