[OpenGL]图形的绘制——多边形面

//常见的平面多面体:平行多面体,球体,圆环,正四面体,三棱锥 
//三棱锥的绘制
#include <gl/glut.h>

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

bool bDepth =false;//深度测试开关
bool bCull = false;//剔除开关

//初始化窗口
void SetupRC()
{
    //设置窗口背景颜色为黑色
    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()
{
    //清除颜色及深度缓冲区
    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.0f,1.0f,0.0f);//使整个场景绕着y轴旋转

    //指定顺时针绕法的多边形为多边形正面
    glFrontFace(GL_CW);
 
    //绘制三棱锥的三个棱面,它的颜色分别为红,绿,蓝
    glBegin(GL_TRIANGLE_FAN);
    glVertex3f(0.0f,0.0f,80.0f);
    glVertex3f(0,50,0);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(50,-50,0);
    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f(-50,-50,0); 
    glColor3f(0.0f,0.0f,1.0f);
    glVertex3f(0,50,0); 
    glEnd();

    //绘制三棱锥的底面,它的颜色黄色
    glBegin(GL_TRIANGLE_FAN);
    glColor3f(0.0f,50.0f,0.0f);
    glVertex3f(50,-50,0);
    glColor3f(1.0f,1.0f,0.0f);
    glVertex3f(-50,-50,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;

    if (xRot > 356.0f) 
        xRot = 0.0f; 
    if (xRot < -1.0f) 
        xRot = 355.0f; 
    if (yRot > 356.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();
}
void main()
{
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutCreateWindow("三棱锥演示");
    glutDisplayFunc(RenderScene);
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);//设置特殊键响应回调函数
 
    //创建右键菜单
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("深度测试",1);
    glutAddMenuEntry("剔除背面",2);

    //将创建的菜单与右键关联,即把菜单设置为右键弹出式菜单
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    SetupRC();
    glutMainLoop();
}
/* 在旋转的过程中,红色的棱镜始终不能显示出来,这是因为红色的棱面是最先绘制的,它总是被后面绘制的绿色,蓝色或黄色的多边形所遮挡,要改变这种状况就需要启用深度测试。
1.深度测试
在绘制图形的过程中,有时一个物体的一部分会被其前方的物体挡住(从观察者的角度看),如果这是这个物体在档在其前面的物体绘制完成之后绘制,那么屏幕中显示的图形将不是我们所希望的,即后面的物体挡住了前面的物体。
只需启用一项称为深度测试的功能就可以解决这一问题,深度测试是一种移除被挡住表面的有效技术,它的过程是:在绘制一个像素时,会给他分配一个值(称为z值),这个值表示它与观察者的距离。然后,如果需要在同一个位置上绘制另一个像素,将比较新像素和已经保存的该位置的像素的z值。如果新像素的z的值比较大,即它离观察者更近因而在原来那个像素的前面,原来的像素就会被新像素挡住。这一操作在内部有深度缓冲区完成。
为了使深度缓冲区正常完成深度测试功能,子啊每次渲染场景时,必须先清除深度缓冲区:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
2.隐藏表面
启用深度测试之后,我们得到良好的视觉效果,但是还是付出了一些性能代价,因为每个画出的像素都必须与先前像素的z值比较。但是如果我们知道某些表面无论如何也不必画出,我们可以将其指出,这种技术称为"剔除",这种技术可以将已知永远看不到的几何图形消除掉,这样可以显著的改善性能。
那么哪些表面时永远看不到的呢?最常见的例子就是封闭物体的内部表面。一种称为回溯的技术可以消除表面的背面,通过glEnable/glDisable(GL_CULL_FACE)来实现。启用剔除技术后,我们发现三棱锥的底面消失了,这是因为在绘制的过程中,我们都使用了顺时针绕法的多边形正面,但这样底面的正面正对着三棱锥的内部,故此启用剔除技术后把底面剔出掉了,要改变这种状况,可以在绘制三棱锥的底面前调用函数glFrontFace(GL_CCW);
*/

效果图:[OpenGL]图形的绘制——多边形面

[OpenGL]图形的绘制——多边形面

上一篇:01我为什么学Unity3d


下一篇:[Unity3d]小地图的制作