OpenGL学习:第二课

OpenGL学习:第二课

OpenGL中,可以对基本图元进行颜色的设置。

先说一下,OpenGL中的基本图元。基本图元是构成图形的基本元素,在启动绘图模式的时候,使用函数glBegin(GLenum mode),其中该函数的参数就是指定的图元的类型,主要包括如表(来自天极网)所示的内容:

类型 说明 GL_POINTS 单个顶点集 GL_LINES 多组双顶点线段 GL_POLYGON 单个简单填充凸多边形 GL_TRAINGLES 多组独立填充三角形 GL_QUADS 多组独立填充四边形 GL_LINE_STRIP 不闭合折线 GL_LINE_LOOP 闭合折线 GL_TRAINGLE_STRIP 线型连续填充三角形串 GL_TRAINGLE_FAN 扇形连续填充三角形串 GL_QUAD_STRIP 连续填充四边形串

具体地,部分基本图元显示效果示例如图(来自互联网)所示:

颜色的设置,最简单地,可以直接调用例如函数glColor3f()进行颜色的设置,其声明如下所示:

WINGDIAPI void APIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);

这里就是指定了R、G、B三个颜色分量的值。

另外,可以在gl.h中看到更多设置颜色的函数声明,如下所示:

WINGDIAPI void APIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue);
WINGDIAPI void APIENTRY glColor3bv (const GLbyte *v);
WINGDIAPI void APIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue);
WINGDIAPI void APIENTRY glColor3dv (const GLdouble *v);
WINGDIAPI void APIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);
WINGDIAPI void APIENTRY glColor3fv (const GLfloat *v);
WINGDIAPI void APIENTRY glColor3i (GLint red, GLint green, GLint blue);
WINGDIAPI void APIENTRY glColor3iv (const GLint *v);
WINGDIAPI void APIENTRY glColor3s (GLshort red, GLshort green, GLshort blue);
WINGDIAPI void APIENTRY glColor3sv (const GLshort *v);
WINGDIAPI void APIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue);
WINGDIAPI void APIENTRY glColor3ubv (const GLubyte *v);
WINGDIAPI void APIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue);
WINGDIAPI void APIENTRY glColor3uiv (const GLuint *v);
WINGDIAPI void APIENTRY glColor3us (GLushort red, GLushort green, GLushort blue);
WINGDIAPI void APIENTRY glColor3usv (const GLushort *v);
WINGDIAPI void APIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
WINGDIAPI void APIENTRY glColor4bv (const GLbyte *v);
WINGDIAPI void APIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
WINGDIAPI void APIENTRY glColor4dv (const GLdouble *v);
WINGDIAPI void APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
WINGDIAPI void APIENTRY glColor4fv (const GLfloat *v);
WINGDIAPI void APIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha);
WINGDIAPI void APIENTRY glColor4iv (const GLint *v);
WINGDIAPI void APIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha);
WINGDIAPI void APIENTRY glColor4sv (const GLshort *v);
WINGDIAPI void APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
WINGDIAPI void APIENTRY glColor4ubv (const GLubyte *v);
WINGDIAPI void APIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha);
WINGDIAPI void APIENTRY glColor4uiv (const GLuint *v);
WINGDIAPI void APIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha);
WINGDIAPI void APIENTRY glColor4usv (const GLushort *v);
WINGDIAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
WINGDIAPI void APIENTRY glColorMaterial (GLenum face, GLenum mode);
WINGDIAPI void APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

函数名称的格式说明如下:

数字表示参数的个数,字母表示参数的类型, 
b 表示8位字符(OpenGL中将这个类型定义为GLubyte) 
s 表示16位整数(OpenGL中将这个类型定义为GLshort)   
i 表示32位整数(OpenGL中将这个类型定义为GLint和GLsizei)   
f 表示32位浮点数(OpenGL中将这个类型定义为GLfloat和GLclampf), 
d 表示64位浮点数(OpenGL中将这个类型定义为GLdouble和GLclampd)   
v 表示传递的几个参数将使用指针的方式 
u 表示上述类型为无符号的,即unsigned,可以和上述字母进行组合  

通过上节课中画点的例子,对每个点进行颜色的设置,代码如下所示:

#include <windows.h>
#include <GL/glut.h>

void drawPoint(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0f);
const GLfloat vertex[9][2] = { // 定义点数组
   {-0.5f,0.5f},
   {0.0f,0.5f},
   {0.5f,0.5f},
   {-0.5f,0.0f},
   {0.0f,0.0f},
   {0.5f,0.0f},
   {-0.5f,-0.5f},
   {0.0f,-0.5f},
   {0.5f,-0.5f}
};
const GLfloat color[9][3] = { // 定义颜色数组
   {0.0f,0.0f,0.0f},
   {0.0f,1.0f,0.0f},
   {0.0f,0.0f,1.0f},
   {0.35f,0.360f,0.782f},
   {0.87f,0.87f,0.87},
   {0.5f,0.5f,0.5f},
   {1.0f,0.0f,0.0},
   {0.0f,0.533f,0.457},
   {1.0f,1.0f,1.0f}
};
glBegin(GL_POINTS);
for(int i=0;i<9;i++) {
   glColor3fv(color[i]); // 在画点之前进行颜色设置
   glVertex2fv(vertex[i]); //   画点
}
glEnd();
glFlush();
}

