【问题标题】:How can I apply different textures to different objects using GLKit?如何使用 GLKit 将不同的纹理应用于不同的对象?
【发布时间】:2012-12-03 06:52:38
【问题描述】:

我在 GLKit 的帮助下显示了 3 个对象。但是,当我将纹理应用于这些对象时,所有三个都只使用了一个纹理。

我使用的代码如下:

- (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;
}

为什么这三个只使用一个纹理,而不是三个不同的纹理,每个对象一个?我该如何解决这个问题?

【问题讨论】:

    标签: ios opengl-es textures glkit


    【解决方案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);  
    
    }  
    

    【讨论】:

      【解决方案2】:

      要制作多个纹理,您需要这样做:

      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, 索引);

      我尝试对每个对象使用 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];
       }
      

      当然这是简化了,没有顶点属性数组设置。

      【讨论】:

        【解决方案3】:

        我为这个问题做的一件事是我制作了一张包含所有纹理的图像......现在我只给我的 GLKBaseEffect 对象提供一个纹理。

        但是如果有人在 GLKit 的帮助下对具有多个纹理的多个对象有答案,请告诉我...

        谢谢。

        【讨论】:

          【解决方案4】:

          一种解决方案是将绘图调用分开,以便首先绘制所有使用纹理 A 的对象,然后绘制所有使用纹理 B 的对象,依此类推。

          这里还描述了纹理图集替代方案:https://stackoverflow.com/a/8230592/64167

          【讨论】:

            【解决方案5】:

            我正在学习更多 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);
            }
            

            到目前为止,这对我来说还可以。

            【讨论】:

              猜你喜欢
              • 2020-10-28
              • 2023-03-15
              • 2018-07-11
              • 2015-07-14
              • 2017-12-09
              • 2011-10-10
              • 2020-03-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多