首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >glReadPixels()返回0

glReadPixels()返回0
EN

Stack Overflow用户
提问于 2014-04-25 07:09:03
回答 1查看 2K关注 0票数 1

我在Windows平台上使用gl和glut

我的问题是,glReadPixels返回所有的0。我想这与我初始化窗口的方式有关,所以它无法得到正确的像素值。

我就是这样初始化窗口的:

代码语言:javascript
运行
复制
glutInit(&argc, argv);
glutInitWindowSize(800,600);

glClear(GL_COLOR_BUFFER_BIT);    

glMatrixMode (GL_PROJECTION); 
glLoadIdentity();
glOrtho(0, 800, 600, 0, 0, 1);
glMatrixMode(GL_MODELVIEW); 
glTranslatef(0.375, 0.375, 0);

glClearColor(0, 0, 0, 1.0); 

通过这个,我得到了所有的0:

编辑:

代码语言:javascript
运行
复制
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);        
    glVertex2i(x-20, y-20);
    glVertex2i(x-20, y+20);
    glVertex2i(x+20, y+20);
    glVertex2i(x+20, y-20);
glEnd();
unsigned char pixel[4]; 
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);

在我glClear之后,我确实呈现了一些形状,在(x,y),然后我使用glReadPixels在(x,y)处得到颜色,但它返回0。我试图glReadPixels整个屏幕,它也返回0。

编辑2:

因此,为了更清楚地了解我的问题,下面是代码:我只是不知道问题的来源在哪里,所以我把所有的代码粘贴在这里。这是乔纳森·S·哈布尔(JonathanS.Habour)著的“游戏编程一体化”一书中的坦克程序。这本书使用快板库,我试着把它转换成openGL。在更新子弹程序中的“寻找一个命中”,我打印出敌人坦克的坐标和那个像素处的颜色,但我得到的只是0。

代码语言:javascript
运行
复制
#include <GL/glut.h>
#include <stdlib.h>
#include <iostream.h>
#include <windows.h>

//define tank structure
struct tagTank
{
    int x,y;
    int dir,speed;
} tanks[2];

struct tagBullet
{
    int x,y;
    int alive;
    int xspd,yspd;
} bullets[2];

void setuptanks()
{   
    tanks[0].x = 30;
    tanks[0].y = 40;
    tanks[0].dir = 1;
    tanks[0].speed = 5;

    tanks[1].x = 800 - 30;
    tanks[1].y = 600 - 30;
    tanks[1].dir = 3;
    tanks[1].speed = 5;
}

void drawtank(int num)
{
    int x = tanks[num].x;
    int y = tanks[num].y;
    int dir = tanks[num].dir;

    //draw tank body
    glColor3f(1.0, 0.0, 0.0);
    if (num) glColor3f(0.0, 0.0, 1.0);
    glBegin(GL_QUADS);        
        glVertex2i(x-20, y-20);
        glVertex2i(x-20, y+20);
        glVertex2i(x+20, y+20);
        glVertex2i(x+20, y-20);
    glEnd();

    glColor3f(0.5, 0.0, 0.0);
    if (num) glColor3f(0.0, 0.0, 0.5);
    glBegin(GL_QUADS);        
        glVertex2i(x-10, y-10);
        glVertex2i(x-10, y+10);
        glVertex2i(x+10, y+10);
        glVertex2i(x+10, y-10);
    glEnd();

    //draw the turret based on direction
    glColor3f(1.0, 1.0, 1.0);
    switch (dir)
    {
        case 0:
            glBegin(GL_QUADS);        
                glVertex2i(x-2, y-30);
                glVertex2i(x-2, y);
                glVertex2i(x+2, y);
                glVertex2i(x+2, y-30);
            glEnd();
            break;
        case 1:
            glBegin(GL_QUADS);        
                glVertex2i(x, y-2);
                glVertex2i(x, y+2);
                glVertex2i(x+30, y+2);
                glVertex2i(x+30, y-2);
            glEnd();
            break;
        case 2:
            glBegin(GL_QUADS);        
                glVertex2i(x-2, y);
                glVertex2i(x-2, y+30);
                glVertex2i(x+2, y+30);
                glVertex2i(x+2, y);
            glEnd();
            break;
        case 3:
            glBegin(GL_QUADS);        
                glVertex2i(x-30, y-2);
                glVertex2i(x-30, y+2);
                glVertex2i(x, y+2);
                glVertex2i(x, y-2);
            glEnd();
            break;
    }
}

