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