openGL学习笔记1(入门----如何绘制 直线、多边形、圆、利用图片绘制图形等)

#include <GL/glut.h>
void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);//GL_COLOR_BUFFER_BIT表示清除颜色
	glRectf(-0.5f, -0.5f, 0.5f, 0.5f); //画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标
	glFlush(); //保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(100, 100); //设置窗口位置
	glutInitWindowSize(400, 400);//窗口大小
	glutCreateWindow("第一个OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}




需要包含头文件#include <GL/glut.h>,这是GLUT的头文件。


本来OpenGL程序一般还要包含<GL/gl.h>和<GL/glu.h>,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含



程序运行结果:





===========================================================================================================

画圆:

/*
正四边形,正五边形,正六边形,……,直到正n边形,当n越大时,这个图形就越接近圆
当n大到一定程度后,人眼将无法把它跟真正的圆相区别
这时我们已经成功的画出了一个“圆”
(注:画圆的方法很多,这里使用的是比较简单,但效率较低的一种)

*/

程序:

#include <GL/glut.h>

#include <math.h>
const int n = 6;
const GLfloat R = 0.5f;
const GLfloat Pi = 3.1415926536f;
void myDisplay(void)
{
	int i;
	glClear(GL_COLOR_BUFFER_BIT); //清除颜色
	glBegin(GL_POINTS);//OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,
	       //glEnd函数之前(否则指定的顶点将被忽略)。并由glBegin来指明如何使用这些点
	       //GL_POLYGON表示画多边形(由点连接成多边形)

	for(i=0; i<n; ++i)
		glVertex2f(R*cos(2*Pi/n*i), R*sin(2*Pi/n*i));

	glEnd(); 

	glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)

}


int main(int argc, char *argv[])
{
	glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(100, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("第一个OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}



当n=6时,结果如下:

GL_POLYGON(填充的多边形):


GL_LINE_LOOP:(不填充的多边形)


GL_POINTS时(画点):




当n=100时,结果如下




======================================================================================================

改变点的大小:

#include <GL/glut.h>

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);清除颜色
	glPointSize(5.0f);//点的大小默认为1个像素,但也可以改变之。size必须大于0.0f,默认值为1.0f,单位为“像素”。
	glBegin(GL_POINTS);
	//glVertex2f(0.9f, 0.1f);
	glVertex2f(0.1f, 0.9f);
	glEnd();
	glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)
}


int main(int argc, char *argv[])
{
	glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(100, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}


======================================================================================================

画虚线:

程序:

#include <GL/glut.h>

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);//清除颜色
	glEnable(GL_LINE_STIPPLE);//启动虚线模式,使用glDisable(GL_LINE_STIPPLE)可以关闭
	glLineStipple(2, 0x0F0F);//设置虚线的样式
	glLineWidth(10.0f);//指定线宽

	glBegin(GL_LINES); ///在下面2个点之间画一条虚线
	glVertex2f(0.0f, 0.0f);
	glVertex2f(0.5f, 0.5f);
	glEnd(); //结束

	glFlush();
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(100, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}

结果如下:



使用glLineStipple来设置虚线的样式。
void glLineStipple(GLint  factor, GLushort  pattern);
pattern是由1和0组成的长度为16的序列,从最低位开始看,如果为1,则直线上接下来应该画的factor个点将被画为实的;如果为0,则直线上接下来应该画的factor个点将被画为虚的。

glLineStipple(2,0x0F0F); //设置虚线的样式

意思就是,最低位为1,表示最开始的2个点画为实的。也就是说虚线的样式是,先画10个实点,再画10个虚点。


=================================================================

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

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

可以通过glFrontFace函数来交换“正面”和“反面”的概念。
glFrontFace(GL_CCW);  // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
glFrontFace(GL_CW);   // 设置CW方向为“正面”,CW即ClockWise,顺时针



#include <GL/glut.h>

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();
}


int main(int argc, char *argv[])
{
	glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(200, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用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   // 这是最上面的一行
};

如果将这样的数据保存成图片,并用专门的工具进行编辑,显然会方便很多。

程序:

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
void myDisplay(void)
{
	
		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   // 这是最上面的一行
	};

	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);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(200, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}
运行结果:




程序:

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
void myDisplay(void)
{
	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); // 移动文件指针到这个位置,使得再读sizeof(Mask)个字节就会遇到文件结束
	if( !fread(Mask, sizeof(Mask), 1, fp) )
		exit(0); // 读取sizeof(Mask)个字节到Mask
	fclose(fp);

	glClear(GL_COLOR_BUFFER_BIT);//清除颜色
	glEnable(GL_POLYGON_STIPPLE);//启动多边形绘制模式
	glPolygonStipple(Mask);//设置多边形绘制模式.参数mask是一个指向32x32位图的指针。
	                      //与虚线绘制的道理一样,某位为1时绘制,为0时什么也不绘。
	                       //注意,不用时用glDisable(GL_POLYGON_STIPPLE)关闭。

	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);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式
	glutInitWindowPosition(200, 100); 
	glutInitWindowSize(400, 400);
	glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。
	glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数
	glutMainLoop(); //进行一个消息循环
	return 0;
}


运行结果:


其中,bmp位图:




评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值