2012-12-03 66 views
0

我在GLKit的幫助下顯示3個對象。但是,當我將紋理應用到這些對象時,所有三個紋理都只使用一個紋理。如何使用GLKit將不同的紋理應用於不同的對象?

我使用的代碼如下:

- (void)setUpGL{ 


    NSLog(@"i : %d, %d, %d",i,j,k); 
    firstPlayerScore = 0; 
    secondPlayerScore = 0; 
    staticBall = YES; 
    isSecondPlayer = NO; 

    self.boxPhysicsObjects = [NSMutableArray array]; 
    self.spherePhysicsObjects = [NSMutableArray array]; 
    self.immovableBoxPhysicsObjects = [NSMutableArray array]; 
    self.cylinderPhysicsObjects = [NSMutableArray array]; 
    self.secondPlayerCylinderPhysicsObjects = [NSMutableArray array]; 
    self.sphereArray = [NSMutableArray array]; 

    GLKView *view = (GLKView *)self.view; 
    NSAssert([view isKindOfClass:[GLKView class]],@"View controller's view is not a GLKView"); 

    view.drawableDepthFormat = GLKViewDrawableDepthFormat16; 
    view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
    [EAGLContext setCurrentContext:view.context]; 

    self.baseEffect = [[GLKBaseEffect alloc] init]; 

    glEnable(GL_CULL_FACE); 
    glEnable(GL_DEPTH_TEST); 

    //glGenBuffers(1, &_vertexBuffer); 
    //glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); 
    //glBufferData(GL_ARRAY_BUFFER, (i+j)*sizeof(float), sphereVerts, GL_STATIC_DRAW); 

    glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 

    self.baseEffect.light0.enabled = GL_TRUE; 
    self.baseEffect.light0.ambientColor = GLKVector4Make(0.7f, 0.7f, 0.7f, 1.0f); 


    [self addImmovableBoxPhysicsObjects]; 
    [self addRandomPhysicsSphereObject]; 
    //[self addFirstPlayerCylinderObject]; 
    //[self addSecondPlayerCylinderObject]; 
    //[self scheduleAddRandomPhysicsSphereObject:nil]; 

} 


- (void)addRandomPhysicsObject{ 
    if(random() % 2 == 0) 
    { 
     [self addRandomPhysicsBoxObject]; 
    } 
    else 
    { 
     [self addRandomPhysicsSphereObject]; 
    } 
} 

- (void)setUpBox{ 

    CGImageRef image = [[UIImage imageNamed:@"outUV2.PNG"] CGImage]; 
    textureInfo1 = [GLKTextureLoader textureWithCGImage:image options:nil error:NULL]; 
    self.baseEffect.texture2d0.name = textureInfo1.name; 
    self.baseEffect.texture2d0.enabled = YES; 

    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), final_meshVerts); 

    glEnableVertexAttribArray(GLKVertexAttribNormal); 
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), final_meshNormals); 

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), final_meshTexCoords); 

    //glDisableVertexAttribArray(GLKVertexAttribTexCoord0); 

} 

- (void)drawPhysicsBoxObjects{ 

    //self.baseEffect.texture2d0.target = textureInfo1.target; 

    PAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 

    GLKMatrix4 savedModelviewMatrix = self.baseEffect.transform.modelviewMatrix; 

    for(PPhysicsObject *currentObject in self.boxPhysicsObjects){ 
     self.baseEffect.transform.modelviewMatrix = 
     GLKMatrix4Multiply(savedModelviewMatrix,[appDelegate physicsTransformForObject:currentObject]); 

     [self.baseEffect prepareToDraw]; 

     glDrawArrays(GL_TRIANGLES, 0, final_meshNumVerts); 
    } 

    self.baseEffect.light0.diffuseColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f);// Alpha 

    for(PPhysicsObject *currentObject in self.immovableBoxPhysicsObjects){ 
     self.baseEffect.transform.modelviewMatrix = GLKMatrix4Multiply(savedModelviewMatrix, [appDelegate physicsTransformForObject:currentObject]); 
     [self.baseEffect prepareToDraw]; 

     glDrawArrays(GL_TRIANGLES,0, final_meshNumVerts); 
    } 

    self.baseEffect.transform.modelviewMatrix = savedModelviewMatrix; 
} 

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{ 
    static float a = 0; 
    a = a+0.1; 
    //NSLog(@"a : %f",a); 
    self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeLookAt(
                    0, 9.8, 10.0, // Eye position 
                    0.0, 1.0, 0.0, // Look-at position 
                    0.0, 1.0, 0.0); // Up direction 

    const GLfloat aspectRatio = (GLfloat)view.drawableWidth/(GLfloat)view.drawableHeight; 

    self.baseEffect.transform.projectionMatrix = 
    GLKMatrix4MakePerspective(GLKMathDegreesToRadians(35.0f),aspectRatio,0.2f,200.0f); // Far arbitrarily far enough to contain scene 

    self.baseEffect.light0.position = GLKVector4Make(0.6f, 1.0f, 0.4f, 0.0f); 

    [self.baseEffect prepareToDraw]; 

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

    [self drawPhysicsSphereObjects]; 
    [self drawPhysicsBoxObjects]; 
    //[self drawPhysicsCylinderObjects]; 
} 

