OpenGL 编程/基础/二维对象
glRectf() 虽然有用,但它不允许我们对矩形的单个顶点进行太多控制。为了给我们更多控制,并能够绘制更复杂的形状,我们必须使用不同的函数。
要开始一个由顶点定义的形状,我们使用 glBegin() 函数。glBegin() 接受一个参数:你想创建的形状类型。以下是一些可能的参数
- GL_TRIANGLES
- GL_QUADS
- GL_POLYGON
四边形是任何具有 4 个顶点的形状:矩形、正方形、梯形等。顶点的位置将定义它是哪种类型的形状。
虽然多边形听起来很适合绘制复杂形状,但请向下滚动查看有关多边形限制的警告:多边形有很多限制,在某些情况下你可能最好使用一系列连接的四边形或三角形。
在调用 glBegin() 之后,我们实际上使用 glVertex2f(float xPosition, float yPosition) 来定义顶点。
glBegin(GL_XYZ); glVertex2f(-1.0f,-0.5f); glVertex2f(1.0f,-0.25f); ...
重要提示:你定义顶点的顺序很重要!一般来说,如果你按逆时针顺序定义顶点,则正面将朝向你,这通常是你想要的。这种区别在我们进入 3D 时变得非常重要,所以请确保按逆时针顺序定义你的顶点,除非你知道自己在做什么!如果你想按顺时针顺序定义顶点,请确保在你的 setup() 函数中包含此函数
glFrontFace(GL_CW);
它将允许你仅按顺时针顺序绘制。
要结束一个顶点定义的形状,只需调用 glEnd(),它不接受任何参数。
此显示函数将在我们的屏幕中央绘制一个黑色的梯形。
void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0f, 0.0f, 0.0f); // sets color to black. glBegin(GL_QUADS); glVertex2f(-0.25f, 0.25f); // vertex 1 glVertex2f(-0.5f, -0.25f); // vertex 2 glVertex2f(0.5f, -0.25f); // vertex 3 glVertex2f(0.25f, 0.25f); // vertex 4 glEnd(); glutSwapBuffers(); }
关于样式的说明:对 glVertex() 的调用有时会缩进以将其与 glBegin() 和 glEnd() 分开。前面示例中的缩进不是错误。
如果我们要绘制一系列形状,其中每个形状都与另一个形状共享一条边或顶点,那么没有理由重复对 glVertex2f() 的如此多次调用。相反,我们使用一个特殊参数调用 glBegin() 以指示我们要绘制这些对象的“条带”。
当我们使用这两个参数中的任何一个调用 glBegin() 时,我们可以绘制一系列三角形或四边形,其中每个三角形或四边形都与另一个三角形或四边形共享一条边。这一个很好的用途是绘制复杂的形状,例如一个 2D 圣诞树。
三角形条带由用于三角形的 3 个初始顶点定义,然后每个额外的三角形由一个顶点定义。任何给定的三角形都是由它的一个顶点和它前面的两个顶点形成的。
四边形条带由用于四边形的 4 个初始顶点定义,然后每个额外的四边形由两个顶点定义。任何给定的四边形都是由它的两个顶点和它前面的两个顶点形成的。
以下代码使用三角形条带定义一个房子的形状,它有一个倾斜的屋顶。
void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0f, 0.0f, 0.0f); // sets color to black. glBegin(GL_TRIANGLE_STRIP); // draw in triangle strips glVertex2f(0.0f, 0.75f); // top of the roof glVertex2f(-0.5f, 0.25f); // left corner of the roof glVertex2f(0.5f, 0.25f); // right corner of the roof glVertex2f(-0.5f, -0.5f); // bottom left corner of the house glVertex2f(0.5f, -0.5f); //bottom right corner of the house glEnd(); glutSwapBuffers(); }
在这里,定义了三个三角形,一个用于屋顶,一个用于房子的左上角,一个用于房子的右下角。
如果我们要绘制一堆三角形,其中每个三角形都共享一个预定义的顶点(例如,在原点),我们可以使用三角形扇形。三角形扇形通过奇数个顶点定义一个形状。第一个顶点定义一个中心点,每个三角形都将该点作为顶点。然后,每两个顶点都与初始顶点一起使用来定义一个三角形。
#include <GL/glut.h>
void init(){
glClearColor(0,0,0,0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0,100,0,200);
}
void Display(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1,0,0);
glVertex2f(0,0.5);
glVertex2f(-0.4,0);
glVertex2f(0.4,0);
glColor3f(0,1,0);
glVertex2f(0,-0.5);
glEnd();
glFlush();
}
int main(int argc, char **argv){
glutInit(& argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200,200);
glutCreateWindow("line");
glutDisplayFunc(Display);
init();
glutMainLoop();
return 0;
}
GLUT 有一些内置对象,只需调用一个简单的函数就可以使用它们。这些对象中最有趣和最有用的对象是
函数 | 二维形状 | 三维形状 | 注释 |
glutSolidSphere(float radius, int slices, int stacks) | 圆形 | 球体 | 为 slices 和 stacks 参数选择一个 20-100 的整数;数字越大,球体/圆形越准确。 |
glutSolidCube(double size) | 正方形 | 立方体 | |
glutSolidCone(double base, double height, int slices, int stacks) | 三角形 | 圆锥体 | slices 参数越大,圆锥体看起来越平滑。 |
glutSolidTorus(double innerRadius, double outerRadius, int nSides, int rings) | 环面 | ||
glutSolidTeapot(float radius) | 茶壶 | 茶壶 | 是的,一个茶壶。请参阅维基百科文章“Utah 茶壶”,了解为什么选择了一个茶壶。 |