我使用OpenGL和GLUT编写了一个小示例程序,使用glDrawPixels
函数显示一个2×2的四个彩色方块网格。不幸的是,我发现了:
以下C ++代码段显示示例图像。我在这里做错了什么,我应该改变什么才能查看预期的颜色并旋转像素图?
struct RGB
{
unsigned char r, g, b;
};
class Pixmap
{
public:
RGB color[4];
Pixmap()
{
color[0].r = 255;
color[0].g = 0;
color[0].b = 0;
color[1].r = 0;
color[1].g = 255;
color[1].b = 0;
color[2].r = 0;
color[2].g = 0;
color[2].b = 255;
color[3].r = 255;
color[3].g = 255;
color[3].b = 255;
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels( 2, 2, GL_RGB, GL_UNSIGNED_BYTE, color );
glFlush();
}
};
// Create an instance of class Pixmap
Pixmap myPixmap;
void myRender()
{
myPixmap.render();
}
int main( int argc, char *argv[] )
{
int screenWidth, screenHeight;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
screenWidth = glutGet(GLUT_SCREEN_WIDTH);
screenHeight = glutGet(GLUT_SCREEN_HEIGHT);
int windowWidth = screenHeight / 2;
int windowHeight = screenHeight / 2;
glutInitWindowSize(windowWidth, windowHeight);
int posX = (screenWidth - windowWidth) / 2;
int posY = (screenHeight - windowHeight) / 4;
glutInitWindowPosition(posX, posY);
glutCreateWindow("Picture");
GLfloat scaleX = 1.0f * windowWidth / 2;
GLfloat scaleY = 1.0f * windowHeight / 2;
glMatrixMode( GL_PROJECTION );
// If glPixelZoom(-scaleX, scaleY)
// then no image is displayed
glPixelZoom(scaleX, scaleY);
glClearColor(1.0, 1.0, 1.0, 0.0);
glColor3f(0.0f, 0.0f, 0.0f);
glutDisplayFunc( myRender );
glutMainLoop();
}
答案 0 :(得分:2)
glMatrixMode( GL_PROJECTION );
以上一行是造成问题的一方。将其更改为“glMatrixMode(GL_MODELVIEW);”因为你并没有真正使用投影矩阵。
投影矩阵用于设置投影参数,如透视/正交模式,FOV等。这通常需要在创建窗口时以及窗口/视口大小发生变化时进行。模型视图矩阵用于平移,旋转和缩放。
由于OpenGL的工作方式,跟踪“状态”非常重要。一般工作流程是设置投影模式,根据需要更改参数并立即更改回模型视图模式,如:
glMatrixMode(GL_PROJECTION);
//...
//do various projection stuff
//...
glMatrixMode(GL_MODELVIEW);
这适用于OpenGL中的许多东西,不仅仅是矩阵状态,还有灯光,混合等其他东西。在执行另一组操作并再次切换回默认状态之前执行一组操作之后,返回到“默认”状态非常常见。
答案 1 :(得分:2)
经过一些实验,我认为我找到了一个似乎适合我自己目的的解决方案。首先,鉴于上面我的问题中的示例代码,似乎pixmap需要作为带有alpha通道的数组glDrawPixels
传递给GLubyte color[2][2][4]
函数。正如Vaayu所提到的,还有可能需要正确设置glMatrixMode
函数。第二,据pg。在OpenGL编程指南(第7版)的356中,如果使用负参数调用glPixelZoom
函数,则需要设置当前的栅格位置。基本上我无法看到图像的原因是由于光栅是在不在窗口可视区域内的位置绘制的。以下代码演示了如何为四种不同的情况设置旋转和当前栅格位置:
// case 0
glWindowPos2i(0, 0);
glPixelZoom(scaleX, scaleY);
// case 1
glWindowPos2i(windowHeight, 0);
glPixelZoom(-scaleX, scaleY);
// case 2
glWindowPos2i(0, windowHeight);
glPixelZoom(scaleX, -scaleY);
// case 3
glWindowPos2i(windowWidth, windowHeight);
glPixelZoom(-scaleX, -scaleY);
因此,我原始问题中给出的示例可以更新:
class Pixmap { public: GLubyte color[2][2][4]; Pixmap() { // red color[0][0][0] = 255; color[0][0][1] = 0; color[0][0][2] = 0; color[0][0][3] = 0; // green color[0][1][0] = 0; color[0][1][1] = 255; color[0][1][2] = 0; color[0][1][3] = 0; // blue color[1][0][0] = 0; color[1][0][1] = 0; color[1][0][2] = 255; color[1][0][3] = 0; // white color[1][1][0] = 255; color[1][1][1] = 255; color[1][1][2] = 255; color[1][1][3] = 0; } void render() { glClear(GL_COLOR_BUFFER_BIT); glDrawPixels( 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, color ); glFlush(); } }; // Create an instance of class Pixmap Pixmap myPixmap; void myRender() { myPixmap.render(); } int main( int argc, char *argv[] ) { int screenWidth, screenHeight; int rotation; // Choose rotation case {0, 1, 2, 3} rotation = 3; glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); screenWidth = glutGet(GLUT_SCREEN_WIDTH); screenHeight = glutGet(GLUT_SCREEN_HEIGHT); int windowWidth = screenHeight / 2; int windowHeight = screenHeight / 2; glutInitWindowSize(windowWidth, windowHeight); int posX = (screenWidth - windowWidth) / 2; int posY = (screenHeight - windowHeight) / 4; glutInitWindowPosition(posX, posY); glutCreateWindow("Picture"); GLfloat scaleX = 1.0f * windowWidth / 2; GLfloat scaleY = 1.0f * windowHeight / 2; glMatrixMode(GL_MODELVIEW); // Select rotation switch(rotation) { case 0: glWindowPos2i(0, 0); glPixelZoom(scaleX, scaleY); break; case 1: glWindowPos2i(windowHeight, 0); glPixelZoom(-scaleX, scaleY); break; case 2: glWindowPos2i(0, windowHeight); glPixelZoom(scaleX, -scaleY); break; case 3: glWindowPos2i(windowWidth, windowHeight); glPixelZoom(-scaleX, -scaleY); break; default: break; } glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); glutDisplayFunc( myRender ); glutMainLoop(); }