提问链接: http://stackoverflow.com/questions/13678485/how-can-i-apply-different-textures-to-different-objects-using-glkit
刚好我也需要实现这样的功能,于是就写了一个demo,demo中的sphere.h 以及两张图片都是从Erik的白皮书源码中拿来的,下面贴上实现的代码,有详细注释比较简单,新手要注意整个逻辑过程,估计看一篇就知道该怎么对不同对象贴上不同的纹理了。
#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