0

我使用 OpenGL 和 GLSL 着色器编写了一个小型 OpenGL 程序。这是我的应用程序的屏幕:

在此处输入图像描述

现在,我的目标是使用 OpenCV 将我的 opengl 框架和来自网络摄像头的框架混合在一个独特的框架中。在使用 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);
}

这是渲染:

在此处输入图像描述

如您所见,结果是正确的。现在,我想尝试使用带有 OpenCV 的 GLSL 着色器的第一个程序,如下所示,但是当我的应用程序启动时出现黑屏。我尝试了几个测试,当我调用 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);
}

所以我认为问题来自不能与 GLSL 着色器一起使用的 glDrawPixels。我尝试了几种可能的方法,但都没有成功。也许我必须将视频帧缓冲区直接发送到像素着色器?在这种情况下,我该怎么做?我真的迷路了。有人可以帮助我吗?

4

1 回答 1

0

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

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

你在上面画什么取决于你。

于 2013-05-04T13:51:01.657 回答