嘗試在腦子中想象一個(gè)3D立方體,數(shù)數(shù)你從任意方向最多能同時(shí)看到幾個(gè)面。如果你的想象力不是過于豐富了,你應(yīng)該能得出最大的面數(shù)是3。你可以從任意位置和任意方向看向這個(gè)球體,但你永遠(yuǎn)不能看到3個(gè)以上的面。所以我們?yōu)槭裁匆速M(fèi)時(shí)間繪制我們不能看見的那3個(gè)面呢?如果我們能夠以某種方式丟棄這幾個(gè)看不見的面,我們能省下超過50%的片段著色器執(zhí)行數(shù)!
我說的是超過50%而不是50%,因?yàn)閺奶囟ń嵌葋砜吹脑捴荒芸匆?個(gè)甚至是1個(gè)面。在這種情況下,我們就能省下超過50%了。
這是一個(gè)很好的主意,但我們?nèi)杂幸粋€(gè)問題需要解決:我們?nèi)绾沃酪粋€(gè)物體的某一個(gè)面不能從觀察者視角看到呢?
如果我們想象任何一個(gè)閉合形狀,它的每一個(gè)面都有兩側(cè),每一側(cè)要么面向用戶,要么背對(duì)用戶。如果我們能夠只繪制面向觀察者的面呢?
這正是面剔除(Face Culling)所做的。OpenGL能夠檢查所有面向(Front Facing)觀察者的面,并渲染它們,而丟棄那些背向(Back Facing)的面,節(jié)省我們很多的片段著色器調(diào)用(它們的開銷很大?。?。但我們?nèi)砸嬖VOpenGL哪些面是正向面(Front Face),哪些面是背向面(Back Face)。OpenGL使用了一個(gè)很聰明的技巧,分析頂點(diǎn)數(shù)據(jù)的環(huán)繞順序(Winding Order)。
環(huán)繞順序
當(dāng)我們定義一組三角形頂點(diǎn)時(shí),我們會(huì)以特定的環(huán)繞順序來定義它們,可能是順時(shí)針(Clockwise)的,也可能是逆時(shí)針(Counter-clockwise)的。每個(gè)三角形由3個(gè)頂點(diǎn)所組成,我們會(huì)從三角形中間來看,為這3個(gè)頂點(diǎn)設(shè)定一個(gè)環(huán)繞順序。

可以看到,我們首先定義了頂點(diǎn)1,之后我們可以選擇定義頂點(diǎn)2或者頂點(diǎn)3,這個(gè)選擇將定義了這個(gè)三角形的環(huán)繞順序。下面的代碼展示了這點(diǎn):
float vertices[] = {
// 順時(shí)針
vertices[0], // 頂點(diǎn)1
vertices[1], // 頂點(diǎn)2
vertices[2], // 頂點(diǎn)3
// 逆時(shí)針
vertices[0], // 頂點(diǎn)1
vertices[2], // 頂點(diǎn)3
vertices[1] // 頂點(diǎn)2
};
每組組成三角形圖元的三個(gè)頂點(diǎn)就包含了一個(gè)環(huán)繞順序。OpenGL在渲染圖元的時(shí)候?qū)⑹褂眠@個(gè)信息來決定一個(gè)三角形是一個(gè)正向三角形還是背向三角形。默認(rèn)情況下,逆時(shí)針頂點(diǎn)所定義的三角形將會(huì)被處理為正向三角形。
當(dāng)你定義頂點(diǎn)順序的時(shí)候,你應(yīng)該想象對(duì)應(yīng)的三角形是面向你的,所以你
定義的三角形從正面看去應(yīng)該是逆時(shí)針的。這樣定義頂點(diǎn)很棒的一點(diǎn)是,實(shí)際的環(huán)繞順序是在光柵化階段進(jìn)行的,也就是頂點(diǎn)著色器運(yùn)行之后。這些頂點(diǎn)就是從觀察者視角所見的了。
觀察者所面向的所有三角形頂點(diǎn)就是我們所指定的正確環(huán)繞順序了,而立方體另一面的三角形頂點(diǎn)則是以相反的環(huán)繞順序所渲染的。這樣的結(jié)果就是,我們所面向的三角形將會(huì)是正向三角形,而背面的三角形則是背向三角形。下面這張圖顯示了這個(gè)效果:

