OpenGL背面剔除

来源:互联网 发布:js 字符串中的换行 编辑:程序博客网 时间:2024/04/28 02:27

背面剔除 就是对几何体的背面,我们看不到的三角形进行剔除,以便提高性能

我们先来看一个没有背面剔除的例子

这是一个类似于游泳圈的模型,稍微的对其旋转了一下,从侧面看到的效果如下图:



我们看到有一些黑色的线条 这是因为在没有开启 背面剔除 模式的情况下,三角形的排序可能会出现混乱,从而造成这种现象。

我们来看看怎么来写这个例子

工程的创建在前面已经讲过了

首先 头文件部分

<pre name="code" class="cpp">#include <GLTools.h>// OpenGL toolkit#include <GLMatrixStack.h>#include <GLFrame.h>#include <GLFrustum.h>#include <GLGeometryTransform.h>#include <math.h>#define FREEGLUT_STATI#include <GL/glut.h>

全局变量部分

GLFrame             viewFrame;GLFrustum           viewFrustum;//视景体GLTriangleBatch     torusBatch;GLMatrixStack       modelViewMatix; //模型视图矩阵GLMatrixStack       projectionMatrix; //投影矩阵GLGeometryTransform transformPipeline;//几何变换管线GLShaderManager     shaderManager;


main函数,几乎和前面没有区别 只是多了一行 用来检测键盘方向键的按下,从而旋转泳圈模型的

<pre name="code" class="cpp">int main(int argc, char* argv[]){    //设置当前工作目录      gltSetWorkingDirectory(argv[0]);      //初始化GLUT库      glutInit(&argc, argv);       //告诉GLUT在创建窗口时要使用哪种类型的窗口显示模式,这里只简单的设置为RGBA颜色模式,双缓冲模式      //双缓冲模式就是图形先渲染到后台缓冲区,然后再调用glutSwapBuffers()一起渲染到前台缓冲区      glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);      //要创建的窗口大小      glutInitWindowSize(800, 600);      //要创建的窗口标题      glutCreateWindow("Primitices");      //窗口大小改变时的回调函数      glutReshapeFunc(ChangeSize);      //渲染的回调函数      glutDisplayFunc(RenderScene);      //检测键盘方向键按下的回调函数    glutSpecialFunc(SpecialKeys);    其中ChangeSize和RenderScene函数稍后再讲      //初始化GLEW库,这个库被封装在GLTools中,主要调用OPenGL的一些接口      GLenum err = glewInit();      if (GLEW_OK != err) {          fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));          return 1;      }      //初始化函数,用于创建渲染环境,初始化数据等,这个函数在后面实现      SetupRC();      //开始主消息循环      glutMainLoop();      return 0;}

初始化函数 SetupRC()

void SetupRC(){    // Black background    glClearColor(0.3f, 0.3f, 0.3f, 1.0f );    //初始化着色器管理类    shaderManager.InitializeStockShaders();    //把模型延Z轴的负方向移动7个单位    viewFrame.MoveForward(7.0f);    // gltMakeTorus函数会创建一个泳圈模型的数据,并保存在torusBatch中 随后我们调用torusBatch.Draw() 即可绘制出泳圈模型    gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);//设置点的大小    glPointSize(4.0f);}

//下面是窗口改变的回调函数ChangeSize

void ChangeSize(int w, int h){    // Prevent a divide by zero    if(h == 0)h = 1;    // 设置视口大小    glViewport(0, 0, w, h);//创建投影矩阵,并将它载入到投影矩阵堆栈中    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());//把模型视图矩阵 和 投影矩阵 设置到管理管线的对象transformPipeline中 以便对模型视图矩阵 和 投影矩阵 进行管理    transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);}

//下面是渲染函数 RenderScene

void RenderScene(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 开启背面剔除glEnable(GL_CULL_FACE);//glDisable(GL_CULL_FACE);//设置模型视图矩阵modelViewMatix.PushMatrix(viewFrame);//设置着色器    GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);    //绘制泳圈模型torusBatch.Draw();//回复模型视图矩阵modelViewMatix.PopMatrix();glutSwapBuffers();}

//下面是响应键盘按键的函数SpecialKeys

void SpecialKeys(int key, int x, int y){//其中RotateWorld标示把角度转换为弧度//这里把旋转矩阵放在对象viewFrame中 在渲染函数 RenderScene函数 中 //通过modelViewMatix.PushMatrix(viewFrame) 来使用该旋转矩阵//绕x转-5度if(key == GLUT_KEY_UP)viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);//绕x转5度if(key == GLUT_KEY_DOWN)viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);//绕y转-5度if(key == GLUT_KEY_LEFT)viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);//绕y转5度if(key == GLUT_KEY_RIGHT)viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);// 刷新窗口glutPostRedisplay();}


大家注意到 在渲染函数RenderScene中有这样一句

// 开启背面剔除glEnable(GL_CULL_FACE);

这样就开启了背面剔除功能 关闭背面剔除函数

glDisable(GL_CULL_FACE);

开启背面剔除 效果如下图


不在有黑色的线条了





0 0