OpenGL背面剔除

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

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

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



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

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

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

首先 头文件部分

<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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值