Мерцающая 2D текстура с использованием GLUT и C

Я пытаюсь сделать эмулятор chip8 с использованием простого C. Я установил большинство опкодов, поэтому мне просто нужно работать на дисплее. Я решил использовать GLUT для дисплея, так как появилась быстрая настройка. Основная идея - отобразить спрайты chip8 на 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 ответ

Мой 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[], может быть, они не так, как вы ожидаете.

Другие вопросы по тегам