Объединение текстур OpenGL не (всегда) работает - PullRequest
1 голос
/ 21 июля 2009

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

Мой объект WorldQuad имеет переменные bottom и top, оба типа Texture. Это предоставляемый JOGL класс, который оборачивает текстуру OpenGL; он загружает его для меня, и затем я могу вызвать enable (), чтобы он сделал glEnable (GL_TEXTURE_2D), и bind (), чтобы он сделал связывание.

Он также имеет переменную alphaMap моего собственного типа, которая хранит еще одну текстуру; но этот текстур имеет внутренний формат GL_ALPHA8 (другими словами, это текстура с только альфа-значениями). В настоящее время я генерирую это программно, чтобы сделать его идеальным для пикселей.

Затем я использую OpenGL «совмещение текстур» (или иногда называемый текстурным разбрызгиванием), чтобы объединить нижнюю и верхнюю текстуры в соответствии с альфа-картой.

Дело в том, что это прекрасно работало !! ... на моем рабочем ноутбуке. Это IBM Thinkpad T400 со встроенным чипом Intel (GMA950 или что-то подобное). Но я пришел домой к своему Dell Inspiron E1705 с дискретной картой NVIDIA GeForce Go 7900GS и обнаружил, что моя программа отображает только четырехугольники с «нижней» текстурой. Как будто альфа вообще не применяется. Я также попробовал это на двух рабочих столах и другом ноутбуке здесь. Один из рабочих столов вышел из строя, другой показывал четырехугольник полностью белым (это старый чип GeForce, вероятно, не поддерживает OpenGL 2 или что-то в этом роде), а другой ноутбук работал так же, как мой; четырехугольник, покрытый нижней текстурой.

Я уже пытался изменить формат альфа-карты на GL_RGBA, на случай, если моей видеокарте по какой-то причине не понравилась текстура GL_ALPHA8. Я также проверил, что все три текстуры есть и могут отображаться, рисуя нормальные четырехугольники с каждой отдельной текстурой, включая альфа-карту. Я также вывожу альфа-карту в файл, поэтому я дважды проверил, что она есть и должна работать.

Ниже моя функция рисовать квад на основе всего этого. Я добавил комментарии, так что, надеюсь, вы сможете следить за ними. Пожалуйста, предложите все, что может решить проблему. Я в тупике! Почему он работает на хреновом встроенном чипе, а не на моей видеокарте? Чего мне не хватает ??

Спасибо !!

РЕДАКТИРОВАТЬ: Хорошо, никто не может мне помочь, по-видимому ... Я вернулся на работу сейчас, подключил мою флешку к моему рабочему компьютеру, запустил Eclipse и нажал кнопку запуска ... И это сработало. Затем я вынул диск, вставил его в свой личный ноутбук (который я сегодня привел на работу) и сделал то же самое, и это просто красная капля. Но здесь я это задокументировал. Прежде всего, вывод из glGetString (GL_EXTENSIONS), распределенный между двумя компьютерами .

Далее скриншоты сломанных и работающих . Опять же, они были приняты точно так же: откройте Eclipse, нажмите Run, скриншот. Вот и все. Я не трогал свой код, и на флешке, которую я поменял между двумя компьютерами, есть только одна копия. У них обоих одинаковые версии JDK.

Теперь одно из различий между компьютерами состоит в том, что мой рабочий компьютер работает под управлением XP, а мой ноутбук работает под управлением Windows 7. Должна ли это действительно иметь значение? Тем более, что я использую OpenGL 2, я думаю, что оба компьютера будут одинаково поддерживать его. Фактически, если вы посмотрите на мою страницу различий выше, мой персональный ноутбук поддерживает гораздо больше расширений, чем рабочий ноутбук - как я и ожидал, поскольку это карта nvidia 7900gs по сравнению с интегрированной Intel. Так что это кажется задом наперед; во всяком случае, я ожидаю, что встроенный чип захлебнется сочетанием текстур, но не моя видеокарта!

Помощь!

public void drawWorldQuad(GL2 gl, float x, float z, WorldQuad q, WorldVertex tl, WorldVertex tr, WorldVertex bl, WorldVertex br) {
    WorldVertex[] verts = new WorldVertex[] {
        bl, br, tr, tl
    };
    final float[][] texCoords = new float[][] {
            {0.0f, 0.0f},
            {1.0f, 0.0f},
            {1.0f, 1.0f},
            {0.0f, 1.0f}
    };
    final float[][] coords = new float[][] {
            {x,z},
            {x+1,z},
            {x+1,z+1},
            {x,z+1}
    };

    gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    /* BEGIN TEXTURE BLENDING SECTION: */

    /* TEXTURE0 is the alpha map; a texture of type GL_ALPHA8, no rgb channels */
    gl.glActiveTexture(GL2.GL_TEXTURE0);
    q.alphaMap.getTexture().bind();
    q.alphaMap.getTexture().enable();
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_DECAL);

    /* TEXTURE1 is the 'bottom' texture */
    gl.glActiveTexture(GL2.GL_TEXTURE1);
    q.bottom.getTexture().bind();
    q.bottom.getTexture().enable();
    // use the rgb from the bottom texture
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_COMBINE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_RGB, GL2.GL_DECAL);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_RGB, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_RGB, GL2.GL_SRC_COLOR);
    //------------------------
    // use the alpha value from the alphaMap
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_ALPHA, GL2.GL_DECAL);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_ALPHA, GL2.GL_SRC_ALPHA);

    /* TEXTURE2 is the 'top' texture */
    gl.glActiveTexture(GL2.GL_TEXTURE2);
    q.top.getTexture().bind();
    q.top.getTexture().enable();
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_COMBINE);
    // interpolate between texture1 and texture2's colors, using the alpha values
    // from texture1 (which were taken from the alphamap)
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_RGB, GL2.GL_INTERPOLATE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_RGB, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE1_RGB, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE2_RGB, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_RGB, GL2.GL_SRC_COLOR);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND1_RGB, GL2.GL_SRC_COLOR);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND2_RGB, GL2.GL_SRC_ALPHA);
    //------------------------
    // interpolate the alphas (this doesn't really matter, neither of the textures
    // really have alpha values)
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_ALPHA, GL2.GL_INTERPOLATE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE1_ALPHA, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE2_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_ALPHA, GL2.GL_SRC_ALPHA);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND1_ALPHA, GL2.GL_SRC_ALPHA);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND2_ALPHA, GL2.GL_SRC_ALPHA);

    gl.glBegin(GL2.GL_QUADS);
    {
        for(int j=0;j<verts.length;j++) {
            // (this loop and the arrays used here are for convenience, it just draws
            // a quad; verts.length == 4)

            WorldVertex v = verts[j];

            gl.glMultiTexCoord2f(GL2.GL_TEXTURE0, texCoords[j][0], texCoords[j][3]);
            gl.glMultiTexCoord2f(GL2.GL_TEXTURE1, texCoords[j][0], texCoords[j][4]);
            gl.glMultiTexCoord2f(GL2.GL_TEXTURE2, texCoords[j][0], texCoords[j][5]);

            gl.glVertex3f(coords[j][0], (float)v.height * VERTICAL_SCALE, coords[j][6]);
        }
    }
    gl.glEnd();

}

1 Ответ

4 голосов
/ 21 июля 2009

ЭТО РАБОТАЕТ !! После нескольких часов попыток я наконец-то получил это.

После настройки TEXTURE0 я изменил эту строку:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_DECAL);

к этому:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);

Я просто изменил его по прихоти, так как я до сих пор не понимаю разницу между DECAL и REPLACE, и это сработало!

...