Я закодировал небольшую программу OpenGL с использованием шейдеров OpenGL и GLSL. Вот экран моего приложения:OpenGL рендеринг работает неправильно с OpenCV с использованием шейдеров GLSL
Теперь моя цель состоит в том, чтобы смешать мой OPENGL кадр и один из веб-камеры в уникальной раме с помощью OpenCV. Прежде чем делать это с помощью шейдеров GLSL, я попытался сделать очень простую программу, рисуя цветной треугольник с некоторыми базовыми функциями OpenGL (glBengin, glVertex и т. Д.).
static int initGL()
{
if (!glfwInit())
return (-1);
if (!glfwOpenWindow(500, 500, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) {
glfwTerminate();
return (-1);
}
glEnable(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 500.0f/500.0f, 0.1f, 100.0f);
gluLookAt(0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
return (0);
}
static void drawGL()
{
glBegin(GL_TRIANGLES);
glColor3ub(255, 0, 0);
glVertex3f(-1.0f, 0.0f, 0.0f);
glColor3ub(0, 255, 0);
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3ub(0, 0, 255);
glVertex3f(1.0f, 0.0f, 0.0f);
glEnd();
}
int main(void)
{
initGL();
CvCapture *capture = cvCaptureFromCAM(CV_CAP_ANY);
if (!capture) {
fprintf(stderr, "ERROR: capture is NULL \n");
getchar();
return (-1);
}
while (1)
{
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_MODELVIEW);
IplImage *frame = cvQueryFrame(capture);
if (!frame) {
fprintf(stderr, "ERROR: frame is null...\n");
getchar();
break;
}
glDrawPixels(frame->width, frame->height, GL_RGB, GL_UNSIGNED_BYTE, frame->imageData);
drawGL();
glfwSwapBuffers();
if ((cvWaitKey(10) & 255) == 27) break;
}
cvReleaseCapture(&capture);
cvDestroyWindow("mywindow");
return (EXIT_SUCCESS);
}
Вот рендер:
Как вы можете видеть результат является правильным. Теперь я хотел попробовать свою первую программу, используя шейдеры GLSL с OpenCV, как показано ниже, но когда мое приложение запущено, у меня есть черный экран. Я пробовал несколько тестов, и проблема, похоже, начинается, когда я вызываю функцию glUseProgram (поэтому, когда я хочу привязать шейдер программы -> в моем коде, она соответствует вызову program-> bind()). Но здесь я использую функцию glDrawPixels для загрузки моего видеофрагмента. Я думаю, что это не хорошая функция, если я хочу использовать шейдеры GLSL. Вот часть моего кода C++:
[...]
/*My GLSL shaders initialization*/
[...]
int main(int ac, char **av)
{
bool isAlive = true;
unsigned int vaoID = 0;
SDL_Event event;
GLuint textureID = 0;
ShaderProgram *program = NULL;
if (!glfwInit())
return (-1);
if (!glfwOpenWindow(WIDTH, HEIGHT, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) {
glfwTerminate();
return (-1);
}
glEnable(GL_DEPTH_TEST);
//Viewport initialization
glViewport(0, 0, WIDTH, HEIGHT);
//Vertex declaration
VertexDeclaration *vDeclar = initVertexDeclaration();
//Glew init component
glewInit();
//VBO initialization
VertexBuffer *vBuffer = initVBO();
//Shaders initialization
program = initShaders("triangle-pf.vert", "triangle-pf.frag");
//Texture initialization
textureID = loadBMPTexture("Box.bmp");
//VAO initialization
initVAO(vaoID, vBuffer, textureID, vDeclar);
//Screen capture Initialization
CvCapture *capture = cvCaptureFromCAM(CV_CAP_ANY);
if (!capture) {
fprintf(stderr, "ERROR: capture is NULL \n");
getchar();
return (-1);
}
//Main loop
while (isAlive == true)
{
//eventListener(&event, &isAlive);
if (glfwGetKey(GLFW_KEY_ESC))
isAlive = false;
glClearDepth(1.0f);
glClearColor(0.13f, 0.12f, 0.13f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//---------------------------------------------------
IplImage *frame = cvQueryFrame(capture);
if (!frame) {
fprintf(stderr, "ERROR: frame is null...\n");
getchar();
break;
}
//---------------------------------------------------
program->bind();
//Projection matrix
glm::mat4 ProjectionMatrix = glm::perspective(45.0f, 500.0f/500.0f, 0.1f, 100.0f);
//View matrix
glm::mat4 ViewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 8.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
//Model matrix
glm::mat4 ModelMatrix = glm::mat4(1.0f);
ModelMatrix = glm::translate(ModelMatrix, glm::vec3(0.0f, 0.0f, 0.0f));
ModelMatrix = glm::rotate(ModelMatrix, angle, glm::vec3(1.0f, 1.0f, 1.0f));
ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, 1.0f));
//Prepare matrix
glm::mat4 ModelViewMatrix = ViewMatrix * ModelMatrix;
glm::mat3 NormalMatrix = glm::mat3(glm::vec3(ModelViewMatrix[0]), glm::vec3(ModelViewMatrix[1]), glm::vec3(ModelViewMatrix[2]));
glm::mat4 ModelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix;
glm::vec4 LightPositionVec1 = ViewMatrix * glm::vec4(LightPosition1[0], LightPosition1[1], LightPosition1[2], LightPosition1[3]);
//Send source light properties
program->setUniform("LightInfos[0].La", glm::vec3(0.000000f, 0.000000f, 0.000000f));
program->setUniform("LightInfos[0].Ld", glm::vec3(0.800000f, 0.800000f, 0.800000f));
program->setUniform("LightInfos[0].Ls", glm::vec3(1.000000f, 1.000000f, 1.000000f));
program->setUniform("LightInfos[0].Le", glm::vec3(0.200000f, 0.200000f, 0.200000f));
/*program->setUniform("LightInfos[1].La", glm::vec3(0.000000f, 0.000000f, 0.000000f));
program->setUniform("LightInfos[1].Ld", glm::vec3(0.800000f, 0.800000f, 0.800000f));
program->setUniform("LightInfos[1].Ls", glm::vec3(0.000000f, 1.000000f, 1.000000f));
program->setUniform("LightInfos[1].Le", glm::vec3(0.200000f, 0.200000f, 0.200000f));*/
//Send model materials properties
program->setUniform("MaterialInfos.Ka", glm::vec3(0.000000f, 0.000000f, 0.000000f));
program->setUniform("MaterialInfos.Kd", glm::vec3(1.000000f, 1.000000f, 1.000000f));
program->setUniform("MaterialInfos.Ks", glm::vec3(1.000000f, 1.000000f, 1.000000f));
program->setUniform("MaterialInfos.Ke", glm::vec3(0.200000f, 0.000000f, 0.200000f));
program->setUniform("MaterialInfos.Shininess", 10.0f);
//Send light position
program->setUniform("LightInfos[0].Position", LightPositionVec1);
//Send matrix
program->setUniform("ProjectionMatrix", ProjectionMatrix);
program->setUniform("NormalMatrix", NormalMatrix);
program->setUniform("ModelViewMatrix", ModelViewMatrix);
program->setUniform("ModelMatrix", ModelMatrix);
program->setUniform("MVP", ModelViewProjectionMatrix);
glDrawPixels(frame->width, frame->height, GL_RGB, GL_UNSIGNED_BYTE, frame->imageData);
//VAO binding
glBindVertexArray(vaoID);
//Render meshes
glDrawArrays(GL_TRIANGLES, 0, vBuffer->getSize());
glBindVertexArray(0);
program->release();
angle += 0.50f;
glFlush();
glfwSwapBuffers();
}
unsigned int vboID = vBuffer->getHandle();
glDeleteBuffers(1, &vboID);
glDeleteVertexArrays(1, &vaoID);
return (0);
}
Так что я думаю, что проблема исходит от glDrawPixels, которые не могут быть использованы с GLSL шейдеров. Я пробовал несколько возможных путей без каких-либо успехов. Может быть, мне нужно отправить буфер видеофрагмента прямо в пиксельный шейдер? В этом случае, как я могу это сделать? Я действительно потерян. Кто-нибудь может мне помочь?
«Смешайте мою рамку opengl и одну из моей веб-камеры в уникальной рамке с помощью OpenCV», что это значит? Не можете ли вы просто сделать квад в фоновом режиме и использовать данные изображения из OpenCV в качестве текстуры, а затем нарисовать другие 3D-объекты сверху? Я не понимаю, почему вы хотите использовать шейдер. Что должен делать шейдер? –
Я использую шейдеры для вычисления некоторых световых эффектов, которые невозможно визуализировать с использованием базового Opengl. Я просто хочу отобразить свой куб и иметь видео в реальном времени в качестве фона (например, пример с треугольником выше). Это похоже на сопоставление видеорамки (с моей веб-камеры) и другого фрейма с кубом. Вы видите, что я имею в виду ? – user1364743
Да, это называется дополненной реальностью. Вам нужны эти световые эффекты для вашего фона или 3D-объектов? –