Как использовать glBindTexture в opengles для iphone? - PullRequest
1 голос
/ 27 января 2011

это моя первая попытка понять opengl. Я написал простой пример opengles для iphone, который рисует квад. Сначала я забыл использовать glBindTexture, НО это работало. Позже я попытался добавить еще один квад и увидел, что когда я использую glBindTexture, ни один из квадратов не текстурируется, они белые. Затем я удалил недавно добавленный квад, и он все еще не работал, когда glBindTexture был там. Если бы я это прокомментировал, все было хорошо. Конечно, мне понадобится более одного квадра ... с текстурой.

РЕДАКТИРОВАТЬ: Этот метод в моем контроллере представления, который украл EAGLView из примера Apple OpenglES. Инициализирует 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 ]

2 голосов
/ 27 января 2011

OpenGL - это конечный автомат. Одним из этих состояний является текущая текстура для цели GL_TEXTURE_2D. Вы можете загрузить текстуру в любое время, когда захотите заменить текущую текстуру.

В OpenGL 1.0 не было glGenTextures / glBindTexture, предполагалось, что в первой реализации вы передадите каждую текстуру в полном объеме непосредственно перед ее использованием, а во вторую очередь вы будете делать все через список отображения, давая У водителя появилась возможность кэшировать текстуру по своему усмотрению. Списки отображения давно устарели и отсутствуют в OpenGL ES, и, вероятно, были плохой идеей. Начиная с OpenGL 1.1 и во всех итерациях OpenGL ES доступны имена текстур и различные связанные функции.

Имя текстуры - это просто способ сохранить сохраненную версию состояния GL_TEXTURE_2D. Поэтому, если вы создаете имя текстуры и связываете его, вы создаете среду, в которой вы можете изменить текстуру (и параметры текстуры), не затрагивая другие названные текстуры. И драйверу становится действительно легко кэшировать изображения в адресуемой памяти GPU.

Однако вам не нужно использовать имена текстур, если вы этого не хотите. Это действительно только для загрузки и использования текстуры. Вероятно, поэтому ваше приложение работало без каких-либо вызовов glBindTexture.

Учитывая, что вы используете имена текстур, не должен ли ваш reloadTitle связать соответствующую текстуру перед предоставлением нового подизображения? И вы, кажется, не привязываете какую-то конкретную текстуру в drawFrame?

2 голосов
/ 27 января 2011

Вам чего-то не хватает, поместите это после glTexImage2D:

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

Тогда ваши текстуры появятся и не будут выглядеть белыми.Это связано с тем, что по умолчанию OpenGL использует фильтры с отображением.Поскольку у вас нет мипмапов, текстура является неполной и выглядит полностью белой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...