罗大柚OpenGL ES课程系列LessonFour(Part X):rendering multiple objects with different texture

罗大柚OpenGL ES教程系列LessonFour(Part X):rendering multiple objects with different texture
最近在stack overflow 上看到有人提问: 

How can I apply different textures to different objects using GLKit?

提问链接: http://*.com/questions/13678485/how-can-i-apply-different-textures-to-different-objects-using-glkit

刚好我也需要实现这样的功能,于是就写了一个demo,demo中的sphere.h 以及两张图片都是从Erik的白皮书源码中拿来的,下面贴上实现的代码,有详细注释比较简单,新手要注意整个逻辑过程,估计看一篇就知道该怎么对不同对象贴上不同的纹理了。

下面是效果图:
罗大柚OpenGL ES课程系列LessonFour(Part X):rendering multiple objects with different texture 罗大柚OpenGL ES课程系列LessonFour(Part X):rendering multiple objects with different texture


下面是实现代码:
#import "ViewController.h"
#import "sphere.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))

@interface ViewController ()
{
    //私有变量
    GLuint _vertexArray;
    GLuint _positionBuffer;
    GLuint _normalBuffer;
    GLuint _textureBuffer;
}


@end

@implementation ViewController

@synthesize baseEffect;
@synthesize earthTextureInfo;
@synthesize moonTextureInfo;
@synthesize modelviewMatrixStack;
@synthesize earthRotationAngleDegrees;
@synthesize moonRotationAngleDegrees;

//设置一些常量
// Constants
static const GLfloat  SceneEarthAxialTiltDeg = 23.5f;
static const GLfloat  SceneDaysPerMoonOrbit = 28.0f;
static const GLfloat  SceneMoonRadiusFractionOfEarth = 0.25;
static const GLfloat  SceneMoonDistanceFromEarth = 1.5;

// Setup a light to simulate the Sun
- (void)configureLight
{
    self.baseEffect.light0.enabled = GL_TRUE;
    self.baseEffect.light0.diffuseColor = GLKVector4Make(
                                                         1.0f, // Red
                                                         1.0f, // Green
                                                         1.0f, // Blue
                                                         1.0f);// Alpha
    self.baseEffect.light0.position = GLKVector4Make(
                                                     1.0f,
                                                     0.0f,
                                                     0.8f,
                                                     0.0f);
    self.baseEffect.light0.ambientColor = GLKVector4Make(
                                                         0.2f, // Red
                                                         0.2f, // Green
                                                         0.2f, // Blue
                                                         1.0f);// Alpha
}


- (void)viewDidLoad
{
    [super viewDidLoad];
	//1. 设置context
    EAGLContext *context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
    [EAGLContext setCurrentContext:context];
    
    //2.设置当前视图为GLView
    GLKView *glView = (GLKView *) self.view;
    NSAssert([glView isKindOfClass:[GLKView class]],
             @"View controller's view is not a GLKView");
    //3.设置GLView的属性
    glView.context = context;
    glView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    
    //4. 创建一个baseEffect
    self.baseEffect = [[GLKBaseEffect alloc] init];
    
    
    //5. 自主设置场景
    //创建一个stack,A newly created stack is initialized with the identity matrix.
    self.modelviewMatrixStack =
    GLKMatrixStackCreate(kCFAllocatorDefault);
    
    //设置light模拟太阳
    [self configureLight];
    
    
    
    //设置投影矩阵
    self.baseEffect.transform.projectionMatrix =
    GLKMatrix4MakeOrtho(
                        -1.0 * 768.0 / 1024.0,
                        1.0 * 768.0 / 1024.0,
                        -1.0,
                        1.0,
                        1.0,
                        120.0);
    
    //设置模型视图矩阵
    self.baseEffect.transform.modelviewMatrix =
    GLKMatrix4MakeTranslation(0.0f, 0.0f, -5.0);
    
    //设置场景的背景颜色
    glClearColor(0.0f, 0.1f, 0.1f, 1.0f);
    
    //设置用于绘制earth和moon的VAO
    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);
    
    //绑定球体的顶点数据
    glGenBuffers(1,               
                 &_positionBuffer);
    glBindBuffer(GL_ARRAY_BUFFER,
                 _positionBuffer);
    glBufferData(
                 GL_ARRAY_BUFFER,
                 sizeof(sphereVerts),
                 sphereVerts,
                 GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(0));
    
    //绑定球体的法线数据
    glGenBuffers(1,
                 &_normalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER,
                 _normalBuffer);
    glBufferData(
                 GL_ARRAY_BUFFER,
                 sizeof(sphereNormals),
                 sphereNormals,
                 GL_STATIC_DRAW);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(0));
    
    //绑定球体的纹理数据
    glGenBuffers(1,
                 &_textureBuffer);
    glBindBuffer(GL_ARRAY_BUFFER,
                 _textureBuffer);
    glBufferData(
                 GL_ARRAY_BUFFER,
                 sizeof(sphereTexCoords),
                 sphereTexCoords,
                 GL_STATIC_DRAW);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), BUFFER_OFFSET(0));
    
    //Bind back to the default state
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArrayOES(0);
    
    
    // Setup Earth texture
    CGImageRef earthImageRef =
    [[UIImage imageNamed:@"Earth512x256.jpg"] CGImage];
    
    earthTextureInfo = [GLKTextureLoader
                        textureWithCGImage:earthImageRef
                        options:[NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES],
                                 GLKTextureLoaderOriginBottomLeft, 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]
                       error:NULL];
    
    // Initialize the matrix stack
    GLKMatrixStackLoadMatrix4(
                              self.modelviewMatrixStack,
                              self.baseEffect.transform.modelviewMatrix);
    
    // Initialize Moon position in orbit(轨道)
    self.moonRotationAngleDegrees = -20.0f;
}

