OpenGL-入门-关于多边形

关于多边形的正反面

在二维的面,从三维的角度来看,是具有两个面的。一般约定为“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。

每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点
, 其中“填充”是默认的方式。可以为两个面分别设置不同的方式。
glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE); // 设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式

#include "pch.h"
#include <iostream>
#include <GL/glut.h> 
#include <math.h>
const GLfloat Pi = 3.1415926536f;
const GLfloat factor = 0.1f;
void myDisplay(void) {
	glClear(GL_COLOR_BUFFER_BIT);
	glPolygonMode(GL_FRONT, GL_FILL);/*设置正面为填充模式*/
	glPolygonMode(GL_BACK, GL_LINE);/*设置反面为线性模式*/
	glFrontFace(GL_CCW);	/*glFrontFace函数设置逆时针方向为正面
							CCW(counterclockwise逆时针)
							CW(clockwise顺时针)*/
	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();
}

int main(int argc, char *argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("关于多边形");
	glutDisplayFunc(&myDisplay);
	glutMainLoop();
	return 0;
}

剔除多边形表面

在三维空间中,一个多边形虽然有两个面,但我们无法看见背面的那些多边形,而一些多边形虽然是正面的,但被其他多边形所遮挡。
如果将无法看见的多边形和可见的多边形同等对待,无疑会降低我们处理图形的效率。在这种时候,可以将不必 要的面剔除。
首先,使用 glEnable(GL_CULL_FACE);来启动剔除功能。
使用glDisable(GL_CULL_FACE)可以关闭之。
然后,使用 glCullFace 来进行剔除。 glCullFace 的参数可以是 GL_FRONT,GL_BACK 或者 GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除 正反两面的多边形。 注意:剔除功能只影响多边形,而对点和直线无影响。例如,使用 glCullFace(GL_FRONT_AND_BACK)后,所有的多边 形都将被剔除,所以看见的就只有点和直线。

多边形镂空

直线可以被画成虚线,而多边形则可以进行镂空。
首先,使用 glEnable(GL_POLYGON_STIPPLE);来启动镂空模式。
使用glDisable(GL_POLYGON_STIPPLE)可以关闭。

然后,使用 glPolygonStipple 来设置镂空的样式。
void glPolygonStipple(const GLubyte mask);
其中的参数 mask 指向一个长度为 128 字节的空间,它表示了一个 32
32 的矩形应该如何镂空。
其中:第一个字节表示了 最左下方的从左到右(也可以是从右到左,这个可以修改)8 个像素是否镂空(1 表示不镂空,显示该像素;0 表示镂空,显 示其后面的颜色),最后一个字节表示了最右上方的 8 个像素是否镂空。

但是,如果我们直接定义这个 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 数组了。
static GLubyte Mask[128];
FILE *fp;
fp = fopen(“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);
// 读取 sizeof(Mask)个字节到 Mask if( !fread(Mask, sizeof(Mask), 1, fp) )
exit(0);
fclose(fp);

#include <stdio.h>
#include <stdlib.h> 
#include <GL/glut.h>
void myDisplay(void) 
{     
	static GLubyte Mask[128];     
	FILE *fp; 
	/*    
	fp = fopen("mask.bmp", "rb");    //如果使用fopen会出现C4496的安全错误
									//具体错误说明是fopen': This function or 		variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 
									//就是说你用fopen会不安全,考虑用一下fopen_s
	//vs编辑器中fopen没有检查溢出问题,所以会报安全错误。(待补充)
	*/ 
	errno_t err;		/*待补充*/
	err = fopen_s(&fp,"D:\\mask1.bmp", "rb");
	if( !fp )         
		exit(0);     
	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(); 
} 

 int main(int argc, char *argv[]) 
 {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("镂空");
	glutDisplayFunc(&myDisplay);
	glutMainLoop();
	return 0;
}
 

mask图片
mask.bmp图片

以mask.bmp做的镂空图
效果图

郑半仙
2019.3.1

猜你喜欢

转载自blog.csdn.net/weixin_42785489/article/details/88047550
今日推荐