2013-12-21 42 views
1

我想呈現兩個立方體與紋理(「身體」和「頭」)。有一個包含所有立方體面的紋理地圖集。爲了達到這個目的,我創建了一個類來封裝所有繪製立方體的代碼:MSTexturedCubeiOS的OpenGLES渲染多個對象時的奇怪行爲

// In MSTexturedCube.h 
#import <Foundation/Foundation.h> 
#import <GLKit/GLKit.h> 

@interface MSTexturedCube : NSObject { 
    GLKVector3 _vertices[8]; 
    GLKVector3 _triangleVertices[36]; 
    GLKVector2 _textureVertices[36]; 
} 

@property (nonatomic, assign) float xRotationAngle; 
@property (nonatomic, assign) float yRotationAngle; 
@property (nonatomic, assign) GLKVector3 scale;    // x, y, z scale 
@property (nonatomic, assign) GLKVector3 translation; // x, y, z translation 

- (id)initWithTexture:(GLKTextureInfo *)textureInfo vertexData:(GLKVector2[36])textureVertexData; 
- (id)initWithTexture:(GLKTextureInfo *)textureInfo frontFaceCoords:(GLKVector2[4])front right:(GLKVector2[4])right back:(GLKVector2[4])back left:(GLKVector2[4])left top:(GLKVector2[4])top bottom:(GLKVector2[4])bottom; 

- (void)draw; 

- (void)setVertices:(GLKVector3[8])verticesArray; 

@end 



// In MSTexturedCube.m 
#import "MSTexturedCube.h" 

static int vertexIndices[36] = { 
    // Front 
    0, 1, 2, 
    0, 2, 3, 
    // Right 
    1, 5, 6, 
    1, 6, 2, 
    // Back 
    5, 4, 7, 
    5, 7, 6, 
    // Left 
    4, 0, 3, 
    4, 3, 7, 
    // Top 
    3, 2, 6, 
    3, 6, 7, 
    // Bottom 
    4, 5, 1, 
    4, 1, 0, 
}; 

@interface MSTexturedCube() 

@property (nonatomic, strong) GLKBaseEffect *effect; 
@property (nonatomic, strong) GLKTextureInfo *textureInfo; 

- (void)setupOpenGL; 

@end 

@implementation MSTexturedCube 

@synthesize effect = _effect; 
@synthesize textureInfo = _textureInfo; 

@synthesize xRotationAngle = _xRotationAngle; 
@synthesize yRotationAngle = _yRotationAngle; 
@synthesize scale = _scale; 
@synthesize translation = _translation; 

// Init methods 
... 

- (void)draw { 
    // Create matrices 
    GLKMatrix4 yRotation = GLKMatrix4MakeYRotation(self.yRotationAngle); 
    GLKMatrix4 xRotation = GLKMatrix4MakeXRotation(self.xRotationAngle); 
    GLKMatrix4 scale = GLKMatrix4MakeScale(self.scale.x, self.scale.y, self.scale.z); 
    GLKMatrix4 translation = GLKMatrix4MakeTranslation(self.translation.x, self.translation.y, self.translation.z); 

    GLKMatrix4 modelMatrix = GLKMatrix4Multiply(translation, GLKMatrix4Multiply(xRotation, GLKMatrix4Multiply(yRotation, scale))); 
    GLKMatrix4 viewMatrix = GLKMatrix4MakeLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix); 
    self.effect.transform.projectionMatrix = GLKMatrix4MakePerspective(0.25 * M_PI, 1.0, 2.0, 500.0); 

    // Set texture properties if a texture is set 
    if (self.textureInfo) { 
     self.effect.texture2d0.envMode = GLKTextureEnvModeReplace; 
     self.effect.texture2d0.target = GLKTextureTarget2D; 
     self.effect.texture2d0.name = self.textureInfo.name; 
    } 

    // Prepare the effect to draw after creating matrices 
    [self.effect prepareToDraw]; 

    // Set texture 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(self.textureInfo.target, self.textureInfo.name); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    // Set vertices 
    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, _triangleVertices); 

    // Set texture (if set) 
    if (self.textureInfo) { 
     glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
     glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, _textureVertices); 
    } 

    // Draw 
    glDrawArrays(GL_TRIANGLES, 0, 36); 

    // Disable arrays 
    glDisableVertexAttribArray(GLKVertexAttribPosition); 
    glDisableVertexAttribArray(GLKVertexAttribTexCoord0); 
} 

// Getters & setters 
... 

#pragma mark - Private methods 

- (void)setupOpenGL { 
    // Set vertices array 
    _vertices[0] = GLKVector3Make(-0.5, -0.5, 0.5); // Left bottom front 
    _vertices[1] = GLKVector3Make(0.5, -0.5, 0.5); // Right bottom front 
    _vertices[2] = GLKVector3Make(0.5, 0.5, 0.5); // Right top front 
    _vertices[3] = GLKVector3Make(-0.5, 0.5, 0.5); // Left top front 
    _vertices[4] = GLKVector3Make(-0.5, -0.5, -0.5); // Left bottom back 
    _vertices[5] = GLKVector3Make(0.5, -0.5, -0.5); // Right bottom back 
    _vertices[6] = GLKVector3Make(0.5, 0.5, -0.5); // Right top back 
    _vertices[7] = GLKVector3Make(-0.5, 0.5, -0.5); // Left top back 

    // Set the triangle vertices 
    for (int i = 0; i < 36; i++) { 
     _triangleVertices[i] = _vertices[vertexIndices[i]]; 
    } 

    self.effect = [[GLKBaseEffect alloc] init]; 
} 

在我GLKViewController子類,它實現了GLKViewDelegateGLKViewControllerDelegate,我創建了兩個MSTexturedCube對象,我有必要的頂點數據和紋理頂點數據初始化。在GLKViewDelegate我寫了這個功能:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 
    // Set background color 
    glClearColor(0.5, 0.5, 0.5, 1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 

    // Set properties 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_CULL_FACE); 

    [self.cubes makeObjectsPerformSelector:@selector(draw)]; 
} 

它完美,但有一個問題:當我旋轉視圖,立方體數組中的第二個對象呈現沒有任何問題,但第一個對象,即使它是更接近如果它具有下面的其他對象,則顯示爲絕對透明。如果它只有下面的背景,那麼渲染也是不透明的。 ¿我該如何解決這個問題,並使對象尊重Z順序?

+2

你甚至有深度緩衝區連接到你的幀緩衝區?當你做,你將必須清除它:'glClear(GL_COLOR_BUFFER_BIT)'應該是'glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)' –

+0

對不起,我非常非常新的OpenGLES(這是我的第一個應用程序,它使用它,我得到這個代碼結合不同的教程),我甚至不知道如何創建深度緩衝區並附加它。感謝您的幫助! – Garoal

+0

@MaticOblak我解決了它,但是感謝您的幫助!我不知道在評論前要搜索什麼! – Garoal

回答

1

我解決了我的問題。

我忘記了將我的GLView的drawableDepthFormat屬性設置爲GLKViewDrawableDepthFormat16來添加到我的EAGLContext深度緩衝區。

雖然沒有出現在的問題,我曾試圖以下兩行添加在GLView的委託方法,但他們什麼也沒做:

glDepthFunc(GL_LEQUAL); 
glClear(GL_DEPTH_BUFFER_BIT); 

很明顯,因爲緩衝沒有設置。當我設置GLKViewDrawableDepthFormat16並添加這兩行時,它可以很好地工作。