2013-05-04 110 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