Почему эта текстура полностью черная?

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

Вот код:

void doGL2() {

    glTranslatef(0.f, 0.f, 0.f);

    const GLchar* vertShader[] = { R"glsl(
            #version 330 core
            layout (location = 0) in vec3 aPos;
            layout (location = 1) in vec3 aColor;
            layout (location = 2) in vec2 aTexPos;

            out vec3 col;
            out vec2 texturePos;

            void main()
            {
                gl_Position = vec4(aPos, 1.0);
                col = aColor;
                texturePos = aTexPos;
            }
        )glsl" };



    const GLchar* fragShader[] = { R"glsl(
            #version 330 core
            out vec4 FragColor;

            in vec3 col;
            in vec2 texturePos;
            
            uniform sampler2D t;
            
            uniform vec2 iResolution;
            
            
            void main()
            {
                vec2 uv = gl_FragCoord.xy / iResolution;
                //FragColor = vec4(iResolution, 1., 1.);
                FragColor = mix(vec4(col, 1.0f), texture(t, gl_FragCoord.xy / vec2(1200., 675.)), 1.);
            }
        )glsl" };



    vShader2 = glCreateShader(GL_VERTEX_SHADER);
    fShader2 = glCreateShader(GL_FRAGMENT_SHADER);



    glShaderSource(vShader2, 1, vertShader, NULL);
    glCompileShader(vShader2);

    GLint success;
    GLchar infoLog[1024];
    glGetShaderiv(vShader2, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vShader2, 1024, NULL, infoLog);
        throw std::runtime_error("\noh no vert\n");
    }




    glShaderSource(fShader2, 1, fragShader, NULL);
    glCompileShader(fShader2);

    glGetShaderiv(fShader2, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fShader2, 1024, NULL, infoLog);
        throw std::runtime_error("\noh no frag\n");
    }




    shaderProgram2 = glCreateProgram();

    glAttachShader(shaderProgram2, vShader2);
    glAttachShader(shaderProgram2, fShader2);

    glLinkProgram(shaderProgram2);

    GLfloat screen[2] = { 1200.0f, 675.0f };
    glUseProgram(shaderProgram2);

    glUniform2fv(glGetUniformLocation(shaderProgram2, "iResolution"), 2, screen);
    glUniform1i(glGetUniformLocation(shaderProgram2, "t"), 10);

    //not sure if I should do this on cleanup or now
    glDeleteShader(vShader2);
    glDeleteShader(fShader2);


    
    //lets make a temporary test texture
    int width, height, channels;
    unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);


    GLuint tempT = 1;

    glActiveTexture(GL_TEXTURE10);
    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &tempT);
    glBindTexture(GL_TEXTURE_2D, tempT);
    // set texture options
    
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    //glPixelStorei(GL_UNPACK_ALIGNMENT, 2);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

    stbi_image_free(data);
    
    
    

    GLfloat vertices[] = {
        // positions         // colors          // texture positions
         0.0f,  0.0f, 1.0f,  1.0f, 0.0f, 0.0f,  0.0f, 0.0f,         // bottom left
         1.0f,  0.0f, 1.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f,         // bottom right
         1.0f,  1.0f, 1.0f,  0.0f, 0.0f, 1.0f,  1.0f, 1.0f          // top right
         ,
         0.0f,  0.0f, 1.0f,  1.0f, 0.0f, 0.0f,  0.0f, 0.0f,         // bottom left
         0.0f,  1.0f, 1.0f,  0.0f, 1.0f, 0.0f,  0.0f, 1.0f,         // top left
         1.0f,  1.0f, 1.0f,  0.0f, 0.0f, 1.0f,  1.0f, 1.0f          // top right
    };

    glGenVertexArrays(1, &VAO2);
    glGenBuffers(1, &VBO2);

    glBindVertexArray(VAO2);

    glBindBuffer(GL_ARRAY_BUFFER, VBO2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //positions
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    //colors
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    //texture positions
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    

    float initTime = glutGet(GLUT_ELAPSED_TIME);
    float prevTime = initTime;
    float dt = 0.0f;
    while (prevTime - initTime < 1000.0f) {
        

        dt = (glutGet(GLUT_ELAPSED_TIME) - prevTime) / 1000.0f;
        prevTime = glutGet(GLUT_ELAPSED_TIME);

        glClearColor(1.f, 1.f, 1.f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);

        
        glBindVertexArray(VAO2);
        
        glBindTexture(GL_TEXTURE_2D, tempT);
        
        glDrawArrays(GL_TRIANGLES, 0, 6);
        
        SwapBuffers(GetDC(w));
        glFlush();
    }

}

По какой-то причине, когда я вместо этого привязываю текстуру к GL_TEXTURE0, она отображает текстуру.

