0

我在 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;
}

为什么这三个只使用一个纹理,而不是三个不同的纹理,每个对象一个?我怎样才能解决这个问题?

4

5 回答 5

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

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

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

于 2014-02-12T04:33:23.050 回答
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);  

}  
于 2014-05-01T15:10:59.160 回答
0

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

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

谢谢你。

于 2012-12-11T10:27:22.647 回答
0

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

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

于 2013-04-15T17:54:01.110 回答
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);
}

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

于 2014-02-09T00:32:44.443 回答