我是靠谱客的博主 傻傻小蝴蝶,最近开发中收集的这篇文章主要介绍OpenGL(二)图形绘制之平面多面体的绘制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述


通过绘制一个三菱锥初步了解绘制平面多面体。

<span style="font-size:18px;">#include<windows.h>
#include<gl/gl.h>
#include<gl/glut.h>
#include<gl/glu.h>
#include<stdio.h>

//窗口的大小
GLsizei windowWidth;
GLsizei windowHeight;


//旋转角度参数
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

//确定多边形的绕法的方向
BOOL bDepth = FALSE; //深度测试开关
BOOL bCull =  FALSE; //剔除开关



//初始化窗口
void SetupRC(void)
{
	//设置窗口背景西颜色为黑色
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	//指定多变形的阴影模式为平面阴暗模式
	glShadeModel(GL_FLAT);

}
void ChangeSize(int w, int h)
{
	if (h == 0)
		h = 1;

	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();


	if (w <= h)
	{
		glOrtho(-100.0f, 100.0f, -100.0f*h / w, 100.0f*h / w, -100.0f, 100.0f);
	}
	else
	{
		glOrtho(-100.0f*w / h, 100.0f*w / h, -100.0f, 100.0f, -100.0f, 100.0f);
	}
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void RenderScene(void)
{
	//清除颜色及深度缓冲区
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


	//是否开启设度模式
	if (bDepth)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);

	//是否打开剔除
	if (bCull)
		glEnable(GL_CULL_FACE);
	else
		glDisable(GL_CULL_FACE);

	//旋转图形
	glPushMatrix();

	//角度正负决定是顺逆时针
	glRotatef(xRot,1.0f,0.0f,0.0f); //使整个场景绕着x轴旋转  
	glRotatef(yRot, 0.0, 1.0, 0.0f);//使整个场景绕着y轴旋转  


	//指定顺时针绕法的多变形为正多变边形正面
	//glFrontFace(GL_CW);

	//绘制三菱锥的三个棱面
    //他们的颜色分别为红、绿、蓝
	glBegin(GL_TRIANGLE_FAN);

	glVertex3f(0.0, 0.0,80);
	glVertex3f(0.0, 50.0,0.0);


	glColor3f(1.0,0.0,0.0);  //红色
	glVertex3f(50.0,-50.0,0.0);

	glColor3f(0.0f, 1.0f, 0.0); //绿色
	glVertex3f(-50.0,-50.0,0.0);


	glColor3f(0.0f,0.0f,1.0f); //蓝色
	glVertex3f(0.0,50.0,0.0);
	
	glEnd();


	//绘制三菱锥的地面,其颜色为黄色
	glBegin(GL_TRIANGLE_FAN);
	glVertex3f(0.0,50.0,0.0);
	glVertex3f(50.0,-50.0,0.0);
	glColor3f(1.0,1.0,0.0);  //黄色
	glVertex3f(-50.0,-50.0,0.0);
	glEnd();


	glPopMatrix();
	glutSwapBuffers();  //刷新命令缓冲区
}

void SpecialKeys(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)    xRot -= 5.0f;
	if (key == GLUT_KEY_DOWN)  xRot += 5.0f;
	if (key == GLUT_KEY_LEFT)  yRot -= 5.0f;
	if (key == GLUT_KEY_RIGHT) yRot += 5.0f;


	//结合glPushMatrix()和glPopMatrix()绘图模式理解旋转
	// 首先,glPushMateix记住来的绘图坐标(起点)
	//glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	//glRotatef(yRot, 0.0f, 1.0f, 0.0f);
	//然后旋转相应的坐标后绘制图形
	//glPopMatrix 回到了坐标原来的位置(起点)

	printf("%lfn", yRot);
	if (xRot >= 360.0f)   xRot = 0.0f;
	if (xRot < -1.0f)    xRot=355.0f;
	if (yRot >= 360.0f)    yRot = 0.0f;
	if (yRot < -1.0f)    yRot = 355.0f;


	//刷新窗口  强制
	glutPostRedisplay();
}
void ProcessMenu(int value)
{
	switch (value)
	{
	case 1:bDepth = !bDepth;
		break;
	case 2:bCull = !bCull;
		break;
	default:
		break;
	}
	//强制刷新
	glutPostRedisplay();
}

