OpenGL, GL_MODULATE и мультитекстурирование - PullRequest
5 голосов
/ 02 февраля 2012

Я успешно нарисовал мульти-текстурированный многоугольник, но, к сожалению, только первый пиксель наложенной текстуры используется во всей области текстуры.

Вот текстуры (GL_TEXTURE0 и GL_TEXTURE1):

icon overlay

Результат таков:

result

Используется только красный пиксель вверху. Я пробовал с синим пикселем 1x1 вверху, и я получаю тот же результат с синим наложением.

Мой код:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_COLOR_ARRAY);

const CGPoint vertices[] = {
    ccp(0,0),
    ccp(100,0),
    ccp(0,100),
    ccp(100,100),
};

// This will flip the image for us as well
const CGPoint coordinates[] = {
    ccp(0,1),
    ccp(1,1),
    ccp(0,0),
    ccp(1,0),
};

// Config multitextures
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icon.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, overlay.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

GLubyte points = 4;

// Draw the square
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, points);

// Revert back
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);

// glClientActiveTexture(GL_TEXTURE0); // breaks multitexturing
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);

glEnableClientState(GL_COLOR_ARRAY);

Это проблема OpenGL, но для тех, кто заинтересован, здесь доступен проект iOS: http://dl.dropbox.com/u/33811812/cocos2d/OpenGLTest.zip

EDIT: Из Красной Книги:

Если вы используете мультитекстурирование и используете glTexCoord * (), вы настраиваете координаты текстуры для первого текстурного блока. Другими словами, использование glTexCoord * () эквивалентно использованию glMultiTexCoord * (GL_TEXTURE0, ...)

Любые подсказки о том, как передать массив координат? OpenGL ES 1.1 не поддерживает glBegin () и т. Д.

1 Ответ

6 голосов
/ 03 февраля 2012

Наконец-то! Решение состояло в том, что я должен был сделать три вещи:

  • Используйте glClientActiveTexture (GL_TEXTURE *) для 0 и 1 перед glTexCoordPointer
  • Также используйте glEnableClientState (GL_TEXTURE_COORD_ARRAY) для каждой текстуры
  • Вернитесь обратно к glClientActiveTexture (GL_TEXTURE0), чтобы избежать конфликта с дальнейшими ничьями

Вот код, который работает:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_COLOR_ARRAY);

const CGPoint vertices[] = {
    ccp(0,0),
    ccp(100,0),
    ccp(0,100),
    ccp(100,100),
};

// This will flip the image for us as well
const CGPoint coordinates[] = {
    ccp(0,1),
    ccp(1,1),
    ccp(0,0),
    ccp(1,0),
};

// Config multitextures
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, icon.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, overlay.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

GLubyte points = 4;

// Draw the square
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, points);

// Revert back
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);

glEnableClientState(GL_COLOR_ARRAY);

И результат:

works

...