在頂點(diǎn)數(shù)據(jù)中,我們將兩個(gè)三角形都以逆時(shí)針順序定義(正面的三角形是1、2、3,背面的三角形也是1、2、3(如果我們從正面看這個(gè)三角形的話))。然而,如果從觀察者當(dāng)前視角使用1、2、3的順序來繪制的話,
從觀察者的方向來看,背面的三角形將會(huì)是以順時(shí)針順序渲染的。雖然背面的三角形是以逆時(shí)針定義的,它現(xiàn)在是以順時(shí)針順序渲染的了。這正是我們想要剔除(Cull,丟棄)的不可見面了!
在頂點(diǎn)數(shù)據(jù)中,我們定義的是兩個(gè)逆時(shí)針順序的三角形。然而,從觀察者的方面看,后面的三角形是順時(shí)針的,如果我們?nèi)砸?、2、3的順序以觀察者當(dāng)面的視野看的話。即使我們以逆時(shí)針順序定義后面的三角形,它現(xiàn)在還是變?yōu)轫槙r(shí)針。它正是我們打算剔除(丟棄)的不可見的面!
面剔除
在本節(jié)的開頭我們就說過,OpenGL能夠丟棄那些渲染為背向三角形的三角形圖元。既然已經(jīng)知道如何設(shè)置頂點(diǎn)的環(huán)繞順序了,我們就可以使用OpenGL的面剔除選項(xiàng)了,它默認(rèn)是禁用狀態(tài)的。
要想啟用面剔除,我們只需要啟用OpenGL的GL_CULL_FACE選項(xiàng):
glEnable(GL_CULL_FACE);
從這一句代碼之后,所有背向面都將被丟棄(嘗試飛進(jìn)立方體內(nèi)部,看看所有的內(nèi)面是不是都被丟棄了)。目前我們?cè)阡秩酒蔚臅r(shí)候能夠節(jié)省50%以上的性能,但注意這只對(duì)像立方體這樣的封閉形狀有效。當(dāng)我們想要繪制上篇博客中的草時(shí),我們必須要再次禁用面剔除,因?yàn)樗鼈兊恼蛎婧捅诚蛎娑紤?yīng)該是可見的。
就是面剔除只對(duì)立方體有效.平面無效
OpenGL允許我們改變需要剔除的面的類型。如果我們只想剔除正向面而不是背向面會(huì)怎么樣?我們可以調(diào)用glCullFace來定義這一行為:
glCullFace(GL_FRONT);
glCullFace函數(shù)有三個(gè)可用的選項(xiàng):
- GL_BACK:只剔除背向面。
- GL_FRONT:只剔除正向面。
- GL_FRONT_AND_BACK:剔除正向面和背向面。
glCullFace的初始值是GL_BACK。除了需要剔除的面之外,我們也可以通過調(diào)用glFrontFace,告訴OpenGL我們希望將順時(shí)針的面(而不是逆時(shí)針的面)定義為正向面:
glFrontFace(GL_CCW);
默認(rèn)值是 GL_CCW ,它代表的是逆時(shí)針的環(huán)繞順序,另一個(gè)選項(xiàng)是 GL_CW ,它(顯然)代表的是順時(shí)針順序。
demo演示
我們繪制一個(gè)立方體,立方體沿著x,y軸旋轉(zhuǎn)30度
基本代碼
#import "FaceCullingDefaultViewController.h"
#import "FaceCullingDefaultBindObject.h"
#import "CubeManager.h"
float FCD_planeVertices[] = {
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
};
@interface FaceCullingDefaultViewController ()
@property (nonatomic ,strong) Vertex * vertex;
@property (nonatomic ,strong) Vertex * planeVertex ;
@property (nonatomic ,strong) TextureUnit * cubeUnit ;
@property (nonatomic ,strong) TextureUnit * floorUnit ;
@end
@implementation FaceCullingDefaultViewController
-(void)initSubObject{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
self.bindObject = [FaceCullingDefaultBindObject new];
}
-(void)loadVertex{
self.vertex= [Vertex new];
int vertexNum =[CubeManager getTextureNormalVertexNum];
[self.vertex allocVertexNum:vertexNum andEachVertexNum:5];
for (int i=0; i<vertexNum; i++) {
float onevertex[5];
for (int j=0; j<3; j++) {
onevertex[j]=[CubeManager getTextureNormalVertexs][i*8+j];
}
for (int j=0; j<2; j++) {
onevertex[j+3]=[CubeManager getTextureNormalVertexs][i*8+6+j];
}
[self.vertex setVertex:onevertex index:i];
}
[self.vertex bindBufferWithUsage:GL_STATIC_DRAW];
self.planeVertex= [Vertex new];
vertexNum =6;
[self.planeVertex allocVertexNum:vertexNum andEachVertexNum:5];
for (int i=0; i<vertexNum; i++) {
float onevertex[5];
for (int j=0; j<3; j++) {
onevertex[j]=FCD_planeVertices[i*5+j];
}
for (int j=0; j<2; j++) {
onevertex[j+3]=FCD_planeVertices[i*5+3+j];
}
[self.planeVertex setVertex:onevertex index:i];
}
[self.planeVertex bindBufferWithUsage:GL_STATIC_DRAW];
}
//-(void)createShader{
// [super createShader];
// self.stencilShader = [Shader new];
// [self.stencilShader compileLinkSuccessShaderName:@"BlendColor" completeBlock:^(GLuint program) {
// [self.bindObjectColor BindAttribLocation:program];
// }];
// [self.bindObjectColor setUniformLocation:self.stencilShader.program];
//}
-(void)createTextureUnit{
self.cubeUnit = [TextureUnit new];
[self.cubeUnit setImage:[UIImage imageNamed:@"marble.jpg"] IntoTextureUnit:GL_TEXTURE0 andConfigTextureUnit:nil];
self.floorUnit = [TextureUnit new];
[self.floorUnit setImage:[UIImage imageNamed:@"metal.png"] IntoTextureUnit:GL_TEXTURE1 andConfigTextureUnit:^{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}];
}
-(void)_bindViewMatrix4:(GLBaseBindObject*)bindObject{
GLKMatrix4 viewMatrix =
GLKMatrix4MakeLookAt(
0.0, 0.0, 3.0, // Eye position
0.0, 0.0, 0.0, // Look-at position
0.0, 1.0, 0.0); // Up direction
glUniformMatrix4fv(bindObject->uniforms[FCD_uniform_view], 1, 0,viewMatrix.m);
}
-(void)_bindProjectionMatrix4:(GLBaseBindObject*)bindObject{
GLfloat aspectRatio= CGRectGetWidth([UIScreen mainScreen].bounds) / CGRectGetHeight([UIScreen mainScreen].bounds);
GLKMatrix4 projectionMatrix =
GLKMatrix4MakePerspective(
GLKMathDegreesToRadians(100.0f),
aspectRatio,
0.1f,
100.0f);
glUniformMatrix4fv(bindObject->uniforms[FCD_uniform_projection], 1, 0,projectionMatrix.m);
}
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
/// 模板測(cè)試雖然開啟了. 但是不起作用.
glClearStencil(0);
glClearColor(1,0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLKMatrix4 cubeMode1 =[self _getModeMatrix4Location:GLKVector3Make(0.0f, 0.0f, 1.0f)];
cubeMode1 = GLKMatrix4Rotate(cubeMode1, 30*M_PI/180.0, 1, 1, 0);
[self.shader use];
[self _bindViewMatrix4:self.bindObject];
[self _bindProjectionMatrix4:self.bindObject];
[self _drawFloor:self.bindObject];
[self _drawCubeMode:cubeMode1 bindObject:self.bindObject];
}
-(GLKMatrix4)_getModeMatrix4Location:(GLKVector3)location{
GLKMatrix4 mode = GLKMatrix4Identity;
mode = GLKMatrix4TranslateWithVector3(mode, location);
// mode = GLKMatrix4Rotate(mode, 30*M_PI/180.0, 0, 1, 0);
return mode;
}
-(void)_drawCubeMode:(GLKMatrix4)mode bindObject:(GLBaseBindObject*)bindObject{
glUniformMatrix4fv(bindObject->uniforms[FCD_uniform_model], 1, 0,mode.m);
[self.cubeUnit bindtextureUnitLocationAndShaderUniformSamplerLocation:bindObject->uniforms[FCD_uniform_Texture]];
[self.vertex enableVertexInVertexAttrib:FCD_aPos numberOfCoordinates:3 attribOffset:0];
[self.vertex enableVertexInVertexAttrib:FCD_aTexCoords numberOfCoordinates:2 attribOffset:sizeof(float)*3];
[self.vertex drawVertexWithMode:GL_TRIANGLES startVertexIndex:0 numberOfVertices:[CubeManager getTextureNormalVertexNum]];
}
-(void)_drawFloor:(GLBaseBindObject*)bindObject{
GLKMatrix4 mode = GLKMatrix4Identity;
glUniformMatrix4fv(bindObject->uniforms[FCD_uniform_model], 1, 0,mode.m);
[self.floorUnit bindtextureUnitLocationAndShaderUniformSamplerLocation:bindObject->uniforms[FCD_uniform_Texture]];
[self.planeVertex enableVertexInVertexAttrib:FCD_aPos numberOfCoordinates:3 attribOffset:0];
[self.planeVertex enableVertexInVertexAttrib:FCD_aTexCoords numberOfCoordinates:2 attribOffset:sizeof(float)*3];
[self.planeVertex drawVertexWithMode:GL_TRIANGLES startVertexIndex:0 numberOfVertices:6];
}
@end
shader
precision mediump float;
attribute vec3 aPos;
//attribute vec3 aNormal;
attribute vec2 aTexCoords;
varying vec2 vTexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
vTexCoords = aTexCoords;
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
precision mediump float;
varying vec2 vTexCoords;
uniform sampler2D uTexture;
void main()
{
vec4 textureColor = texture2D(uTexture, vTexCoords);
gl_FragColor = textureColor;
}
#import "GLBaseBindObject.h"
NS_ASSUME_NONNULL_BEGIN
// Attribute identifiers
typedef enum {
FCD_aPos,
// aNormal,
FCD_aTexCoords,
} FCD_BaseBindAttribLocation;
typedef union {
struct{
GLKVector3 aPos;
// GLKVector3 aNormal;
GLKVector2 aTexCoords;
};
float a[5];
}FCD_BindAtt;
typedef enum {
FCD_uniform_model,
FCD_uniform_view,
FCD_uniform_projection,
FCD_uniform_Texture
} FCD_UniformLocation;
@interface FaceCullingDefaultBindObject : GLBaseBindObject
@end
NS_ASSUME_NONNULL_END
#import "FaceCullingDefaultBindObject.h"
@implementation FaceCullingDefaultBindObject
-(void)BindAttribLocation:(GLuint)program{
glBindAttribLocation(program, FCD_aPos, "aPos");
glBindAttribLocation(program, FCD_aTexCoords, "aTexCoords");
}
-(void)setUniformLocation:(GLuint)program{
self->uniforms[FCD_uniform_model] = glGetUniformLocation(program, "model");
self->uniforms[FCD_uniform_view] = glGetUniformLocation(program, "view");
self->uniforms[FCD_uniform_projection] = glGetUniformLocation(program, "projection");
self->uniforms[FCD_uniform_Texture] = glGetUniformLocation(program, "uTexture");
}
-(NSString *)getShaderName{
return @"FaceCullingDefault";
}
@end
正常渲染立方體的頂點(diǎn)
float textureNormalvertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
選入的立方體結(jié)果是

