如何在iPhone的opengles中使用glBindTexture?

时间:2011-01-27 11:42:03

标签: iphone opengl-es

这是我第一次尝试理解opengl。我写了一个简单的opengles示例,用于绘制四边形的iphone。起初我忘记使用glBindTexture,但它有效。后来我尝试添加另一个四边形并看到当我使用glBindTexture时,没有一个四边形被纹理化,它们是白色的。然后我删除了新添加的四元组,当glBindTexture存在时它仍然无效。如果我评论它一切都很好。当然,我需要不止一个四元组......纹理。

编辑:此方法在我的视图控制器中,从Apple OpenglES示例中窃取了EAGLView。它初始化opengl。每个四元组都有一个Place类的实例。首先进行测试我只使用了一个四核;我只有一个Place对象,正如我所说,我忘了使用glBindTexture。但在那之后,当我开始使用它时,纹理不再有效,即使只有一个四边形。

EDIT2:以下是我想要的示例:http://www.youtube.com/watch?v=U2uH-jrsSxs


-(void) setupOpenGL
{
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  // Enable use of the texture
  glEnable(GL_TEXTURE_2D);
  // Enable blending
  glEnable(GL_BLEND);
  // Set a blending function to use
  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

  //!!!!!!!!!!!!
  //EDIT: THIS IS WHERE I WAS WRONG: I NEED TO SET THESE FOR EVERY TEXTURE I USE
  //THEY ARE NOT GLOBAL
  //!!!!!!!!!!!!
  // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  //same for magnification
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  //-----------------

  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

  for (Place *p in locations)
  {
    [p loadTexture];
    [p reloadTitle];
    /*
    p.relativeHeading = 123.45;
    p.absoluteHeading = 23.45;
    p.distance = 1234.5;
    [p reloadHeading];
    [p reloadDistance];
    */
  }

  glError = glGetError(); //check if we f*cked up already or not;
  NSLog(@"setupOpenGL result: %i", glError);
}

以下是我Place班的代码:


- (void) loadTexture
{
  Byte * textureData = [Place getTexture];
  glGenTextures(1, &textureID);

  glBindTexture(GL_TEXTURE_2D, self.textureID);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 
    TEXTURE_W, TEXTURE_H, 0, 
    GL_RGBA, GL_UNSIGNED_BYTE, textureData); 
  //copy the texture to video memory we can safely release our own copy of the texture after this
  GLenum glError = 0;
  glError = glGetError();
}

- (void) reloadTitle
{
  CGSize actualSize = CGSizeZero; //not used now

  CGRect cropRect = CGRectMake(TITLE_X, TITLE_Y, TITLE_W, TITLE_H);
  Byte *imageData = [self writeTextOverTexture:
    [Place getTextureCrop : cropRect] : cropRect.size :
    CGRectMake(0, 0, TITLE_W, TITLE_H) :
    self.title : [UIFont fontWithName: @"Arial" size: 14] :
    [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1] : 
    &actualSize];

  glBindTexture(GL_TEXTURE_2D, self.textureID);
  glTexSubImage2D(GL_TEXTURE_2D, 0,
    TITLE_X, TITLE_Y, TITLE_W , TITLE_H, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
}

- (void) reloadDistance
{
 //...very similar to reloadTitle
}

- (void) reloadHeading
{
  // very similar to the other too
}

这是绘制四边形的方法。基本上在每个“地方”我都有纬度/经度,当我绘制时,我使用iPhone罗盘标题,位置和加速度计将其他地方绘制在正确的位置。


- (void) drawFrame
{
  if (location == nil) return;
  if (myHeading == -1) return;

  [(EAGLView *)self.glView setFramebuffer];

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  perspective(LANDSCAPE_FOV, WIDTH/HEIGHT , 1.0f, 20.0f);
  glRotatef((GLfloat)rollAngle, 0, 0, 1);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  double tmpPitchAngle = pitchAngle;
  tmpPitchAngle -= 20;
  tmpPitchAngle = clampValue(tmpPitchAngle, -85, +85);

  //glRotatef((GLfloat) tmpPitchAngle, 1, 0, 0);
  glRotatef((GLfloat) myHeading, 0, 1, 0);

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glClear(GL_COLOR_BUFFER_BIT);

  for (Place *p in locations)
  {
    glPushMatrix();
      glRotatef(-p.absoluteHeading, 0, 1, 0);
      glTranslatef(0, 0, -5);
      glScalef(0.4, 0.4, 1.0);
      glBindTexture(GL_TEXTURE_2D, p.textureID);
      glVertexPointer (3, GL_BYTE, 0, KVertices);
      glTexCoordPointer(2, GL_BYTE, 0, texCoords);
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    glPopMatrix();
  }

  glError = glGetError();
  NSLog(@"glError drawFrame = %i", glError);

  [(EAGLView *)self.glView presentFramebuffer];
}

我该如何使这项工作?当我忘记绑定纹理时,我使用什么纹理。据我所知glBindTexture用于选择或激活纹理,以便我可以绘制或更改它。

2 个答案:

答案 0 :(得分:2)

你错过了一些东西,把它放在glTexImage2D之后:

glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_MAG_FILTER, GL_NEAREST);

然后你的纹理会出现而不是白色。这是因为默认情况下,OpenGL使用mipmapped过滤器。由于没有mipmap,纹理不完整,看起来完全是白色。

答案 1 :(得分:2)

OpenGL是一个状态机。其中一个状态是目标GL_TEXTURE_2D的当前纹理。您可以随时上传纹理以替换当前纹理。

在OpenGL 1.0中,没有glGenTextures / glBindTexture,假设在第一次实现时你会在使用之前立即提交完整的每个纹理,并且作为第二个实现,你可以通过显示列表完成所有工作,驱动程序有机会在看到合适时缓存纹理。 OpenGL ES长期不推荐使用显示列表,这可能是一个坏主意。从OpenGL 1.1开始,在OpenGL ES的所有迭代中,都可以使用纹理名称和各种相关函数。

纹理名称只是保存GL_TEXTURE_2D状态的存储版本的一种方式。因此,如果您创建纹理名称并将其绑定,您将创建一个环境,您可以在其中更改纹理(和纹理参数),而不会影响任何其他命名纹理。并且驱动程序很容易将图像缓存在GPU可寻址内存中。

但是,如果您不想,实际上不需要使用纹理名称。它只是上传和使用纹理是有效的。这可能就是为什么你的应用程序在没有调用glBindTexture的情况下工作的原因。

鉴于您正在使用纹理名称,在提供新的子图像之前,您的reloadTitle不应该绑定相关纹理吗?你似乎没有绑定drawFrame中的任何特定纹理?

相关问题