OpenGl(二)点线设置、多边形镂空


1. 改变点的大小


OpenGL中默认点的大小是1个像素,使用函数glPointSIze可以调整点的大小,入参是GLfloat,相当于是浮点数。

相关代码:


void myDisplay(void)    
{ 
	//设置点的大小
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(5);  //设置点的大小为5个像素
	glColor4f(0,0,1,0);  //设置颜色为蓝色
	glBegin(GL_POINTS); //绘制点
	glVertex2f(0,0);
	glVertex2f(0.6,0.6);
	glEnd();
	glFlush();
}

效果:




2. 改变直线的宽度


线宽的设置用函数glLineWidth,入参是GLfloat,必须大于0.0f。

相关代码:


void myDisplay(void)    
{ <span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//设置线的宽度
<span style="white-space:pre">	</span>glClear(GL_COLOR_BUFFER_BIT);
<span style="white-space:pre">	</span>glLineWidth(5);
<span style="white-space:pre">	</span>glBegin(GL_LINES);
<span style="white-space:pre">	</span>glVertex2f(-0.5,-0.5);
<span style="white-space:pre">	</span>glVertex2f(0.5,-0.5);
<span style="white-space:pre">	</span>glEnd();
<span style="white-space:pre">	</span>glFlush();
}


效果:




3. 设置直线显示模式为虚线


对虚线的设置需要先用函数glEnable(GL_LINE_STIPPLE)开启虚线模式,之后使用glLineStipple函数设置,它有连个参数。

void  glLineStipple (GLint factor, GLushort pattern);

第一个参数是直线上一个片段的像素个数,第二个参数是一个由1和0组成的16位序列,从最低位开始,如果为1,则线段上从起点开始的factor个像素点被绘制为实的,如果为0,则会被绘制成虚的。其对应关系如下图所示:




相关代码:


void myDisplay(void)    
{ 	
	//设置虚线模式
	glClear(GL_COLOR_BUFFER_BIT);
	glLineWidth(3);
	glEnable(GL_LINE_STIPPLE);
	glLineStipple(0,0X00FF);
	glBegin(GL_LINES);
	glVertex2f(-0.8,0.5);
	glVertex2f(0.8,0.5);
	glEnd();
	glFlush();
}


显示效果:




4. 多边形


4.1 多边形的正面和反面


三维空间中的一个平面多边形(即厚度为0的多边形)具有两个面,就像一张纸具有正面和反面一样。在OpenGL中可以对正反面分别设置不同的填充、边缘线轮廓填充方式等。

一般约定,“顶点以逆时针顺序呈现在窗口上的面”为正面,以顺时针顺序呈现的面为反面。

下边绘制一个正面多边形和一个反面多边形,相关代码:


void myDisplay(void)    
{ 	
	//正反面分别设置不同的模式、正反面调换
	glClear(GL_COLOR_BUFFER_BIT);
	glPolygonMode(GL_FRONT,GL_FILL);   //设置正面为填充模式
	glPolygonMode(GL_BACK,GL_LINE);    //设置反面为线形模式
	//glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);  //正反面都设置为顶点绘制方式
	glFrontFace(GL_CCW); //设置逆时针为正面,为系统默认
	//glFrontFace(GL_CW);  //设置顺时针为正面
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(-0.5,0);
	glVertex2f(-0.5,-0.5);
	glVertex2f(0,-0.5);
	glEnd();
	glBegin(GL_POLYGON);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glVertex2f(0,0);
	glEnd();
	glFlush();
}

 效果:



正反面可以通过函数glFrongFace来交换,正面被设置为反面的同时,反面被自动设置为正面,效果:





4.2 剔除多边形的反面


空间三维中的一个多边形(注意是多边形,不是三维物体)在二维平面显示的时候,多边形的反面是被遮挡看不见的,或者是一个多边形被另一个多边形遮挡住的情况,如果把这种情况跟正面显示的部分同等对待处理的话,会降低处理图形的效率,因为就算花费了大量时间去处理,在最终的显示上也是体现不出来的,相当于是做了无用功。所以需要把这些面剔除掉,在处理的时候不参与运算。

使用glEnable(GL_CULL_FACE)来激活剔除功能,使用glCullFace来剔除指定的反面(或正面)。

相关代码:


void myDisplay(void)    
{ 	
	//剔除正面示例
	glClear(GL_COLOR_BUFFER_BIT);
	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(-0.5,0);
	glVertex2f(-0.5,-0.5);
	glVertex2f(0,-0.5);
	glEnd();
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glEnd();
	glFlush();
	glBegin(GL_POLYGON);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glVertex2f(0,0);
	glEnd();
	glFlush();
}