沒有頂點(diǎn)順序的立方體開啟剔除面
#import "FaceCullingOutOrderViewController.h"
@interface FaceCullingOutOrderViewController ()
@end
@implementation FaceCullingOutOrderViewController
-(void)initSubObject{
[super initSubObject];
//開啟剔除面
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
}
@end
#import "GLBaseViewController.h"
#import "FaceCullingDefaultViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface FaceCullingOutOrderViewController : FaceCullingDefaultViewController
@end
NS_ASSUME_NONNULL_END

我們發(fā)現(xiàn),要是立方體的頂點(diǎn)沒有按照一定順序排列,那么剔除面的結(jié)果是不好預(yù)測(cè)的.
有順序的剔除面
頂點(diǎn)是逆時(shí)針排列
頂點(diǎn)坐標(biāo)如下
unsigned int cubeFaceCullingVertuceNum = 36;
float cubeFaceCullingVertices[] = {
// Back face
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // Bottom-left
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // bottom-left
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // top-left
// Front face
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // top-right
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // top-right
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // top-left
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
// Left face
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-right
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-left
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-left
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-left
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-right
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-right
// Right face
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-left
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-right
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-right
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-left
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
// Bottom face
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // top-right
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, // top-left
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-left
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-left
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-right
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // top-right
// Top face
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // top-left
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // top-left
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f // bottom-left
};
開啟剔除面結(jié)果
-(void)initSubObject{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
self.bindObject = [FaceCullingOrderFrontBindObject new];
}

剔除前面的面
-(void)initSubObject{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
self.bindObject = [FaceCullingOrderFrontBindObject new];
glCullFace(GL_FRONT);
}

剔除后面的面
-(void)initSubObject{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
self.bindObject = [FaceCullingOrderFrontBindObject new];
glCullFace(GL_BACK);
}

默認(rèn)是開啟剔除后面的面的
剔除面順序
我們計(jì)算剔除面默認(rèn)是逆時(shí)針的,改變成順時(shí)針的結(jié)果是啥樣子的呢?
-(void)initSubObject{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
self.bindObject = [FaceCullingOrderFrontBindObject new];
glCullFace(GL_BACK);
glFrontFace(GL_CW);
}

順序改變,剔除的面正好相反.