int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("OpenGL基本图元:点");
glutDisplayFunc(&drawPoint);
glutMainLoop();
return 0;
}

编译并运行,效果如图所示:

需要注意的是,在画点之前最近进行的颜色设置才会生效。

画线

仍然利用上面的例子,只是将绘图模式改为画线。同时,将点的大小修改为15f,并使用函数glVertex3fv()进行点的设置,因此点就是三维坐标点,就要修改点数组为9*3数组,代码如下所示:

#include <windows.h>
#include <GL/glut.h>

void drawLine(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(15.0f);
const GLfloat vertex[9][3] = {
   {-0.5f,0.5f,0.1f},
   {0.0f,0.5f,0.2f},
   {0.5f,0.5f,0.3f},
   {-0.5f,0.0f,0.4f},
   {0.0f,0.0f,0.5f},
   {0.5f,0.0f,0.6f},
   {-0.5f,-0.5f,0.7f},
   {0.0f,-0.5f,0.8f},
   {0.5f,-0.5f,0.9f}
};
const GLfloat color[9][3] = {
   {0.8f,0.3f,0.2f},
   {0.0f,1.0f,0.0f},
   {0.0f,0.0f,1.0f},
   {0.35f,0.360f,0.782f},
   {0.87f,0.87f,0.87},
   {0.5f,0.5f,0.5f},
   {1.0f,0.0f,0.0},
   {0.0f,0.533f,0.457},
   {1.0f,1.0f,1.0f}
};
glBegin(GL_LINES);  // 启用画线模式
for(int i=0;i<9;i++) {
   glColor3fv(color[i]);
   glVertex3fv(vertex[i]);
}
glEnd();
glFlush();
}

int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("OpenGL基本图元:线");
glutDisplayFunc(&drawLine);
glutMainLoop();
return 0;
}

编译并运行,显示效果如图所示:

可以看到,一共画出了4条线,而我们用到了9个点,也就是说,画线的操作是这样执行的:按照在glBegin(GL_LINES)与glEnd()语句之间列出的点的顺序,每相邻的两个点画一条线,如果是奇数个点,那么最后一个点就不可能有另一个端点而画出线条,同时,这个点也不会在屏幕中单独显示出一个点的。

画线的时候,可以对线宽和线型进行设置。

对线宽设置调用函数glLineWidth(),该函数的声明如下所示:

WINGDIAPI void APIENTRY glLineWidth (GLfloat width);

一个参数width指定了线条的宽度,即线条的粗细。

对线型进行设置可以调用函数glLineStipple(),该函数的声明如下所示:

WINGDIAPI void APIENTRY glLineStipple (GLint factor, GLushort pattern);

第一个参数是一个乘数因子,主要对第二个参数而言的,第二个参数pattern是16位的整数。在使用某种指定的线型进行画线的时候,会计算factor与pattern中每一个bit的乘积,即,使用factor次pattern中的某一位(bit)。其中factor的取值范围是[0,256],pattern一般使用16进制。

在启动使用某种线型模式的时候,需要调用glEnable()函数来启动,而使用glDisable()函数关闭这种模式。

下面写一个程序,如下所示:

void drawLine(void) {
glClear(GL_COLOR_BUFFER_BIT);

glLineWidth(30.0f);
glEnable(GL_LINE_STIPPLE); //   启用虚线画线模式
glLineStipple(5,0xF0F0); // 设置画线样式
glBegin(GL_LINES);
   glColor3f(1.0f,0.0f,0.0f);
   glVertex3f(-0.5f,0.5f,0.0f);
   glVertex3f(0.5f,0.5f,0.0f);
glEnd();
glDisable(GL_LINE_STIPPLE);

glLineWidth(2.0f);
glEnable(GL_LINE_SMOOTH); //   启用平滑画线模式
glBegin(GL_LINES);
   glColor3f(1.0f,1.0f,0.0f);
   glVertex3f(-0.5f,0.0f,0.0f);
   glVertex3f(0.5f,0.0f,0.0f);
glEnd();
glDisable(GL_LINE_SMOOTH);

glLineWidth(7.0f);
glEnable(GL_LINE_STIPPLE); //   启用虚线画线模式
glLineStipple(3,0xA160);
glBegin(GL_LINES);
   glColor3f(0.0f,1.0f,0.0f);
   glVertex3f(-0.5f,-0.5f,0.0f);
   glVertex3f(0.5f,-0.5f,0.0f);
glEnd();
glDisable(GL_LINE_STIPPLE);

glFlush();
}