- (void)addRandomPhysicsSphereObject{ 
    PAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 

    PPhysicsObject *anObject = nil; 

    if([self.spherePhysicsObjects count] < PMAX_NUMBER_BLOCKS) 
    { 
     NSLog(@"if"); 
     anObject = [[PPhysicsObject alloc] init]; 
    } 
    else 
    { 
     NSLog(@"else"); 
     anObject = [self.spherePhysicsObjects objectAtIndex:0]; 
     [self.spherePhysicsObjects removeObjectAtIndex:0]; 
    } 

    [self.spherePhysicsObjects addObject:anObject]; 

    [appDelegate physicsRegisterSphereObject:anObject 
            position:GLKVector3Make(0,3.5,-2) 
             mass:0.0f]; 
    [self setUpSphere]; 

    /*[appDelegate physicsSetVelocity:GLKVector3Make(
    random()/(float)RAND_MAX * 2.0f - 1.0f, 
    0.0f, 
    random() /(float)RAND_MAX * 2.0f - 1.0f) 
    forObject:anObject];*/ 
} 

- (void)setUpSphere{ 

    CGImageRef image = [[UIImage imageNamed:@"basketball.png"] CGImage]; 
    textureInfo = [GLKTextureLoader textureWithCGImage:image options:nil error:NULL]; 

    self.baseEffect.texture2d0.name = textureInfo.name; 
    self.baseEffect.texture2d0.enabled = YES; 

    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), newbasketballVerts); 

    glEnableVertexAttribArray(GLKVertexAttribNormal); 
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), newbasketballNormals); 

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), newbasketballTexCoords); 

    //glDisableVertexAttribArray(GLKVertexAttribTexCoord0); 

} 

- (void)drawPhysicsSphereObjects{ 
    NSLog(@"draw"); 
    /*static int x = 1; 
    if (x>20) { 
    x=20; 
    } 
    matrix = GLKMatrix4Identity; 
    matrix = GLKMatrix4MakeTranslation(0.1 * (x++), 0.0, 0.0);*/ 
    //self.baseEffect.texture2d0.target = textureInfo2.target; 

    PAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 

    GLKMatrix4 savedModelviewMatrix = self.baseEffect.transform.modelviewMatrix; 

    /*CGImageRef image = [[UIImage imageNamed:@"basketball.png"] CGImage]; 
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:image options:nil error:NULL]; 

    self.baseEffect.texture2d0.name = textureInfo.name; 
    self.baseEffect.texture2d0.target = textureInfo.target;*/ 

    self.baseEffect.light0.diffuseColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f); 
    //glVertexPointer(3, GL_FLOAT, 0, sphereVerts); 
    //glNormalPointer(GL_FLOAT, 0, sphereNormals); 
    //glTexCoordPointer(2, GL_FLOAT, 0, final meshTexCoords); 

    /*glGenBuffers(1, &ballVertexBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, ballVertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(MeshVertexData), MeshVertexData, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(arrowVertexData), 0); 
    glEnableVertexAttribArray(GLKVertexAttribNormal); 
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_TRUE, sizeof(arrowVertexData), (void *)offsetof(arrowVertexData, normal)); 
    glBindVertexArrayOES(arrowVertexArray);*/ 

    //glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
    //glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), newbasketballTexCoords); 
    if (!isSecondPlayer) { 
     for(PPhysicsObject *currentObject in self.spherePhysicsObjects) 
     {NSLog(@"first"); 
      self.baseEffect.transform.modelviewMatrix = 
      GLKMatrix4Multiply(savedModelviewMatrix, [appDelegate physicsTransformForObject:currentObject]); 
      [self.baseEffect prepareToDraw]; 

      glDrawArrays(GL_TRIANGLES, 0, newbasketballNumVerts); 
      //glDrawArrays(GL_TRIANGLES, 0, sizeof(MeshVertexData)/sizeof(arrowVertexData)); 
     } 
    } 
    else{ 
     for(PPhysicsObject *currentObject in self.secondSpherePhysicsObjects) 
     { 
      self.baseEffect.transform.modelviewMatrix = 
      GLKMatrix4Multiply(savedModelviewMatrix, [appDelegate physicsTransformForObject:currentObject]); 
      [self.baseEffect prepareToDraw]; 

      glDrawArrays(GL_TRIANGLES, 0, newbasketballNumVerts); 
      //glDrawArrays(GL_TRIANGLES, 0, sizeof(MeshVertexData)/sizeof(arrowVertexData)); 
     } 
    } 
    //glBindBuffer(GL_ARRAY_BUFFER, 0); 
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

    //glDisableVertexAttribArray(GLKVertexAttribTexCoord0); 
    self.baseEffect.transform.modelviewMatrix = savedModelviewMatrix; 
} 

