[英]How can I apply different textures to different objects using GLKit?
我在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;
}
為什么這只對所有三個使用一個紋理,而不是三個不同的紋理,每個對象一個? 我怎樣才能解決這個問題?
要做多個紋理,您需要做:
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,indices);
我試圖為每個對象使用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];
}
當然這是簡化它,沒有頂點屬性數組設置。
我已經實現了一個場景,即地球周圍的月亮在移動。 地球和月亮的不同紋理。 在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);
}
我為這個問題做的一件事就是我制作了一張包含所有紋理的單個圖像...現在我只給了一個紋理到我的GLKBaseEffect對象。
但是如果有人在GLKit的幫助下回答了多個具有多個紋理的對象,請告訴我...
謝謝。
一種解決方案是分離繪圖調用,以便首先繪制使用紋理A的所有對象,然后繪制使用紋理B的所有對象,依此類推。
這里還描述了紋理圖集替代方案: https : //stackoverflow.com/a/8230592/64167 。
我正在學習更多的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);
}
到目前為止,這對我來說還不錯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.