ios opengl-es textures glkit

ios - ¿Cómo puedo aplicar diferentes texturas a diferentes objetos usando GLKit?



opengl-es textures (5)

Una cosa que hice para este problema es que hice una sola imagen con todas las texturas ... ahora le doy solo una textura a mi objeto GLKBaseEffect.

Pero si alguna persona tiene respuesta para múltiples objetos con múltiples texturas con la ayuda de GLKit, por favor, hágamelo saber ...

Gracias.

Estoy mostrando 3 objetos con la ayuda de GLKit. Sin embargo, cuando estoy aplicando texturas a estos objetos, solo se usa una textura para los tres.

El código que estoy usando es el siguiente:

- (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; }

¿Por qué esto solo usa una textura para las tres, y no tres texturas diferentes, una para cada objeto? ¿Cómo puedo arreglar esto?


Estoy jugando con aprender más OpenGL ES y puedo tener una manera de hacer esto.

En mi caso, tengo N quads, cada uno con una textura individual. En [view drawInRect] para cada cuadrante que quiero dibujar, establezco nuevas propiedades de textura en baseEffect antes de dibujar cada cuadrante, luego, preparo a PrepareToDraw en el BaseEffect y el quad, luego renderizo el quad.

Aquí hay un pseudocódigo para lo que quiero decir:

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); }

Esto está funcionando bien para mí hasta ahora.


Para hacer múltiples texturas necesitarás hacer:

effect.texture2d0.name = firstTexture.name; [effect prepareToDraw]; [self renderFirstObject]; effect.texture2d0.name = secondTexture.name; [effect prepareToDraw]; [self renderSecondObject];

o algo similar. Si tienes muchos objetos, te recomiendo usar atlas de texturas y luego hacer un renderizado por lotes usando:

glDrawElements (GL_TRIANGLES, totalIndicies, GL_UNSIGNED_SHORT, índices);

Traté de usar glDrawArray para cada objeto y la velocidad de fotogramas de mi aplicación bajó a 10fps.

En tu código, la razón por la que usaba 1 textura para todos los objetos es porque nunca cambiaste el efecto.texture2d0.name por la textura que necesitas antes de cada objeto. Si tuviera que cambiar tu código, sería:

- (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]; }

Por supuesto, esto lo está simplificando, y sin la configuración de matriz de atributos de vértice.


Había logrado una escena en la que la luna alrededor de la tierra se movía. diferentes texturas para la tierra y la luna. debajo del marco GLKit, el código es así:

-(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]; //......

}

luego, dibuja la tierra y la luna.

- (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); }


Una solución sería separar sus llamadas de dibujo para que primero dibuje todos los objetos que usen texturas A, luego todos los objetos que usen texturas B y así sucesivamente.

También está la alternativa del atlas de textura que se describe aquí: https://.com/a/8230592/64167 .