重新自學(xué)學(xué)習(xí)openGL 之性能優(yōu)化面剔除

嘗試在腦子中想象一個(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);
}

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


面剔除
OpenGLZeroStudyDemo(12)-高級(jí)Opengl-面剔除

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容