Несколько текстур в GLSL - работает только одна

Моя проблема в том, чтобы получить более одной текстуры, доступной в шейдере GLSL. Вот что я делаю:

Shader:

uniform sampler2D sampler0;
uniform sampler2D sampler1;
uniform float blend;
void main( void )
{
    vec2 coords = gl_TexCoord[0];
    vec4 col = texture2D(sampler0, coords);
    vec4 col2 = texture2D(sampler1, coords);
    if (blend > 0.5){
        gl_FragColor = col;
    } else {
        gl_FragColor = col2;
    }
};

Итак, я просто выбираю между двумя значениями цвета на основе равномерной переменной. Достаточно просто (это тест), но вместо ожидаемого поведения я получаю весь черный , когда blend <= 0.5 .

Код OpenGL:

m_sampler0location = m_shader.FindUniform("sampler0");
m_sampler1location = m_shader.FindUniform("sampler1");
m_blendlocation = m_shader.FindUniform("blend");

glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler0location, 0);
glBindTexture(GL_TEXTURE_2D, Texture0.Handle);  
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler1location, 1);
glBindTexture(GL_TEXTURE_2D, Texture1.Handle);
glBegin(GL_QUADS);
    //lower left
    glTexCoord2f(0, 0);
    glVertex2f(-1.0, -1.0);
    //upper left
    glTexCoord2f(0, maxCoords0.t);
    glVertex2f(-1.0, 1.0);
    //upper right
    glTexCoord2f(maxCoords0.s, maxCoords0.t);
    glVertex2f(1.0, 1.0);
    //lower right
    glTexCoord2f(maxCoords0.s, 0);
    glVertex2f(1.0, -1.0);
glEnd()

Шейдер компилируется и связывается перед всем этим , Все проверки работоспособности в этом процессе показывают, что все идет хорошо. As I said, the value of col in the shader program reflects fragments from a texture; the value of col2 is black. The texture that is displayed is the last active texture - if I change the last glBindTexture to bind Texture0.Handle, the texture changes. Fixed according to Bahbar's reply.

As it is, the scene renders all black, even if I add something like gl_FragColor.r = blend; as the last line of the shader. But, if I comment out the call glActiveTexture(GL_TEXTURE1);, the shader works again, and the same texture appears in both sampler0 and sampler1.

What's going on? The line in question, glActiveTexture(GL_TEXTURE1);, seems to work just fine, as evidenced by a subsequent glGetIntegerv(GL_ACTIVE_TEXTURE, &anint). Why does it break everything so horribly? I've already tried upgrading my display drivers.

21
задан genpfault 22 August 2012 в 04:06
поделиться

3 ответа

Вот базовый пример GLUT (написанный для OS X, адаптируйте при необходимости), который генерирует две текстуры шахматной доски, загружает шейдер с двумя сэмплерами и объединяет их, окрашивая каждый (один красный, один синий) и смешивая. Посмотрите, сработает ли это для вас:

#include <stdio.h>
#include <stdlib.h>

#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>

#define kTextureDim 64

GLuint t1;
GLuint t2;

/* adapted from the red book */
GLuint makeCheckTex() {
    GLubyte image[kTextureDim][kTextureDim][4]; // RGBA storage

    for (int i = 0; i < kTextureDim; i++) {
        for (int j = 0; j < kTextureDim; j++) {
            int c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0))*255;
            image[i][j][0]  = (GLubyte)c;
            image[i][j][1]  = (GLubyte)c;
            image[i][j][2]  = (GLubyte)c;
            image[i][j][3]  = (GLubyte)255;
        }
    }

    GLuint texName;
    glGenTextures(1, &texName);    
    glBindTexture(GL_TEXTURE_2D, texName);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureDim, kTextureDim, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

    return texName;
}