Редактировать: Я делаю дальнейшее редактирование, так как содержание моего исходного вопроса не решает проблему должным образом. Кажется, я не могу привязать любую текстуру к любой текстуре, кроме GL_TEXTURE0. Я видел другие форумы с этой проблемой, но все ответы на эти проблемы касаются других проблем, которых здесь нет. Как видите, я пытаюсь привязать эту текстуру к GL_TEXTURE10, однако на выходе все черное. Однако, когда я привязываюсь к GL_TEXTURE0, текстура отображается нормально. Я изменил код, чтобы отразить ответ Rabbid, поскольку это действительно были ошибки, но не ошибки, которые повлияли на эту проблему; код актуален, отражая текущую проблему.

Кроме того, я напечатал tempT, и он всегда возвращается как 1, что означает, что он каждый раз привязывается к GL_TEXTURE0, несмотря на то, что я вызываю glActiveTexture().

Других проблем с вашим кодом нет, я его проверил. Какая у вас система? Это исходный код? В какой среде вы запускаете код?

Rabbid76 08.05.2022 10:27
«Кроме того, я напечатал tempT, и он всегда возвращает значение 1, что означает, что он каждый раз привязывается к GL_TEXTURE0, несмотря на то, что я вызываю в glActiveTexture()». — Текстурный модуль не имеет ничего общего с идентификатором объекта текстуры. tempT не указывает на текстурный блок! Вы должны установить текстурный блок перед привязкой текстуры (до glBindTexture), но это не имеет никакого эффекта. glGenTextures.
Rabbid76 08.05.2022 10:28

Я добавил несколько предложений к ответу.

Rabbid76 08.05.2022 10:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
116
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы не генерируете мип-картыglGenerateMipmap), важно установить GL_TEXTURE_MIN_FILTER. Поскольку фильтр по умолчанию — GL_NEAREST_MIPMAP_LINEAR, текстура будет иметь статус «Mipmap Incomplete», если вы не измените функцию минимизации на GL_NEAREST или GL_LINEAR.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Кроме того, вместо (1, 1) необходимо указать размер изображения (with, height):

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

Не гарантируется, что stbi_load создаст текстуру с 4 цветовыми каналами. Заставьте stbi_load генерировать изображение с 4 цветовыми каналами, явно передав 4 последнему параметру:

unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);

unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 4);

Если вы используете шейдерную программу, вам не нужно включать текстурирование. Используется ли текстура или нет, решается в шейдерной программе. glEnable(GL_TEXTURE_2D); — это устаревший OpenGL, удалите его.


Помимо того, что ваш код работает нормально, я его протестировал. Однако количество текстурных блоков ограничено. Убедитесь, что вы используете текстурный блок в пределах досягаемости вашей системы. Вы можете получить количество текстурных блоков с помощью GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. например.:

int max_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units);
std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS " << max_units << std::endl;

Also, I printed tempT and it always returns as 1, meaning it is binding to GL_TEXTURE0 every time despite what I call in glActiveTexture().

Блок текстуры не имеет ничего общего с идентификатором объекта текстуры. Значение tempT не указывает на текстурный блок, в котором текстура будет привязана. Вы должны установить текстурный блок перед привязкой текстуры с помощью glBindTexture, но это не влияет на glGenTextures. Вы можете привязать текстуру к нескольким текстурным модулям или к разным текстурным модулям в разное время. Блок текстуры — это точка привязки между объектом текстуры и юниформом сэмплера текстуры. Если вы хотите использовать текстуру в шейдерной программе, вам необходимо убедиться, что текстура привязана к текстурному модулю, и этот модуль настроен на равномерный сэмплер текстуры.

Я предлагаю установить текстурный блок перед привязкой текстуры и использовать его для рисования объекта:

GLint t_location = glGetUniformLocation(shaderProgram2, "t")
glUseProgram(shaderProgram2);
glUniform1i(t_location, 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);

@BradenYonano Я добавил в ответ несколько новых предложений.

Rabbid76 08.05.2022 10:43

Итак, если идентификатор текстуры, в данном случае tempT, не является текстурным блоком, то я не должен передавать идентификатор текстуры в юниформ-сэмплер в шейдере, тогда правильно? Если это так, то как мне связать единицу с идентификатором текстуры, например, если бы у меня было 100 текстур? Мой код работает с этими изменениями, но только потому, что у меня есть 1 текстура. Мне просто интересно, что бы я передал в униформу, если я не могу передать идентификатор текстуры.

Braden Yonano 09.05.2022 03:00

@BradenYonano "как связать единицу с идентификатором текстуры, например, если бы у меня было 100 текстур" — Вы не можете использовать 100 разных текстур в одном шейдере одновременно. (ГП не может кэшировать все эти текстуры сразу и обрабатывать их с хорошей производительностью). Вы должны использовать GL_TEXTURE_2D_ARRAY или атлас текстур.

Rabbid76 09.05.2022 06:56

Итак, у меня есть код для работы со 128 текстурами, которые я использую (я визуализирую текст), но он довольно медленный, так как символов становится все больше. Я считаю, что на этот вопрос был дан полный ответ. Спасибо за ваше понимание!

Braden Yonano 09.05.2022 23:37

Другие вопросы по теме