简单的Opengl程序不能正常工作

时间:2013-04-07 10:18:11

标签: c++ c opengl

这是一个试图实现边界填充算法的简单程序。例如,它将尝试用蓝色填充绿色矩形并保留其他所有内容。

这个程序有什么问题?

这是应用算法之前的图片: enter image description here 这是应用算法时的图片。你可以清楚地看到算法/应用程序停留在一个地方!

enter image description here

这是源代码:

#include <iostream>
#include <glut.h>

using namespace std;
bool b = false;
void init(void)
{
    glClearColor(1.0,0.0,0.0,0.0); 
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0,1366.0,0.0,768.0);
}

bool getpixelcolor(GLint x, GLint y)
{
    unsigned char pick_col[3];
    float r,g,b;
    glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);

    r = pick_col[0]/255.0;
    g = pick_col[1]/255.0;
    b = pick_col[2]/255.0;

    //cout<<"b:"<<b<<"\r\n";
    if ( (r != 1 )&&( b != 1 )&&( g == 1 ) )//g==1
    {
        return true;
    }
    else    
    {
        return false;
    }
}

void PutPoint( int x, int y ) 
{
    glBegin (GL_POINTS);
    glColor3f (1.0,1.0,1.0);
    glVertex2i (x,y);
    glEnd();

    glFlush();
    glPointSize(1);
    glBegin (GL_POINTS);
    glColor3f (0.0,0.0,1.0);
    glVertex2i (x,y);
    glEnd();
    glFlush();
}

void Filling(int x,int y)
{
    bool Value = getpixelcolor(x,y);
    if (Value==true)
    {
        PutPoint(x, y);
        Filling (x+1,y);
        Filling (x-1,y);
        Filling (x,y+1);
        Filling (x,y-1);
    }
}
void displayfnc()
{
    if (b==false)
    {
    glClear(GL_COLOR_BUFFER_BIT);
        b=true;
        glColor3f(0.0,1.0,0.0);
        glRecti(100,100,200,200);
        glFlush();
        Filling(180,180);
    }

}
void Timer(int extra)
{
    glutPostRedisplay();
    glutTimerFunc(30,Timer,0);
}
int  main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(1366,768);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("BoundaryFill");
    init();
    glutDisplayFunc(displayfnc);
    glutTimerFunc(10,Timer,0);
    glutMainLoop();
    return 0;
}

5 个答案:

答案 0 :(得分:3)

首先,你不应该用glReadPixels / glBegin(GL_POINTS)来窥视和挖掘OpenGL中的像素 - 它的速度和它一样慢。如果要在CPU上实现泛洪填充,请回读整个映像并在CPU内存上执行。

你最大的问题之一是:

r = pick_col[0]/255.0;
g = pick_col[1]/255.0;
b = pick_col[2]/255.0;

if ( (r != 1 )&&( b != 1 )&&( g == 1 ) )

从不 对花车执行相等测试!老实说,在我看来,编译器应该发出一个很大的警告,如果你在浮点数上做==!=,甚至可能会出错。浮点数始终与误差范围相关联,当您在大多数情况下比较浮点的相等性时,它们将比较为不等于(即使它们只相隔一个非常小的epsilon> 0),它们在它们的性质。

为什么不直接测试精确定义的无错误整数?

uint8_t r,g,b;
/* ... */
if ( (r != 0xff) && ( b != 0xff )&& ( g == 0xff ) )

如果您启用了全屏抗锯齿(FSAA),则可能遇到的问题是。在这种情况下,你戳的点可能会被反锯齿,导致像素颜色不完全设置为你指定的值,在这种情况下,泛洪填充算法将失败。也许添加一些保证金/门槛。或者做一些合理的事情并控制值如何被放入内存,自己动手,即将整个图片读回CPU内存,进行泛洪填充,并将其上传到OpenGL纹理中并将其打印在帧缓冲区上。

答案 1 :(得分:2)

我的第一个建议是将整个 display 图像读入本地内存,这样就不需要进行大量的OpenGL调用了。然后在本地构建一个新图像,然后将其推送到 display

答案 2 :(得分:1)

以下是您需要的程序: 您可以使用两种方法 我认为方法2是你和其他人对于边界4填充算法也需要的。