//绘制模型一:地球
- (void)drawEarth
{
    //设置纹理
    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);
    
    //GLKMatrixStackGetMatrix4()函数从栈中获取矩阵
    self.baseEffect.transform.modelviewMatrix =
    GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);
    
    //开始绘制earth
    [self.baseEffect prepareToDraw];
    
    //绘制earth
    glBindVertexArrayOES(_vertexArray);
    glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
    
    //出栈
    GLKMatrixStackPop(self.modelviewMatrixStack);
    
    self.baseEffect.transform.modelviewMatrix =
    GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);

}

//绘制模型二:moon
- (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);
    //设置当前模型的MV矩阵
    self.baseEffect.transform.modelviewMatrix =
    GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);
    
    //准备绘制Moon
    [self.baseEffect prepareToDraw];
    
    //绘制Moon
    glBindVertexArrayOES(_vertexArray);
    glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
    
    GLKMatrixStackPop(self.modelviewMatrixStack);
    
    self.baseEffect.transform.modelviewMatrix =
    GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);

}

#pragma mask GLKView Delegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // Update the angles every frame to animate
    // (one day every 60 display updates)
    //每帧调用一次代理方法
    self.earthRotationAngleDegrees += 360.0f / 120.0f;
    self.moonRotationAngleDegrees += (360.0f / 120.0f) /
    SceneDaysPerMoonOrbit;
    
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    [self drawEarth];
    [self drawMoon];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    
    // Make the view's context current
    GLKView *view = (GLKView *)self.view;
    //[AGLKContext setCurrentContext:view.context];
    [EAGLContext setCurrentContext:view.context];
    
    glDeleteBuffers(1, &_positionBuffer);
    glDeleteBuffers(1, &_normalBuffer);
    glDeleteBuffers(1, &_textureBuffer);
    
    
    // Stop using the context created in -viewDidLoad
    ((GLKView *)self.view).context = nil;
    [EAGLContext setCurrentContext:nil];
    
    CFRelease(self.modelviewMatrixStack);
    self.modelviewMatrixStack = NULL;
}




- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)takeShouldUsePerspective:(UISwitch *)sender {
    
    
    GLfloat   aspectRatio =
    (float)((GLKView *)self.view).drawableWidth /
    (float)((GLKView *)self.view).drawableHeight;
    
    if([sender isOn])       //UISwith 的属性
    {
        self.baseEffect.transform.projectionMatrix =
        GLKMatrix4MakeFrustum(
                              -1.0 * aspectRatio,
                              1.0 * aspectRatio,
                              -1.0,
                              1.0,
                              1.0,
                              120.0);
    }
    else
    {
        self.baseEffect.transform.projectionMatrix =
        GLKMatrix4MakeOrtho(
                            -1.0 * aspectRatio,
                            1.0 * aspectRatio,
                            -1.0,
                            1.0,
                            1.0,
                            120.0);
    }

}

源码下载地址: http://download.csdn.net/detail/luozhonglan/7211993