使用 GLUT 和 C 闪烁 2D 纹理
Posted
技术标签:
【中文标题】使用 GLUT 和 C 闪烁 2D 纹理【英文标题】:Flickering 2D Texture using GLUT and C 【发布时间】:2017-05-30 06:15:42 【问题描述】:我正在尝试使用纯 C 语言制作一个chip8 模拟器。我设置了大部分操作码,所以我只需要在显示器上工作。我决定使用 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。所以当第一次绘制命令时,精灵被显示,当再次调用它时,它就会消失,依此类推。
【问题讨论】:
在对纹理进行操作之前不应该调用glBindTexture(GL_TEXTURE_2D, texName);
吗?禁用双缓冲会改变行为吗?
【参考方案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[]
里面的数据,可能和你想象的不一样。
【讨论】:
以上是关于使用 GLUT 和 C 闪烁 2D 纹理的主要内容,如果未能解决你的问题,请参考以下文章