int main(int argc, char *argv[])
{

	//initialize the GLUT library  
	//初始化GLUT库
	glutInit(&argc, argv);


	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutCreateWindow("三菱锥");

	//回调函数
	glutDisplayFunc(RenderScene);
	glutReshapeFunc(ChangeSize);

	//设置特殊键盘相应回调函数
	glutSpecialFunc(SpecialKeys);
	//void glutSpecialFunc(void(*func)(int key,int x,int y));
	//special函数第一个关键字是键盘的值,  x,y是获取鼠标点击的坐标
	// sets the special keyboard callback for the current window
	//the special keyboared callback is triggered when keyboard function or 
	//directional keys are pressed



	//创建一个菜单
	glutCreateMenu(ProcessMenu);
	glutAddMenuEntry("深度测试",1);
	glutAddMenuEntry("剔除背面",2);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	SetupRC();
	glutMainLoop();
	return 0;
}


</span>

程序一开始运行的图片结果如下:


通过旋转和使用深度测试功能结果如下:






本次学习知识点:

在旋转的过程中,红色的棱镜始终不能显示出来,这是因为红色的棱面是最先绘制的,它总是被后面绘制的绿色,

蓝色或黄色的多边形所遮挡,要改变这种状况就需要启用深度测试。
1.  深度测试 (恢复看不到的区域)
 在绘制图形的过程中,有时一个物体的一部分会被其前方的物体挡住(从观察者的角度看),如果这是这个物体在档在其前面的物体绘制完成之后绘制,那么屏幕中显示的图形将不是我们所希望的,即后面的物体挡住了前面的物体。
只需启用一项称为深度测试的功能就可以解决这一问题。


    启动深度测试: 调用  glEnable(GL_DEPTH_TEST);

    关闭深度测试: 调用 glDisable(GL_DEPTH_TEST);

深度测试是一种移除被挡住表面的有效技术,它的过程是:在绘制一个像素时,会给他分配一个值(称为z值),这个值表示它与观察者的距离。然后,如果需要在同一个位置上绘制另一个像素,将比较新像素和已经保存的该位置的像素的z值。如果新像素的z的值比较大,即它离观察者更近因而在原来那个像素的前面,原来的像素就会被新像素挡住。这一操作在内部有深度缓冲区完成。

为了使深度缓冲区正常完成深度测试功能,每次渲染场景时,必须先清除深度缓冲区:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)


2.隐藏表面

启用深度测试之后,我们得到良好的视觉效果,但是还是付出了一些性能代价,因为每个画出的像素都必须与先前像素的z值比较。但是如果我们知道某些表面无论如何也不必画出,我们可以将其指出,这种技术称为"剔除",这种技术可以将已知永远看不到的几何图形消除掉,这样可以显著的改善性能。
那么哪些表面时永远看不到的呢?最常见的例子就是封闭物体的内部表面。一种称为回溯的技术可以消除表面的背面,通过

                glEnable/glDisable(GL_CULL_FACE)

来实现。启用剔除技术后,我们发现三棱锥的底面消失了,这是因为在绘制的过程中,我们都使用了顺时针绕法的多边形正面,但这样底面的正面正对着三棱锥的内部,故此启用剔除技术后把底面剔出掉了,要改变这种状况,可以在绘制三棱锥的底面前调用函数

                  glFrontFace(GL_CCW);

最后

以上就是傻傻小蝴蝶为你收集整理的OpenGL(二)图形绘制之平面多面体的绘制的全部内容,希望文章能够帮你解决OpenGL(二)图形绘制之平面多面体的绘制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部