OpenGL第三讲——关于点、直线和多边形

Chapter 3 关于点、直线和多边形

3.1 关于点

3.1.1 改变点的大小

点的大小默认为1px,但是也可以用glPointSize来改变其大小:

void glPointSize(GLfloat size);

size必须大于0.0f,默认为1.0f

void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPointSize(5.0f);
    glBegin(GL_POINTS);
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.5f, 0.5f);
    glEnd();
    glFlush();
}
image-20211229164509575

3.2 关于直线

3.2.1 指定直线宽度

直线也可以指定宽度:

void glLineWidth(GLfloat width);

3.2.2 画虚线

使用glEnable(GL_LINE_STIPPLE)来启动虚线模式

使用glDisable(GL_LINE_STIPPLE)可以关闭

然后使用glLineStipple来设置虚线的样式

void glLineStipple(GLint factor, GLushort pattern);

pattern是由1和0组成的长度为16的序列,从最低位开始看,如果为1,则直线上接下来应该画的factor个点将被画为实的;如果为0,则直线上接下来应该画的factor个点将被画为虚的。

http://blog.programfan.com/upfile/200608/20060801172519.gif

factor理解为重复因子,可以实现扩展,比如本来有1位1,那么会将它重复变成factor个点。举个例子,比如AAAA就是1010 1010 1010 1010,就是每隔一个像素画一个点,如果factor为2,则将每一位都扩展成2位相同的,变成11001100 11001100这种,于是就是每2个像素一隔画2个像素。

void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_LINE_STIPPLE);
    // factor=2, pattern=0000 1111 0000 1111
    glLineStipple(2, 0x0F0F);
    glLineWidth(10.0f);
    glBegin(GL_LINES);
    glVertex2f(0.0f, 0.0f);
    glVertex2f(0.5f, 0.5f);
    glEnd();
    glFlush();
}
image-20211229165627562

3.3 关于多边形

3.3.1 多边形的两面以及绘制方式

从三维的角度来看,一个多边形具有两个面。每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,其中“填充”是默认的方式。可以为两个面分别设置不同的方式。

一般约定为“顶点以逆时针(Counter Clock Wise CCW)顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。

glPolygonMode(GL_FRONT, GL_FILL);           // 设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE);            // 设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式

反转

可以通过glFrontFace函数来交换“正面”和“反面”的概念。

 glFrontFace(GL_CCW); // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
 glFrontFace(GL_CW);  // 设置CW方向为“正面”,CW即ClockWise,顺时针

示例程序:

void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式
    glPolygonMode(GL_BACK, GL_LINE);  // 设置反面为线形模式
    glFrontFace(GL_CCW);              // 设置逆时针方向为正面
    glBegin(GL_POLYGON);              // 按逆时针绘制一个正方形,在左下方
        glVertex2f(-0.5f, -0.5f);
        glVertex2f(0.0f, -0.5f);
        glVertex2f(0.0f, 0.0f);
        glVertex2f(-0.5f, 0.0f);
    glEnd();
    glBegin(GL_POLYGON);              // 按顺时针绘制一个正方形,在右上方
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.0f, 0.5f);
        glVertex2f(0.5f, 0.5f);
        glVertex2f(0.5f, 0.0f);
    glEnd();
    glFlush();
}

image-20211229170643827
逆时针为正面,填充;顺时针为方面,线条

3.3.2 剔除多边形表面

在三维空间中,一个多边形虽然有两个面,但我们无法看见背面的那些多边形,而一些多边形虽然是正面的,但被其他多边形所遮挡。如果将无法看见的多边形和可见的多边形同等对待,无疑会降低我们处理图形的效率。在这种时候,可以将不必要的面剔除。

首先,使用glEnable(GL_CULL_FACE)来启动剔除功能

使用glDisable(GL_CULL_FACE)可以关闭之

然后,使用glCullFace来进行剔除。glCullFace的参数可以是GL_FRONTGL_BACK或者GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除正反两面的多边形。

注意:剔除功能只影响多边形,而对点和直线无影响。例如,使用glCullFace(GL_FRONT_AND_BACK)后,所有的多边形都将被剔除,所以看见的就只有点和直线。

加上下面语句后运行效果如下

glEnable(GL_CULL_FACE);           // 开启剔除面
glCullFace(GL_FRONT);
image-20211229171454911
可以看到正面被剔除了

3.3.3 镂空多边形

首先,使用glEnable(GL_POLYGON_STIPPLE)来启动镂空模式

使用glDisable(GL_POLYGON_STIPPLE)可以关闭之

然后,使用glPolygonStipple来设置镂空的样式。