编译并运行,效果如图所示:

画多边形

OpenGL使用glBegin(GL_POLYGON);语句来启动画多边形,而且只能是凸多边形。

绘制多边形,调用glEnable(GL_POLYGON_STIPPLE)来启动多边形绘制模式,可以调用函数glPolygonStipple()来设置多边形绘制模式。该函数的声明如下:

WINGDIAPI void APIENTRY glPolygonStipple (const GLubyte *mask);

参数mask是一个指向32x32位图的指针。与虚线绘制的道理一样,某位为1时绘制,为0时什么也不绘。注意,不用时用glDisable(GL_POLYGON_STIPPLE)关闭。

函数glPolygonMode()可以设置多边形的填充模式,声明如下:

WINGDIAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);

参数face用来指定要填充的是多变形的哪一个面,可以取值:

GL_FRONT    正面(前面)
GL_BACK      反面(背面)
GL_FRONT_AND_BACK   正面和反面

参数mode用来指定要对多边形进行填充的模式,可以取值:

GL_POINT    轮廓点式多边形
GL_LINE     轮廓线式多边形
GL_FILL     全填充式多边形

下面是一个使用位图填充多边形的例子,代码如下所示:

include <windows.h>
#include <GL/glut.h>

void drawPolygon(void) {
glClear(GL_COLOR_BUFFER_BIT);
GLubyte pattern[128] = {  // 定义填充位图数组
        0x00,0x01,0x80,0x00,
        0x00,0x03,0xc0,0x00,
        0x00,0x07,0xe0,0x00,
        0x00,0x0f,0xf0,0x00,
        0x00,0x1f,0xf8,0x00,
        0x00,0x3f,0xfc,0x00,
        0x00,0x7f,0xfe,0x00,
        0x00,0xff,0xff,0x00,
        0x01,0xff,0xff,0x80,
        0x03,0xff,0xff,0xc0,
        0x07,0xff,0xff,0xe0,
        0x0f,0xff,0xff,0xf0,
        0x1f,0xff,0xff,0xf8,
        0x3f,0xff,0xff,0xfc,
        0x7f,0xff,0xff,0xfe,
        0xff,0xff,0xff,0xff,
        0xff,0xff,0xff,0xff,
        0x7f,0xff,0xff,0xfe,
        0x3f,0xff,0xff,0xfc,
        0x1f,0xff,0xff,0xf8,
        0x0f,0xff,0xff,0xf0,
        0x07,0xff,0xff,0xe0,
        0x03,0xff,0xff,0xc0,
        0x01,0xff,0xff,0x80,
        0x00,0xff,0xff,0x00,
        0x00,0x7f,0xfe,0x00,
        0x00,0x3f,0xfc,0x00,
        0x00,0x1f,0xf8,0x00,
        0x00,0x0f,0xf0,0x00,
        0x00,0x07,0xe0,0x00,
        0x00,0x03,0xc0,0x00,
        0x00,0x01,0x80,0x00
       };
glEnable(GL_POLYGON_STIPPLE); // 启动多边形填充模式
glPolygonStipple(pattern); //   指定填充位图数组
glPolygonMode(GL_BACK,GL_FILL);   // 设置正面填充模式
glPolygonMode(GL_FRONT,GL_POINT); // 设置反面填充模式
glBegin(GL_POLYGON);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f(-0.3f,0.5f,0.0f);
glVertex3f(0.3f,0.5f,0.0f);
glVertex3f(0.5f,0.0f,0.0f);
glVertex3f(0.3f,-0.5f,0.0f);
glVertex3f(-0.3f,-0.5f,0.0f);
glVertex3f(-0.5f,0.0f,0.0f);
glEnd();
glDisable(GL_POLYGON_STIPPLE);

glFlush();
}

int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("OpenGL基本图元:多边形");
glutDisplayFunc(&drawPolygon);
glutMainLoop();
return 0;
}

编译运行,效果如图所示:

由于多边形的反面我们看不到,所以也看不到它的填充模式。

画三角形

画三角形,需要调用:

glEnable(GL_TRIANGLES);

来启动。

在glEnable(GL_TRIANGLES)与glEnd()之间的点,按照顺序,每三个点对应一个三角形。例如

void drawTriangles(void) {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);

glColor3f(1.0f,1.0f,0.0f);
glVertex3f(-0.3f,0.5f,0.0f);
glVertex3f(0.3f,0.5f,0.0f);
glVertex3f(0.5f,0.0f,0.0f);

glColor3f(0.0f,1.0f,1.0f);
glVertex3f(0.3f,-0.5f,0.0f);
glVertex3f(-0.3f,-0.5f,0.0f);
glVertex3f(-0.5f,0.0f,0.0f);
glEnd();

glFlush();
}

编译运行,效果如图所示:

画其它图形

还可以方便地画出其它图形,可以参考前面的表格和图形示例。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值