本例指定剔除正面,剔除前:                                               剔除后:

           



4.3 多边形的镂空


多边形可以设置镂空效果,使用glEnable(GL_POLYGON_STIPPLE)开启镂空模式,之后使用glPolygonStipple

设置镂空基本图案。

void   glPolygonStipple (const GLubyte *mask);

mask是一个指向32*32*8bit的矩形空间,这个矩形空间中前8位表示图案最下方从左到右的8位像素的显示方式,1不镂空,0镂空显示背景色。

可以用一幅大小为32*32像素的图案来定义多边形镂空的基本样式单元。


制作方式为:

  • 1. 打开Windows自带的画图程序,新建一个空白图像
  • 2. 按下Ctrl+E,打开属性页,设置宽度和高度都为32




  • 3. 按下Ctrl键,之后波动鼠标滚轮放大图像到最大,在图像标题栏“查看”项里勾选标尺和网格线,方便作图:




  • 4. 之后就可以用画笔在上边做你想要镂空的图案了,做完之后另存为mask.bmp,并且保存类型里选择“单色位图”,忽略警告。


相关代码:


void myDisplay(void)    
{ 		
	//镂空效果
	glClear(GL_COLOR_BUFFER_BIT);
	static GLubyte Mask[128]; 
	FILE *fp;    
	fp = fopen("mask.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.7f, -0.7f, 0.7f, 0.7f);   // 绘制一个有镂空效果的正方形     	 
	glFlush();
}

效果:



完整代码:


#include <glut.h> 
#include <iostream>

using namespace std;

void myDisplay(void)    
{ 
	//设置点的大小
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(5);  //设置点的大小为5个像素
	glBegin(GL_POINTS); //绘制点
	glVertex2f(0,0);
	glVertex2f(0.6,0.6);
	glEnd();
	glFlush();
	system("pause");

	//设置线的宽度
	glLineWidth(5);
	glBegin(GL_LINES);
	glVertex2f(-0.4,-0.4);
	glVertex2f(0.4,-0.4);
	glEnd();
	glFlush();
	system("pause");

	//设置虚线模式
	glLineWidth(3);
	glEnable(GL_LINE_STIPPLE);
	glLineStipple(0,0X00FF);
	glBegin(GL_LINES);
	glVertex2f(-0.8,0.8);
	glVertex2f(0.8,0.8);
	glEnd();
	glFlush();
	system("pause");

	//正反面分别设置不同的模式、正反面调换
	glPolygonMode(GL_FRONT,GL_FILL);   //设置正面为填充模式
	glPolygonMode(GL_BACK,GL_LINE);    //设置反面为线形模式
	//glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);  //正反面都设置为顶点绘制方式
	glFrontFace(GL_CCW); //设置逆时针为正面,为系统默认
	//glFrontFace(GL_CW);  //设置顺时针为正面
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(-0.5,0);
	glVertex2f(-0.5,-0.5);
	glVertex2f(0,-0.5);
	glEnd();
	glBegin(GL_POLYGON);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glVertex2f(0,0);
	glEnd();
	glFlush();
	system("pause");

	//剔除正面示例
	glClear(GL_COLOR_BUFFER_BIT);
	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(-0.5,0);
	glVertex2f(-0.5,-0.5);
	glVertex2f(0,-0.5);
	glEnd();
	glBegin(GL_POLYGON);
	glVertex2f(0,0);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glEnd();
	glFlush();
	glBegin(GL_POLYGON);
	glVertex2f(0,0.5);
	glVertex2f(0.5,0.5);
	glVertex2f(0.5,0);
	glVertex2f(0,0);
	glEnd();
	glFlush();
	system("pause");

	//镂空效果
	glClear(GL_COLOR_BUFFER_BIT);
	glDisable(GL_CULL_FACE);
	static GLubyte Mask[128]; 
	FILE *fp;    
	fp = fopen("mask.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.7f, -0.7f, 0.7f, 0.7f);   // 绘制一个有镂空效果的正方形     	 
	glFlush();
}  

int main(int argc, char *argv[])    
{    
	glutInit(&argc, argv);   //初始化GLUT
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);  
	glutInitWindowPosition(500, 200);    
	glutInitWindowSize(400, 400);    
	glutCreateWindow("OpenGL");   
	glutDisplayFunc(&myDisplay);   //回调函数 
	glutMainLoop();    //持续显示,当窗口改变会重新绘制图形
	return 0;    
}  

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenGL橡皮筋画多边形是一种使用OpenGL图形库绘制多边形形状的方法。它利用鼠标的移动轨迹来动态绘制多边形的边界。 实现这个功能需要几个步骤: 1. 初始化OpenGL的环境,创建窗口并设置视口和投影矩阵。 2. 在鼠标按下事件中,获取鼠标点击位置的坐标,并保存为多边形的第一个顶点。 3. 在鼠标移动事件中,获取鼠标当前位置的坐标,并根据之前保存的第一个顶点和当前位置来计算出多边形的其他顶点坐标。可以使用简单的算法,如直线连续相连来计算顶点坐标。 4. 在鼠标释放事件中,将最后一个计算出的顶点添加到多边形的顶点列表中。 5. 最后,使用OpenGL的绘制函数(如glBegin和glEnd)将多边形的顶点连接起来,形成一个完整的多边形。 需要注意的是,OpenGL是一种低级的图形库,需要手动进行绘制调用,并且需要处理鼠标事件和计算顶点坐标等操作。此外,还要考虑多边形的绘制顺序和顶点的连接方式,以确保多边形的边界能够正确地闭合。 总之,通过使用OpenGL的橡皮筋画多边形的方法,可以通过鼠标的移动轨迹实时地绘制多边形的边界。这个方法可以应用于各种需要动态绘制多边形形状的应用,如计算机辅助设计、图形编辑器等领域。 ### 回答2: OpenGL橡皮筋画多边形是一种通过鼠标交互绘制多边形的方法。具体实现过程如下: 首先,需要准备一个空的OpenGL窗口,设置好视口、投影矩阵等OpenGL参数。 接下来,需要捕捉鼠标的事件,包括鼠标按下、鼠标移动和鼠标释放等。 当鼠标按下时,记录下鼠标按下位置的坐标,并将其作为多边形的一个顶点。 当鼠标移动时,根据当前鼠标的位置,绘制一个虚线或虚线框作为橡皮筋效果。这可以通过将OpenGL的绘制模式设置线段模式,并指定线段的样式来实现。 当鼠标释放时,将当前鼠标的位置作为最后一个多边形的顶点,并停止绘制橡皮筋。 最后,根据所记录的鼠标的位置坐标,使用OpenGL的绘图API,绘制多边形的边缘线段。 需要注意的是,在绘制边缘线段时,需要考虑到多边形的闭合性。即最后一个顶点需要与起始点相连,形成一个闭合的多边形。 同时,为了达到橡皮筋效果,可以使用计时器功能,定期刷新OpenGL窗口,重绘橡皮筋。 总结起来,实现OpenGL橡皮筋画多边形需要捕捉鼠标的事件,并根据鼠标的操作实时更新多边形的顶点坐标。在绘制多边形时,通过设置OpenGL的绘制模式和使用计时器功能,实现橡皮筋效果。 ### 回答3: OpenGL橡皮筋画多边形的基本原理是通过鼠标的交互来确定多边形的顶点,然后在OpenGL的窗口中绘制出来。 首先,我们需要定义一个鼠标按键触发的事件函数,当鼠标按下时,获取鼠标当前的位置,并将其作为多边形的第一个顶点。 然后,监听鼠标移动的事件函数,当鼠标移动时,根据当前鼠标位置绘制出一个实时更新的直线,表示橡皮筋的效果。这个直线的起点是多边形的第一个顶点,终点是当前鼠标的位置。 当鼠标再次按下时,将当前鼠标位置作为多边形的下一个顶点,并继续按照之前的步骤,实时更新直线并继续监听鼠标移动事件。 当鼠标右键按下时,表示多边形的绘制完成。此时,将最后一个鼠标位置作为多边形的最后一个顶点,并将多边形的所有顶点连接起来。最后,将多边形的边和填充颜色等绘制属性设置好,通过OpenGL的绘制函数进行绘制。 需要注意的是,当橡皮筋直线绘制时,应该利用OpenGL提供的双缓冲机制,将实时更新的直线绘制到后备缓冲区中,然后将整个后备缓冲区同步到前面的显示缓冲区,以避免闪烁问题。 总结来说,绘制OpenGL橡皮筋画多边形的步骤包括鼠标按下时初始化多边形的第一个顶点,监听鼠标移动时实时更新绘制橡皮筋直线,鼠标右键按下时结束多边形的绘制,并将多边形的边和填充颜色等属性设置好后进行绘制。同时,要注意使用双缓冲机制来避免闪烁问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值