void loadShader() {
#define STRINGIFY(A) #A

    const GLchar* source = STRINGIFY(

                                     uniform sampler2D tex1;
                                     uniform sampler2D tex2;

                                     void main() {
                                         vec4 s1 = texture2D(tex1, gl_TexCoord[0].st);
                                         vec4 s2 = texture2D(tex2, gl_TexCoord[0].st + vec2(0.0625, 0.0625));
                                         gl_FragColor = mix(vec4(1, s1.g, s1.b, 0.5), vec4(s2.r, s2.g, 1, 0.5), 0.5);
                                     }

                                     );

    GLuint program = glCreateProgram();
    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);

    GLint logLength;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar* log = (GLchar*)malloc(logLength);
        glGetShaderInfoLog(shader, logLength, &logLength, log);
        printf("Shader compile log:\n%s\n", log);
        free(log);
    }

    glAttachShader(program, shader);  
    glLinkProgram(program);

    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar* log = (GLchar*)malloc(logLength);
        glGetProgramInfoLog(program, logLength, &logLength, log);
        printf("Program link log:\n%s\n", log);
        free(log);
    }

    GLuint t1Location = glGetUniformLocation(program, "tex1");
    GLuint t2Location = glGetUniformLocation(program, "tex2");

    glUniform1i(t1Location, 0);
    glUniform1i(t2Location, 1);

    glUseProgram(program);
}


void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_FLAT);

    t1 = makeCheckTex();
    t2 = makeCheckTex();

    loadShader();
}


void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, t1);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, t2);

    glBegin(GL_QUADS);
    //lower left
    glTexCoord2f(0, 0);
    glVertex2f(-1.0, -1.0);
    //upper left
    glTexCoord2f(0, 1.0);
    glVertex2f(-1.0, 1.0);
    //upper right
    glTexCoord2f(1.0, 1.0);
    glVertex2f(1.0, 1.0);
    //lower right
    glTexCoord2f(1.0, 0);
    glVertex2f(1.0, -1.0);
    glEnd();

    glutSwapBuffers();
}


void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2, 2, -2, 2, -2, 2);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


int main(int argc, char **argv)
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);

    glutInitWindowSize(512, 512);
    glutInitWindowPosition(0, 0);

    glutCreateWindow("GLSL Texture Blending");

    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(display);

    init();

    glutMainLoop();
    return 0;
}

Надеюсь, результат будет выглядеть примерно так (вы можете закомментировать вызов glUseProgram, чтобы увидеть первую текстуру, нарисованную без шейдера): alt text

22
ответ дан 29 November 2019 в 20:28
поделиться

Похоже, ваш вызов glActiveTexture не работает. Вы уверены, что правильно настроили указатель функции?

Подтвердите, вызвав glGetIntegerv (GL_ACTIVE_TEXTURE, & anint) после вызова glActiveTexture (GL_TEXTURE1).

Также glEnable (GL_TEXTURE_2D) бесполезны. Сам шейдер определяет, какие текстурные блоки использовать и какую цель каждого блока «включить».


Отредактируйте, чтобы добавить:

Что ж, ваша новая ситуация особенная. Тот факт, что вы даже не можете показать красный цвет, особенно странен (ну, вы установили альфа на 1, чтобы убедиться?).

Тем не менее, вы должны восстановить GL_TEXTURE0 как glActiveTexture после того, как вы закончите установку текстурного блока 1 (то есть после вызова glBindTexture ).

0
ответ дан 29 November 2019 в 20:28
поделиться

При компиляции вашего шейдера для тестирования я обнаружил две ошибки:

  1. coords должны быть назначены st части 4-компонентного gl_TexCoord, например

    vec2 coords = gl_TexCoord[0].st;
    
  2. Шейдер не должен заканчиваться точкой с запятой.

Проверяете ли вы где-нибудь в своей основной программе правильность компиляции шейдера? Вы можете посмотреть GL_COMPILE_STATUS через glGetShader и glGetShaderInfoLog.

2
ответ дан 29 November 2019 в 20:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: