如何在现代OpenGL中基于2D数组绘制图像,glVertex2f参数怎么用?
问题解答
1. glVertex2f参数逻辑
默认情况下,OpenGL使用标准化设备坐标(NDC),传入glVertex2f(x,y)的x、y取值范围都在[-1, 1]之间:
- x=-1对应窗口左边缘,x=1对应窗口右边缘
- y=-1对应窗口下边缘,y=1对应窗口上边缘
超出这个范围的坐标会被直接裁剪,不会渲染到窗口上,这也是你原来代码看不到任何红色点的核心原因:你传入的0~32的坐标远大于1,几乎所有点都在视口外。
2. 你的代码存在的前置错误
首先要修正两个逻辑顺序问题,否则后续调整也不会生效:
glutInitWindowSize必须放在glutCreateWindow之前调用,否则窗口大小设置不会生效- 所有绘制相关的代码(
glClear、绘制点、glFlush等)必须放在你注册的displaySpectrogram回调函数里,glutMainLoop是事件死循环,写在它之后的代码永远不会被执行
3. 两种实现全屏红色的方案
方案1:调整坐标适配默认NDC(无需修改投影矩阵)
把循环里的i、j坐标转换到[-1, 1]区间即可,修改循环部分代码:
glBegin(GL_POINTS); glColor3f(1.0f, 0.0f, 0.0f); // Red for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { // 把0~31的像素坐标转换为[-1,1]的NDC坐标 float x = (i / 31.0f) * 2.0f - 1.0f; float y = (j / 31.0f) * 2.0f - 1.0f; glVertex2f(x, y); } } glEnd();
如果想要更方便的直接用像素坐标绘制,可以修改正交投影矩阵,在初始化阶段添加以下代码:
glMatrixMode(GL_PROJECTION); glLoadIdentity(); // 设置正交投影:左下角(0,0),右上角(32,32),和窗口像素一一对应 glOrtho(0, 32, 0, 32, -1, 1); glMatrixMode(GL_MODELVIEW);
添加后你原来的glVertex2f(i,j)写法可以直接使用,无需坐标转换。
方案2:纹理实现(效率更高,适合后续动态修改像素内容)
相比逐点绘制,纹理方案更适合像素级渲染场景,步骤如下:
- 初始化阶段创建32x32的纹理对象,填充全红的像素数据
- 绘制阶段渲染一个覆盖整个NDC范围的四边形,绑定纹理后映射到四边形上
示例代码片段:
// 初始化阶段创建纹理 GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); // 构造32x32全红的像素数据(RGBA格式) unsigned char pixels[32*32*4]; for(int i=0; i<32*32; i++){ pixels[i*4 + 0] = 255; // R pixels[i*4 + 1] = 0; // G pixels[i*4 + 2] = 0; // B pixels[i*4 + 3] = 255; // A } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // 绘制阶段 glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glBegin(GL_QUADS); // 绘制覆盖整个窗口的四边形,对应纹理四个角 glTexCoord2f(0,0); glVertex2f(-1,-1); glTexCoord2f(1,0); glVertex2f(1,-1); glTexCoord2f(1,1); glVertex2f(1,1); glTexCoord2f(0,1); glVertex2f(-1,1); glEnd(); glDisable(GL_TEXTURE_2D);
后续如果要修改窗口像素内容,只需要更新pixels数组后调用glTexSubImage2D更新纹理即可,比逐点绘制性能高很多。
内容的提问来源于stack exchange,提问作者yarin Cohen
相关产品推荐
相关产品推荐

