OpenGL结合书中画苍蝇对位图的思考——镂空效果的实现以及利用位图实现用黑白相间的棋盘图案填充多边形

原理及重要函数说明

其实在画虚线和点划线时就已经利用16进制的每位来代表线段的一部分是开还是关(转换为二进制后也就是1画,0不画),这里的道理类似,只不过因为是绘制平面所以规则更多,但原理和画线一样。所谓镂空,不就是舍弃一部分不画来达到更好的效果吗。
用到的重要函数:
(1)glEnable(GL_POLYGON_STIPPLE);启用多边形填充模式
顾名思义,POLYGON是多边形,STIPPLE是v(动词)点画; 点彩画出;,所以可以看出这是一种依次看每个点画不画的模式,恰好就是和1画,0不画在语义上吻合。
(2)void glPolygonStipple(const GLubyte *mask); 指定用于填充多边形的模板位图
mask就是一个指向32×32位图的指针,这里用必要重新理清位、字节、像素(对于当前情况,不同情况下像素对应的可能不同)的关系,在这里,因为8bit=1字节(B),32×32位图就是128字节,因为默认情况一位控制一个像素画还是不画,那么一个字节对应8个像素,清楚了对应的单位,就容易理解模板位图。
此外,还要注意模板位图在创建时,是反着来的,也就是mask第一行对应画出来的图的最后一行,这么说很难理解,下面给出书中画苍蝇的例子来更好的体会

原理:(对位图的理解)
下面的flydata中一个元素就是8位,分别控制相邻八个像素(一定要转化成二进制才能看明白,跟着写几行就明白了),结合后面的效果图理解:可以看到苍蝇的最后两行是空的,正好对应flydata前两行元素(二进制都是0),而苍蝇的倒数第三行的两个翅膀的末尾,分别是0x03, 0x80, 0x01, 0xC0对应0000 0011 1000 0000 0001 1100 0000,其中两个相连的三个1正好是对应的两个翅膀的末尾,其他为0可以不画。

GLubyte flydata[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, 0x33, 0xcc, 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,
};
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(flydata);
glRectf(64.0f,0.0f,128.0f,64.0f);

通过这个glRectf画矩形的函数也可以体会到位图实现镂空的奥妙。
苍蝇的效果图:
OpenGL结合书中画苍蝇对位图的思考——镂空效果的实现以及利用位图实现用黑白相间的棋盘图案填充多边形_第1张图片

用黑白相间的棋盘图案填充多边形

理解上面这些,画黑白棋盘那太简单了,间隔都是固定的,只用想几个像素画一个格即可,这里我是四个像素为一格画的

#include

int winWidth=600,winHeight=500;
void myinit(void)
{
	glClearColor(1.0f,1.0f,1.0f,1.0f);
}
void myReshape(int w,int h)
{
	winWidth=w;
	winHeight=h;
	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0,winWidth,0.0,winHeight);
}
//每桢OpenGL都会调用这个函数,用户应该把显示代码放在这个函数中
void display(void)
{
	//设置清除屏幕的颜色,并清除屏幕和深度缓冲
    glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.0,0.0,0.0);
	GLubyte Black_and_white_chessboard[]={//黑白间隔为四个像素
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
		0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
	};
	glEnable(GL_POLYGON_STIPPLE);
	glPolygonStipple(Black_and_white_chessboard);
	glRectf(200.0,200.0,300.0,300.0);
	//交换前后缓冲区
	glutSwapBuffers();
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);

	//初始化OPENGL显示方式
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
	//设定OPENGL窗口位置和大小
	glutInitWindowSize (500, 500); 
	glutInitWindowPosition (100, 100);

	//打开窗口
	glutCreateWindow ("");

	//调用初始化函数
    myinit();

	//设定窗口大小变化的回调函数
	glutReshapeFunc(myReshape);

	//开始OPENGL的循环
	glutDisplayFunc(display); 
	glutMainLoop();

	return 0;
}

你可能感兴趣的:(计算机图形学学习总结)