方法1:

    #include <iostream>
    #include <glut.h>

    using namespace std;
    bool b=true,c=true;
    bool A[50][50]={false};
    void init(void)
    {
        glClearColor(1.0,0.0,0.0,0.0); 
        glMatrixMode(GL_PROJECTION);
        gluOrtho2D(0.0,100.0,0.0,100.0);
    }

    bool getpixelcolor(GLint x, GLint y)
    {
        unsigned char pick_col[3];
        glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);
        float r,g,b;
        r = pick_col[0]/255.0;
        g = pick_col[1]/255.0;
        b = pick_col[2]/255.0;

        if ((r!=1)&&(b!=1)&&(g==1))g==1
        {

            return true;
        }
        else    
        {
            return false;
        }
    }

    void PutPoint( int x, int y ) 
    {

        glPointSize(2);
        glBegin (GL_POINTS);
        glColor3f (0.0,0.0,1.0);
        glVertex2i (x,y);
        glEnd();
        glFlush();

    }

    void Filling(int x,int y)
    {
        if (A[x][y]==b&&x<50&&y<50&&x>10&&y>10)
        {
            A[x][y]=c;
            PutPoint(x, y);
            Filling (x+1,y);
            Filling (x-1,y);
            Filling (x,y+1);
            Filling (x,y-1);
        }

    }
    void displayfnc()
    {
            glClear(GL_COLOR_BUFFER_BIT);
            if(b==false)
            {b=true;
             c=false;
            }
            else
                {b=false;
             c=true;
            }

            glColor3f(0.0,1.0,0.0);
            glRecti(10,50,10,50);
            Filling(40,40);

            glFlush();

    }
    int  main(int argc, char** argv)
    {

        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
        glutInitWindowSize(100,100);
        glutInitWindowPosition(0, 0);
        glutCreateWindow("BoundaryFill");
        init();
        glutDisplayFunc(displayfnc);
        glutMainLoop();
        return 0;
    }

方法2:

    #include <iostream>
    #include <glut.h>

    using namespace std;
    unsigned char pick_col[50][50][3];
    void init(void)
    {
        glClearColor(1.0,0.0,0.0,0.0); 
        glMatrixMode(GL_PROJECTION);
        gluOrtho2D(0.0,100.0,0.0,100.0);
    }

    void readAllToBuffer( GLint _start, GLint  _end ) 
    {

        for (int i=_start;i<_end;i++)
        {
            for (int j=_start;j<_end;j++)
            {
                glReadPixels(i , j , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col[i][j]);
            }
        }
    }

    bool getpixelcolor(GLint x, GLint y)
    {
        int r,g,b;
        r = pick_col[x][y][0];
        g = pick_col[x][y][1];
        b = pick_col[x][y][2];

        //cout<<"b:"<<b<<"\r\n";
        if ((r!=255)&&(b!=255)&&(g==255))//g==1
        {
            return true;
        }
        else    
        {
            return false;
        }
    }

    void PutPoint( int x, int y ) 
    {
         pick_col[x][y][0]=0;
         pick_col[x][y][1]=0;
         pick_col[x][y][2]=255;
        glPointSize(2);
        glBegin (GL_POINTS);
        glColor3f (0.0,0.0,1.0);
        glVertex2i (x,y);
        glEnd();
        glFlush();

    }

    void Filling(int x,int y)
    {
        bool Value=getpixelcolor(x,y);
        if (Value==true)
        {
            PutPoint(x, y);

            Filling (x+1,y);
            Filling (x-1,y);
            Filling (x,y+1);
            Filling (x,y-1);
        }
    }
    void displayfnc()
    {   glClear(GL_COLOR_BUFFER_BIT);

            glColor3f(0.0,1.0,0.0);
            glRecti(0,0,50,50);
            glFlush();
            readAllToBuffer(0, 49);
            Filling(40,40);
            glFlush();

    }
    void Timer(int extra)
    {
        glutPostRedisplay();
        glutTimerFunc(30,Timer,0);
    }
    int  main(int argc, char** argv)
    {

        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
        glutInitWindowSize(100,100);
        glutInitWindowPosition(0, 0);
        glutCreateWindow("BoundaryFill");
        init();
        glutDisplayFunc(displayfnc);
        //glutTimerFunc(10,Timer,0);
        glutMainLoop();
        return 0;
    }

答案 3 :(得分:0)

<强> 1 即可。不是glutSwapBuffers(),这对于看到某些东西是必不可少的。

<强> 2 即可。您不必使用glFlush()刷新管道,即使不是glutSwapBuffers()

之前

第3 即可。像素一样逐像素地绘制/读取,使用纹理或一些聪明的多边形绘制魔法。

答案 4 :(得分:0)

为什么要制作r,g,b花车?

我会将所有功能更改为:

bool getpixelcolor(GLint x, GLint y)
{
    unsigned char pick_col[3];
    glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);

    if ( (pick_col[0] != 255 )&&( pick_col[1] != 255 )&&( pick_col[2] == 255 ) )//g==1
    {
        return true;
    }
    else    
    {
        return false;
    }
}