Как мне настроить текстуры, чтобы я мог использовать их в фрагментном шейдере Android OpenGL-ES 2.0? - PullRequest
2 голосов
/ 06 января 2012

Я пытаюсь получить доступ к 2 текстурам в 1 фрагментном шейдере.

Для этого у меня есть 2 текстуры, которые я настроил с помощью следующего кода:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, vbuff);
glTexCoordPointer(2, GL_FLOAT, 0, tbuff);

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, texture0);
glEnable(GL_TEXTURE_2D);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, texture1); 
glEnable(GL_TEXTURE_2D);

И я пытаюсь объединить их со следующим фрагментным шейдером:

uniform sampler2D tex0;
uniform sampler2D tex1;
void main()
{
    vec4 texval1 = texture2D(tex0, TextureCoordOut);
    vec4 texval2 = texture2D(tex1, TextureCoordOut);
    gl_FragColor = 0.5*(texval1 + texval2)
}

Почему-то это не работает, и отображается только вторая текстура.

PS: я занимаюсь разработкой шейдеров для Windows7, но хочу использовать код C ++ и шейдеры с Android NDK на устройстве Android.

РЕДАКТИРОВАТЬ: Я получил это работает, и я публикую код здесь, чтобы другие могли извлечь из этого пользу:

вершинный шейдер

varying vec2 TextureCoordOut;
void main()
{
    gl_Position = ftransform();
    TextureCoordOut = vec2(gl_MultiTexCoord0);
}

фрагментный шейдер

varying mediump vec2 TextureCoordOut;
uniform sampler2D tex0;
uniform sampler2D tex1;
void main()
{
    gl_FragColor = texture2D(tex0, TextureCoordOut) * texture2D(tex1, TextureCoordOut);
}

делает

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, vbuff);  //2 dimensional vertex buffer
glTexCoordPointer(2, GL_FLOAT, 0, tbuff); // 2 dimensional textures
glColor4f(1, 1, 1, 1);

glActiveTexture(GL_TEXTURE0);       glBindTexture(GL_TEXTURE_2D, mapid1);
glActiveTexture(GL_TEXTURE1);       glBindTexture(GL_TEXTURE_2D, mapid2);

glUseProgram(shader);

glUniform1i(glGetUniformLocation(gfx.prog, "tex0"), 0);   //GL_TEXTURE0
glUniform1i(glGetUniformLocation(gfx.prog, "tex1"), 1);   //GL_TEXTURE1

render....

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

1 Ответ

7 голосов
/ 06 января 2012

Недостаточно просто привязать эти текстуры к соответствующим единицам. Вы также должны указать шейдерам, откуда взять текстуры для формы sampler2D. Это делается путем установки соответствующего целочисленного равномерного значения в единицу текстуры, которую вы хотите использовать:

//get uniform locations (either init code or render code)
int locTex0 = glGetUniformLocation(program, "tex0");
int locTex1 = glGetUniformLocation(program, "tex1");

...    

//bind textures to texture units
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture0);

//bind program and specify texture units for each sampler2D uniform
glUseProgram(program);
glUniform1i(locTex0, 0);   //use texture bound to GL_TEXTURE0
glUniform1i(locTex1, 1);   //use texture bound to GL_TEXTURE1

...
draw

Конечно, это предполагает, что вы знаете, как использовать шейдеры и указывать одинаковые значения.

Некоторые дополнительные замечания:

  • При использовании фрагментного шейдера вам не нужно вызывать glEnable(GL_TEXTURE_2D), поскольку шейдер решает сам, использует ли он текстуру или нет.
  • Не используйте эти версии функций и констант ARB, по крайней мере, для таких старых и устоявшихся вещей, как мультитекстурирование, которое является ядром со времен GL 1.2 или 1.3 (~ 15 лет).
  • Не ожидайте, что ваш код будет переносимым 1-к-1 к OpenGL ES 2.0, который не знает о старых встроенных атрибутах (например, glVertexPointer или glTexCoordPointer), но это другой вопрос.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...