void erasetank(int num)
{
    //calculate box to encompass the tank
    int left = tanks[num].x - 30;
    int top = tanks[num].y - 30;
    int right = tanks[num].x + 30;
    int bottom = tanks[num].y + 30;

    //erase the tank
    glColor3f(0.0, 0.0, 0.0);
    glBegin(GL_QUADS);        
        glVertex2i(left, top);
        glVertex2i(left, bottom);
        glVertex2i(right, bottom);
        glVertex2i(right, top);
    glEnd();
}

void movetank(int num)
{
    int dir = tanks[num].dir;
    int speed = tanks[num].speed;
    //update tank position based on direction
    switch(dir)
    {
    case 0:
        tanks[num].y -= speed;
        break;
    case 1:
        tanks[num].x += speed;
        break;
    case 2:
        tanks[num].y += speed;
        break;
    case 3:
        tanks[num].x -= speed;
        break;
    }

    //keep tank inside the screen
    if (tanks[num].x > 800-30)
    {
        tanks[num].x = 800-30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].x < 30)
    {
        tanks[num].x = 30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].y > 600-30)
    {
        tanks[num].y = 600-30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].y < 30)
    {
        tanks[num].y = 30;
        tanks[num].speed = 0;
    }

    else tanks[num].speed = 5;
}

void explode(int num, int x, int y)
{
    int n;
    //retrieve location of enemy tank
    int tx = tanks[!num].x;
    int ty = tanks[!num].y;

    //is bullet inside the boundary of the enemy tank?
    if (x > tx-30 && x < tx+30 && y > ty-30 && y < ty+30)
        setuptanks();

    //draw some random circles for the "explosion"
    for (n = 0; n < 10; n++)
    {
        glColor3f((rand() % 101)/100.0, (rand() % 101)/100.0, (rand() % 101)/100.0);
        glBegin(GL_QUADS);        
            glVertex2i(x-16, y-16);
            glVertex2i(x-16, y+16);
            glVertex2i(x+16, y+16);
            glVertex2i(x+16, y-16);
        glEnd();

        //Sleep(10);
    }

    //clear the area of debris
    glColor3f(0.0, 0.0, 0.0);
    glBegin(GL_QUADS);        
        glVertex2i(x-16, y-16);
        glVertex2i(x-16, y+16);
        glVertex2i(x+16, y+16);
        glVertex2i(x+16, y-16);
    glEnd();
}