void glPolygonStipple(const GLubyte *mask);

其中的参数mask指向一个长度为128字节的空间,它表示了一个32*32的矩形应该如何镂空

其中:第一个字节表示了最左下方的从左到右(也可以是从右到左,这个可以修改)8个像素是否镂空(1表示不镂空,显示该像素;0表示镂空,显示其后面的颜色),最后一个字节表示了最右上方的8个像素是否镂空。

可以直接给一个128字节长度的mask数组:

static GLubyte Mask[128] =
{
    0x00, 0x00, 0x00, 0x00,   //  这是最下面的一行
    0x00, 0x00, 0x00, 0x00,
    0x03, 0x80, 0x01, 0xC0,   //  麻
    0x06, 0xC0, 0x03, 0x60,   //  烦
    0x04, 0x60, 0x06, 0x20,   //  的
    0x04, 0x30, 0x0C, 0x20,   //  初
    0x04, 0x18, 0x18, 0x20,   //  始
    0x04, 0x0C, 0x30, 0x20,   //  化
    0x04, 0x06, 0x60, 0x20,   //  ,
    0x44, 0x03, 0xC0, 0x22,   //  不
    0x44, 0x01, 0x80, 0x22,   //  建
    0x44, 0x01, 0x80, 0x22,   //  议
    0x44, 0x01, 0x80, 0x22,   //  使
    0x44, 0x01, 0x80, 0x22,   //  用
    0x44, 0x01, 0x80, 0x22,
    0x44, 0x01, 0x80, 0x22,
    0x66, 0x01, 0x80, 0x66,
    0x33, 0x01, 0x80, 0xCC,
    0x19, 0x81, 0x81, 0x98,
    0x0C, 0xC1, 0x83, 0x30,
    0x07, 0xE1, 0x87, 0xE0,
    0x03, 0x3F, 0xFC, 0xC0,
    0x03, 0x31, 0x8C, 0xC0,
    0x03, 0x3F, 0xFC, 0xC0,
    0x06, 0x64, 0x26, 0x60,
    0x0C, 0xCC, 0x33, 0x30,
    0x18, 0xCC, 0x33, 0x18,
    0x10, 0xC4, 0x23, 0x08,
    0x10, 0x63, 0xC6, 0x08,
    0x10, 0x30, 0x0C, 0x08,
    0x10, 0x18, 0x18, 0x08,
    0x10, 0x00, 0x00, 0x08   // 这是最上面的一行
};

这样一堆数据非常缺乏直观性,我们需要很费劲的去分析,才会发现它表示的竟然是一只苍蝇。

如果将这样的数据保存成图片,并用专门的工具进行编辑,显然会方便很多。下面介绍如何做到这一点。

首先,用Windows自带的画笔程序新建一副图片,取名为mask.bmp,注意保存时,应该选择**“单色位图”**。在“图象”->“属性”对话框中,设置图片的高度和宽度均为32
用放大镜观察图片,并编辑之。黑色对应二进制零(镂空),白色对应二进制一(不镂空),编辑完毕后保存。

比如画一个这样的图形:

mask

void myDisplay(void)
{
    static GLubyte Mask[128];
    FILE* fp;
    fp = fopen("C:\\Users\\10737\\Pictures\\mask.bmp", "rb");
    if (!fp)
        exit(0);
    // 移动文件指针到这个位置,使得再读sizeof(Mask)个字节就会遇到文件结束
    // 注意-(int)sizeof(Mask)虽然不是什么好的写法,但这里它确实是正确有效的
    // 如果直接写-sizeof(Mask)的话,因为sizeof取得的是一个无符号数,取负号会有问题
    if (fseek(fp, -(int)sizeof(Mask), SEEK_END))
        exit(0);
    if (!fread(Mask, sizeof(Mask), 1, fp))
        exit(0);
    fclose(fp);

    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_POLYGON_STIPPLE);
    glPolygonStipple(Mask);
    glRectf(-0.5f, -0.5f, 0.0f, 0.0f);  // 在左下方绘制一个有镂空效果的正方形
    glDisable(GL_POLYGON_STIPPLE);
    glRectf(0.0f, 0.0f, 0.5f, 0.5f);    // 在右上方绘制一个无镂空效果的正方形
    glFlush();
}
image-20211229173919083
左下角镂空,右上角无镂空

如果出现fopen报错:"error C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead"Definitely

项目----》 XX属性 ----》C++ —>预处理器 —》在预处理器定义添加“_CRT_SECURE_NO_WARNINGS”

详情可见https://blog.csdn.net/my_angle2016/article/details/84335979

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值