這是爲什麼只使用一個紋理所有三個,而不是三個不同的紋理,每一個對象?我怎樣才能解決這個問題?

回答

1

我已經實現了一個場景,即圍繞地球的月球移動。地球和月球的不同紋理。下GLKit幀,代碼只是這樣的:

-(void)viewDidLoad 
{ 
    //...... 
    // Setup Earth texture 
CGImageRef earthImageRef = 
[[UIImage imageNamed:@"Earth512x256.jpg"] CGImage]; 

earthTextureInfo = [GLKTextureLoader 
        textureWithCGImage:earthImageRef 
        options:[NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], 
          GLKTextureLoaderOriginBottomLeft, nil nil] 
        error:NULL]; 

// Setup Moon texture 
CGImageRef moonImageRef = 
[[UIImage imageNamed:@"Moon256x128.png"] CGImage]; 

moonTextureInfo = [GLKTextureLoader 
        textureWithCGImage:moonImageRef 
        options:[NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], 
          GLKTextureLoaderOriginBottomLeft, nil nil] 
        error:NULL]; 
//...... 

}

然後,繪製地球和月亮。

- (void)drawEarth 
{ 
//setup texture 
self.baseEffect.texture2d0.name = earthTextureInfo.name; 
self.baseEffect.texture2d0.target = earthTextureInfo.target; 

// 
GLKMatrixStackPush(self.modelviewMatrixStack); 


GLKMatrixStackRotate( // Rotate (tilt Earth's axis) 
        self.modelviewMatrixStack, 
        GLKMathDegreesToRadians(SceneEarthAxialTiltDeg), 
        1.0, 0.0, 0.0); 
GLKMatrixStackRotate( // Rotate about Earth's axis 
        self.modelviewMatrixStack, 
        GLKMathDegreesToRadians(earthRotationAngleDegrees), 
        0.0, 1.0, 0.0); 


self.baseEffect.transform.modelviewMatrix = 
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack); 

//draw earth 
[self.baseEffect prepareToDraw]; 


glBindVertexArrayOES(_vertexArray); 
glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts); 

//pop 
GLKMatrixStackPop(self.modelviewMatrixStack); 

self.baseEffect.transform.modelviewMatrix = 
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack); 

}

- (void)drawMoon 
{ 

self.baseEffect.texture2d0.name = moonTextureInfo.name; 
self.baseEffect.texture2d0.target = moonTextureInfo.target; 


GLKMatrixStackPush(self.modelviewMatrixStack); 

GLKMatrixStackRotate( // Rotate to position in orbit 
        self.modelviewMatrixStack, 
        GLKMathDegreesToRadians(moonRotationAngleDegrees), 
        0.0, 1.0, 0.0); 
GLKMatrixStackTranslate(// Translate to distance from Earth 
         self.modelviewMatrixStack, 
         0.0, 0.0, SceneMoonDistanceFromEarth); 
GLKMatrixStackScale( // Scale to size of Moon 
        self.modelviewMatrixStack, 
        SceneMoonRadiusFractionOfEarth, 
        SceneMoonRadiusFractionOfEarth, 
        SceneMoonRadiusFractionOfEarth); 
GLKMatrixStackRotate( // Rotate Moon on its own axis 
        self.modelviewMatrixStack, 
        GLKMathDegreesToRadians(moonRotationAngleDegrees), 
        0.0, 1.0, 0.0); 
// 
self.baseEffect.transform.modelviewMatrix = 
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack); 

