Используя QT 4.7 и QGLWidget, я хочу использовать QGLWidget :: paintGL () для рендеринга сцены в QGLFramebufferObject, а затем — используя текстуру, сгенерированную QGLFramebufferObject, — на экран. Для второго шага я отрисовываю полноэкранный квад с ортогональной проекцией и использую собственный шейдер для рендеринга текстуры на него.
Рендеринг в QGLFramebufferObject, кажется, работает нормально (по крайней мере, я могу вызвать QGLFramebufferObject :: toImage (). Save (filename), и я получаю правильно отрендеренное изображение), но я не могу заставить визуализированную текстуру быть нарисованной на экране.
Вот код, который я использую для рендеринга в объект framebuffer:
//Draw into framebufferobject
_fbo->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
_camera->applyModelviewMatrix();
_scene->glDraw();
glFlush();
_fbo->release();
_fbo->toImage().save("image.jpg");
Как сказано, сохраненное здесь изображение содержит правильно отрендеренное изображение.
Вот код, который я пытаюсь отрендерить объект framebuffer на экране. Я использую собственный шейдер для его рендеринга.
//Draw framebufferobject to a full-screen quad on the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
_selectionShader->bind();
glBindTexture(GL_TEXTURE_2D, _fbo->texture());
_selectionShader->setUniformValue("renderedTexture", _fbo->texture());
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex3f(0.0f,0.0f,0.0f);
glTexCoord2f(1.0,0.0);
glVertex3f(1.0f,0.0f,0.0f);
glTexCoord2f(1.0,1.0);
glVertex3f(1.0f,1.0f,0.0f);
glTexCoord2f(0.0,1.0);
glVertex3f(0.0f,1.0f,0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
}
Вершинный шейдер просто проходит через позицию, которую он использует в качестве координат текстуры
varying vec2 position;
void main()
{
gl_Position = ftransform();
position = gl_Vertex.xy;
}
И фрагмент шейдера рисует текстуру
varying vec2 position;
uniform sampler2D renderedTexture;
void main()
{
gl_FragColor = texture2D(renderedTexture, position);
}
Проекция, которую я делаю, правильная, потому что когда я обмениваюсь фрагментным шейдером со следующим, он рисует ожидаемый градиент цвета:
varying vec2 position;
uniform sampler2D renderedTexture;
void main()
{
gl_FragColor = vec4(position.x, 0.0f, position.y, 1.0f);
}
Но используя другой фрагментный шейдер, который должен визуализировать текстуру, я получаю только пустой экран (который был очищен с помощью glClear () в начале рендеринга). Таким образом, фрагментный шейдер выглядит черным или ничего.
Я что-то пропустил? Правильно ли я передаю текстуру в шейдер? Должен ли я сделать что-нибудь еще, чтобы подготовить текстуру?
_selectionShader->setUniformValue("renderedTexture", _fbo->texture());
Это (или) неправильная часть. Форма сэмплера в шейдере устанавливается не для объекта текстуры, а для единицы текстуры, с которой этот объект связан как текстура (с которой вы уже работали glBindTexture(GL_TEXTURE_2D, _fbo->texture()
). Так как вы, кажется, используете GL_TEXTURE0
все время, вы просто должны установить его на единицу текстуры 0
:
_selectionShader->setUniformValue("renderedTexture", 0);
Кстати, не надо glEnable(GL_TEXTURE_2D)
, что не нужно при использовании шейдеров. А зачем использовать glTexCoord2f
если вы просто используете положение вершины в качестве координаты текстуры в любом случае?
Других решений пока нет …