void updatebullet(int num)
{
    int x = bullets[num].x;
    int y = bullets[num].y;
    if (bullets[num].alive)
    {
        //erase bullet
        glColor3f(0.0, 0.0, 0.0);
        glBegin(GL_QUADS);        
            glVertex2i(x-2, y-2);
            glVertex2i(x-2, y+2);
            glVertex2i(x+2, y+2);
            glVertex2i(x+2, y-2);
        glEnd();

        //move bullet
        bullets[num].x += bullets[num].xspd;
        bullets[num].y += bullets[num].yspd;
        x = bullets[num].x;
        y = bullets[num].y;

        //stay within the screen
        if (x < 5 || x > 800 || y < 20 || y > 600)
        {
            bullets[num].alive = 0;
            return;
        }

        //look for a hit
        unsigned char pixel[4]; 
        glReadPixels(tanks[!num].x, tanks[!num].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
        cout << tanks[!num].x << ", " << tanks[!num].y << " | " << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << endl;
        if ((int)pixel[0] || (int)pixel[1] || (int)pixel[2])
        {           
            bullets[num].alive = 0;
            explode(num, x, y);
            return;
        }       

        //draw bullet
        x = bullets[num].x;
        y = bullets[num].y;
        glColor3f(1.0, 1.0, 1.0);
        glBegin(GL_QUADS);        
            glVertex2i(x-2, y-2);
            glVertex2i(x-2, y+2);
            glVertex2i(x+2, y+2);
            glVertex2i(x+2, y-2);
        glEnd();
    }
}

void fireweapon(int num)
{
    int x = tanks[num].x;
    int y = tanks[num].y;

    //ready to fire again?
    if (!bullets[num].alive)
    {
        bullets[num].alive = 1;

        //fire bullet in direction tank is facing
        switch (tanks[num].dir)
        {
            //north
            case 0:
                bullets[num].x = x;
                bullets[num].y = y-30;
                bullets[num].xspd = 0;
                bullets[num].yspd = -20;
                break;

            //east
            case 1:
                bullets[num].x = x+30;
                bullets[num].y = y;
                bullets[num].xspd = 20;
                bullets[num].yspd = 0;
                break;

            //south
            case 2:
                bullets[num].x = x;
                bullets[num].y = y+30;
                bullets[num].xspd = 0;
                bullets[num].yspd = 20;
                break;

            //west
            case 3:
                bullets[num].x = x-30;
                bullets[num].y = y;
                bullets[num].xspd = -20;
                bullets[num].yspd = 0;
                break;
        }
    }
}

void up(int num)
{
    tanks[num].dir = 0; 
}

void down(int num)
{
    tanks[num].dir = 2; 
}

void left(int num)
{
    tanks[num].dir = 3; 
}

void right(int num)
{
    tanks[num].dir = 1; 
}

static void display(void)
{       
    erasetank(0);           
    erasetank(1);   

    movetank(0);        
    movetank(1);    

    drawtank(0);
    drawtank(1);    

    updatebullet(0);
    updatebullet(1);

    glFlush();

    Sleep(50);
}


static void key(unsigned char key, int x, int y)
{
    switch (key)
    {
        case 27 :
            exit(0);
            break;
        case 'a':
            left(1);
            break;
        case 'd':
            right(1);
            break;
        case 'w':
            up(1);
            break;
        case 's':
            down(1);
            break;
        case 32:        
            fireweapon(1);
            break;
        case 13:
            fireweapon(0);
            break;
    }
    glutPostRedisplay();
}

static void specialkey(int key, int x, int y)
{
    switch (key)
    {
        case GLUT_KEY_LEFT:
            left(0);
            break;
        case GLUT_KEY_RIGHT:
            right(0);
            break;
        case GLUT_KEY_UP:
            up(0);
            break;
        case GLUT_KEY_DOWN:
            down(0);
            break;
    }
    glutPostRedisplay();
}

static void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(800,600);
    glutInitWindowPosition(10,10);  

    glutCreateWindow("Tanks");

    glClear(GL_COLOR_BUFFER_BIT);    

    glutDisplayFunc(display);
    glutKeyboardFunc(key);
    glutSpecialFunc(specialkey);
    glutIdleFunc(idle);

    glMatrixMode (GL_PROJECTION); 
    glLoadIdentity();
    glOrtho(0, 800, 600, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW); 
    glTranslatef(0.375, 0.375, 0);

    glClearColor(0, 0, 0, 1.0); 

    setuptanks();

    glutMainLoop();

    return EXIT_SUCCESS;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-25 18:26:43

正如罗格·罗兰指出的那样,你读错了屏幕的部分。在将y坐标传递给glReadPixels()之前,您需要翻转它。

其他事情:

  1. 您不需要erasetank()erasebullet(),只需清除屏幕上的每一帧
  2. 在显示回调中放置glClear()和矩阵是个好主意
  3. 显式的glutInitDisplayMode()是个好主意
  4. 没有真正的理由不使用GLUT_DOUBLE
  5. 使用glutTimerFunc()而不是sleep()

合在一起:

代码语言:javascript
运行
复制
#include <GL/glut.h>

#include <iostream>
using namespace std;

//define tank structure
struct tagTank
{
    int x,y;
    int dir,speed;
} tanks[2];

struct tagBullet
{
    int x,y;
    int alive;
    int xspd,yspd;
} bullets[2];

void setuptanks()
{   
    tanks[0].x = 30;
    tanks[0].y = 40;
    tanks[0].dir = 1;
    tanks[0].speed = 5;

    tanks[1].x = 800 - 30;
    tanks[1].y = 600 - 30;
    tanks[1].dir = 3;
    tanks[1].speed = 5;
}

void drawtank(int num)
{
    int x = tanks[num].x;
    int y = tanks[num].y;
    int dir = tanks[num].dir;

    //draw tank body
    glColor3f(1.0, 0.0, 0.0);
    if (num) glColor3f(0.0, 0.0, 1.0);
    glBegin(GL_QUADS);        
    glVertex2i(x-20, y-20);
    glVertex2i(x-20, y+20);
    glVertex2i(x+20, y+20);
    glVertex2i(x+20, y-20);
    glEnd();

    glColor3f(0.5, 0.0, 0.0);
    if (num) glColor3f(0.0, 0.0, 0.5);
    glBegin(GL_QUADS);        
    glVertex2i(x-10, y-10);
    glVertex2i(x-10, y+10);
    glVertex2i(x+10, y+10);
    glVertex2i(x+10, y-10);
    glEnd();

    //draw the turret based on direction
    glColor3f(1.0, 1.0, 1.0);
    switch (dir)
    {
    case 0:
        glBegin(GL_QUADS);        
        glVertex2i(x-2, y-30);
        glVertex2i(x-2, y);
        glVertex2i(x+2, y);
        glVertex2i(x+2, y-30);
        glEnd();
        break;
    case 1:
        glBegin(GL_QUADS);        
        glVertex2i(x, y-2);
        glVertex2i(x, y+2);
        glVertex2i(x+30, y+2);
        glVertex2i(x+30, y-2);
        glEnd();
        break;
    case 2:
        glBegin(GL_QUADS);        
        glVertex2i(x-2, y);
        glVertex2i(x-2, y+30);
        glVertex2i(x+2, y+30);
        glVertex2i(x+2, y);
        glEnd();
        break;
    case 3:
        glBegin(GL_QUADS);        
        glVertex2i(x-30, y-2);
        glVertex2i(x-30, y+2);
        glVertex2i(x, y+2);
        glVertex2i(x, y-2);
        glEnd();
        break;
    }
}

void movetank(int num)
{
    int dir = tanks[num].dir;
    int speed = tanks[num].speed;
    //update tank position based on direction
    switch(dir)
    {
    case 0:
        tanks[num].y -= speed;
        break;
    case 1:
        tanks[num].x += speed;
        break;
    case 2:
        tanks[num].y += speed;
        break;
    case 3:
        tanks[num].x -= speed;
        break;
    }

    //keep tank inside the screen
    if (tanks[num].x > 800-30)
    {
        tanks[num].x = 800-30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].x < 30)
    {
        tanks[num].x = 30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].y > 600-30)
    {
        tanks[num].y = 600-30;
        tanks[num].speed = 0;
    }

    else if (tanks[num].y < 30)
    {
        tanks[num].y = 30;
        tanks[num].speed = 0;
    }

    else tanks[num].speed = 5;
}