//draw moon 
[self.baseEffect prepareToDraw]; 


glBindVertexArrayOES(_vertexArray); 
glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts); 

GLKMatrixStackPop(self.modelviewMatrixStack); 

self.baseEffect.transform.modelviewMatrix = 
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack); 

} 
0

我爲這個問題所做的一件事就是我製作了一張帶有所有紋理的單個圖像......現在我只給我的GLKBaseEffect對象提供一個紋理。

但是,如果任何人有多個紋理與GLKit的幫助下多個對象的回答,請讓我知道...

謝謝。

0

一個解決方案是將您的繪圖調用分開,以便首先繪製所有使用紋理A的對象,然後繪製所有使用紋理B的對象等。

還有這裏描述的紋理地圖集替代:https://stackoverflow.com/a/8230592/64167

0

我在學習更多OpenGL ES,我可能有辦法做到這一點。

在我的情況下,我有N個四邊形,每個都有一個單獨的紋理。在我想繪製的每個四元組的[view drawInRect]中,我繪製了每個四元素之前在baseEffect上設置了新的紋理屬性,然後在BaseEffect和四元組上調用prepareToDraw,然後渲染四元組。

這裏是我的意思是一些僞代碼:

for (int i = 0; i < quads.count; i++) { 
    baseEffect.texture2d0.name = textureInfo[i].name; 
    baseEffect.texture2d0.target = textureInfo[i].target; 
    [baseEffect prepareToDraw]; 
    [quads[i] prepareToDraw]; 
    glDrawArrays(GL_TRIANGLES, 0, 4); 
} 

這是工作確定爲我至今。

1

要做到多重紋理,你需要做的:

effect.texture2d0.name = firstTexture.name; 
[effect prepareToDraw]; 
[self renderFirstObject]; 

effect.texture2d0.name = secondTexture.name; 
[effect prepareToDraw]; 
[self renderSecondObject]; 

或類似的東西。如果你有很多對象,我推薦使用紋理地圖集,然後使用以下代碼進行批量渲染:

glDrawElements(GL_TRIANGLES,totalIndicies,GL_UNSIGNED_SHORT,indices);

我試圖使用glDrawArray爲每一個對象和我的應用程序的幀率蘸到喜歡10fps。

在你的代碼中,它爲所有對象使用1紋理的原因是因爲你從未在每個對象之前將effect.texture2d0.name改爲你需要的紋理。如果我要改變你的代碼,這將是:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{ 
    static float a = 0; 
    a = a+0.1; 
    //NSLog(@"a : %f",a); 
    self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeLookAt(
                   0, 9.8, 10.0, // Eye position 
                   0.0, 1.0, 0.0, // Look-at position 
                   0.0, 1.0, 0.0); // Up direction 

    const GLfloat aspectRatio = (GLfloat)view.drawableWidth/(GLfloat)view.drawableHeight; 

    self.baseEffect.transform.projectionMatrix = 
    GLKMatrix4MakePerspective(GLKMathDegreesToRadians(35.0f),aspectRatio,0.2f,200.0f); // Far arbitrarily far enough to contain scene 

    self.baseEffect.light0.position = GLKVector4Make(0.6f, 1.0f, 0.4f, 0.0f); 

    [self.baseEffect prepareToDraw]; 

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

    self.baseEffect.texture2d0.name = textureInfo.name; 
    [self.baseEffect prepareToRender]; 
    [self drawPhysicsSphereObjects]; 
    self.baseEffect.texture2d0.name = textureInfo1.name; 
    [self.baseEffect prepareToRender]; 
    [self drawPhysicsBoxObjects]; 
    //[self drawPhysicsCylinderObjects]; 
} 

當然,這是簡化的,並且沒有頂點屬性陣列設置。

相關問題