2013-05-04 150 views
0

我已经编写使用OpenGL和GLSL着色器小OpenGL图像正常工作。这里是我的应用程序的屏幕:OpenGL渲染不使用OpenCV的GLSL着色器

enter image description here

现在,我的目标是混合我的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); 
} 

这里的渲染:

enter image description here

正如你所看到的结果是正确的。现在,我想尝试我的第一个程序使用GLSL着色器与OpenCV像下面一样,但是当我的应用程序启动时,我有一个黑屏。我尝试了几次测试,当我调用glUseProgram函数时,问题似乎开始了(所以当我想绑定程序着色器 - >在我的代码中它对应于程序 - > 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着色器一起使用。我尝试了几种可能的方式,但没有取得任也许我必须将视频帧缓冲区直接发送到像素着色器?在这种情况下,我该怎么做?我真的迷失了。有人可以帮助我吗?

+0

“混合我的OpenGL的框架,并从我的摄像头在一个独特的框架使用了OpenCV的一个,”这是什么意思?你不能只在背景中渲染一个四边形,并使用OpenCV中的图像数据作为纹理,然后在顶部绘制其他3D对象?我不明白你为什么要使用着色器。着色器应该做什么? – 2013-05-04 13:10:24

+0

我使用着色器来计算一些无法用基本的Opengl用法渲染的灯光效果。我只想渲染我的立方体,并将我的实时视频作为背景(如上面三角形的示例)。这就像视频框架(来自我的网络摄像头)和其他框架与立方体的并置。你明白我的意思吗? – user1364743 2013-05-04 13:27:55

+0

是的,这就是所谓的增强现实。你是否需要将这些灯光效果应用于背景或3D对象? – 2013-05-04 13:37:58

回答

0

你会设置此方式是利用你的图像数据作为纹理。 This link可能是一个很好的起点。然后,您可以在背景中渲染四边形,填充整个屏幕,并使用纹理来确定每个像素的颜色。与glDrawPixels()相比,优势在于,如果缩放窗口(和四边形),则视频中的图像将相应地缩放。

如果需要,可以在渲染四边形时使用着色器中的纹理:每个像素都会调用片段(像素)着色器,并且您将使用采样器从纹理中获取颜色。然后,您可以根据您的照明需求修改该颜色。

你画最重要的是什么,完全由你。

+0

好的,这是一个很好的答案。谢谢。我会尝试。所以关于我在上面用彩色三角形贴出的小程序,这意味着如果我只是在OpenGL上下文(没有三角形)返回视频流,OpenGL会创建(在后台)纹理(使用来自网络摄像头的像素缓冲区对于每个视频帧)并将其发送到其片段着色器并将其绘制到屏幕上。我知道OpengL使用它自己的着色器(但是这个过程是隐藏的)。所以我必须重现相同的行为,但这次是用我自己的着色器。是对的吗 ? – user1364743 2013-05-04 14:14:53

+1

我不知道如何实现'glDrawPixels'。这甚至可能取决于硬件。但是如果你不需要修改它的渲染方式,我仍然没有看到使用着色器渲染背景的原因。 – 2013-05-04 14:22:49

+0

我只是想将我的着色器应用于我的3D模型,而不是背景,因为它是视频流。摄像头记录的环境必须相同。我只想在我的3D模型上应用我的光度效果。正如你所说,它是增强现实。 – user1364743 2013-05-04 14:36:36