使用GLUT和C闪烁2D纹理

时间:2017-05-30 06:15:42

标签: c opengl textures glut chip-8

我正在尝试使用普通的C制作chip8仿真器。我设置了大部分操作码,所以我只需要在显示器上工作。我决定使用GLUT进行显示,因为它看起来很快。主要思想是将chip8 sprite显示在2D纹理上。我得到它显示一些数字虽然一些操作码执行,但它闪烁。我正在使用双缓冲,因为从我读到它是最好的方法来确保一些东西准备好显示但我仍然在闪烁。关于什么可以导致它的任何想法?

以下是显示的OpenGL和GLUT的所有代码。

int main(int argc,  char * argv[]) {

//    if(argc < 2){
//        printf("Usage: %s <bin file>\n", argv[0]);
//        exit(0);
//    }

    //initialize chip 8
    chip8_Init();
    //load file if exists
    chip8_load("test6.bin");

    //setup graphics
    glutInit(&argc, argv);
    glutInitWindowSize(display_width, display_height);
    glutInitWindowPosition(320, 320);
    glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
    glutCreateWindow("Chip8 GL");
    setupTexture();
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    glutIdleFunc(renderScene);
    glutKeyboardFunc(chip8_keypad);
    glutKeyboardUpFunc(chip8_keypadUp);

    glutMainLoop();
    return 0;
}


void setupTexture(){ 
    glClearColor (0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);


    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    //set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
                GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                GL_NEAREST);
    //update texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
             SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
             screenData);
}

void updateTexture(){ //display()
    //update pixels
    for (int i = 0; i < SCREEN_HEIGHT; i++) {
        for (int j = 0; j < SCREEN_WIDTH; j++) {
            if(chip8.gfx[(i * SCREEN_WIDTH)+j] == 0){
                screenData[i][j][0] = 0;
                screenData[i][j][1] = 0;
                screenData[i][j][2] = 0;
            }
            else{
                screenData[i][j][0] = 255;
                screenData[i][j][1] = 255;
                screenData[i][j][2] = 255;
            }  
        }
    }
    //update texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
             SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
             screenData);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glBindTexture(GL_TEXTURE_2D, texName);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex2d(0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex2d(display_width, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex2d(display_width, display_height);
    glTexCoord2f(0.0, 1.0); glVertex2d(0.0, display_height);

    glEnd();
    glutSwapBuffers();
}

void renderScene(){
    chip8_emulateCycle();
    if(drawFlag == 1){
    updateTexture();
    drawFlag = 0;
    }  
}

void changeSize(int w, int h){
    glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, w, h, 0);
    glMatrixMode(GL_MODELVIEW);
    glViewport(0, 0, w, h);

    // Resize quad
    display_width = w;
    display_height = h;
}

编辑:我可能已经弄清楚了。在绘制操作码中,它使用XOR。因此,当第一次使用绘图命令显示精灵并再次调用它时,它会消失,依此类推。

1 个答案:

答案 0 :(得分:0)

我的opengl非常尘土飞扬,但我在你的代码中看到了一些要点:

您应该在初始化之前启用GL_TEXTURE_2D

void setupTexture()
{ 
    glClearColor (0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


    /* enable texturing */
    glEnable(GL_TEXTURE_2D);
    /* create texture */
    glGenTextures(1, &texName);
    /* select texture */
    glBindTexture(GL_TEXTURE_2D, texName);

    /* select behavior */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    /* ... */

}

您应该在修改之前选择纹理

void updateTexture(){ 
    /* update pixels */
    /* ... */

    /*select texture */
    glBindTexture(GL_TEXTURE_2D, texName);

    /*update texture */
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
             SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
             screenData);

    /* clear screen */    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* draw texture */
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex2d(0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex2d(display_width, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex2d(display_width, display_height);
    glTexCoord2f(0.0, 1.0); glVertex2d(0.0, display_height);
    glEnd();

    glutSwapBuffers();
}

此外,您可以使用glGetError()

来测试被调用函数的结果
void check_for_error(void)
{
    GLenum err = glGetError();
    if (GL_NO_ERROR != err)
    {
        fprintf("Error %d\n", err);
        exit(EXIT_FAILURE);
    }
}

说,我不知道chip8.gfx[]内的数据,可能不是你想象的那样。