void explode(int num, int x, int y)
{
    int n;
    //retrieve location of enemy tank
    int tx = tanks[!num].x;
    int ty = tanks[!num].y;

    //is bullet inside the boundary of the enemy tank?
    if (x > tx-30 && x < tx+30 && y > ty-30 && y < ty+30)
        setuptanks();

    //draw some random circles for the "explosion"
    for (n = 0; n < 10; n++)
    {
        glColor3f((rand() % 101)/100.0, (rand() % 101)/100.0, (rand() % 101)/100.0);
        glBegin(GL_QUADS);        
        glVertex2i(x-16, y-16);
        glVertex2i(x-16, y+16);
        glVertex2i(x+16, y+16);
        glVertex2i(x+16, y-16);
        glEnd();
    }
}

void updatebullet(int num)
{
    if (bullets[num].alive)
    {
        //move bullet
        bullets[num].x += bullets[num].xspd;
        bullets[num].y += bullets[num].yspd;
        int x = bullets[num].x;
        int y = bullets[num].y;

        //stay within the screen
        if (x < 5 || x > 800 || y < 20 || y > 600)
        {
            bullets[num].alive = 0;
            return;
        }

        //look for a hit
        unsigned char pixel[4]; 
        int h = glutGet( GLUT_WINDOW_HEIGHT );
        glReadPixels(x, h - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
        cout << x << ", " << y << " | " << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << endl;
        if ((int)pixel[0] || (int)pixel[1] || (int)pixel[2])
        {           
            bullets[num].alive = 0;
            explode(num, x, y);
            return;
        }       

        //draw bullet
        glColor3f(1.0, 1.0, 1.0);
        glBegin(GL_QUADS);        
        glVertex2i(x-2, y-2);
        glVertex2i(x-2, y+2);
        glVertex2i(x+2, y+2);
        glVertex2i(x+2, y-2);
        glEnd();
    }
}

void fireweapon(int num)
{
    int x = tanks[num].x;
    int y = tanks[num].y;

    //ready to fire again?
    if (!bullets[num].alive)
    {
        bullets[num].alive = 1;

        //fire bullet in direction tank is facing
        switch (tanks[num].dir)
        {
            //north
        case 0:
            bullets[num].x = x;
            bullets[num].y = y-30;
            bullets[num].xspd = 0;
            bullets[num].yspd = -20;
            break;

            //east
        case 1:
            bullets[num].x = x+30;
            bullets[num].y = y;
            bullets[num].xspd = 20;
            bullets[num].yspd = 0;
            break;

            //south
        case 2:
            bullets[num].x = x;
            bullets[num].y = y+30;
            bullets[num].xspd = 0;
            bullets[num].yspd = 20;
            break;

            //west
        case 3:
            bullets[num].x = x-30;
            bullets[num].y = y;
            bullets[num].xspd = -20;
            bullets[num].yspd = 0;
            break;
        }
    }
}

void up(int num)
{
    tanks[num].dir = 0; 
}

void down(int num)
{
    tanks[num].dir = 2; 
}

void left(int num)
{
    tanks[num].dir = 3; 
}

void right(int num)
{
    tanks[num].dir = 1; 
}

static void display(void)
{       
    glClearColor(0, 0, 0, 1.0); 
    glClear(GL_COLOR_BUFFER_BIT);    

    glMatrixMode (GL_PROJECTION); 
    glLoadIdentity();
    int w = glutGet( GLUT_WINDOW_WIDTH );
    int h = glutGet( GLUT_WINDOW_HEIGHT );
    glOrtho( 0, w, h, 0, -1, 1 );

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity();
    glTranslatef(0.375, 0.375, 0);

    movetank(0);        
    movetank(1);    

    drawtank(0);
    drawtank(1);    

    glFlush();
    updatebullet(0);
    updatebullet(1);

    glutSwapBuffers();
}

static void key(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27 :   exit(0);        break;
    case 'a':   left(1);        break;
    case 'd':   right(1);       break;
    case 'w':   up(1);          break;
    case 's':   down(1);        break;
    case 32:    fireweapon(1);  break;
    case 13:    fireweapon(0);  break;
    }
}

static void specialkey(int key, int x, int y)
{
    switch (key)
    {
    case GLUT_KEY_LEFT:     left(0);    break;
    case GLUT_KEY_RIGHT:    right(0);   break;
    case GLUT_KEY_UP:       up(0);      break;
    case GLUT_KEY_DOWN:     down(0);    break;
    }
}

void timer( int value )
{
    glutTimerFunc( 50, timer, 0 );
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    glutInitWindowSize(800,600);
    glutInit(&argc, argv);
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );

    glutCreateWindow("Tanks");

    glutDisplayFunc(display);
    glutKeyboardFunc(key);
    glutSpecialFunc(specialkey);
    glutTimerFunc( 0, timer, 0 );

    setuptanks();

    glutMainLoop();

    return EXIT_SUCCESS;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23286407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档