Не могу загрузить несколько текстур в OpenGL - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь загрузить несколько текстур в openGL. Чтобы проверить это, я хочу загрузить 2 текстуры и смешать их со следующим фрагментным шейдером:

#version 330 core

out vec4 color;
in vec2 v_TexCoord;

uniform sampler2D u_Texture0;
uniform sampler2D u_Texture1;

void main()
{
    color = mix(texture(u_Texture0, v_TexCoord), texture(u_Texture1, v_TexCoord), 0.5);
}

У меня есть абстрактная пара функциональных возможностей OpenGL в классы, такие как Shader, Texture UniformXX и т. Д. .

Вот попытка загрузить 2 текстуры в единицы выборки фрагмента:

        Shader shader;
        shader.Attach(GL_VERTEX_SHADER, "res/shaders/vs1.shader");
        shader.Attach(GL_FRAGMENT_SHADER, "res/shaders/fs1.shader");
        shader.Link();
        shader.Bind();

        Texture texture0("res/textures/container.jpg", GL_RGB, GL_RGB);
        texture0.Bind(0);

        Uniform1i textureUnit0Uniform("u_Texture0");
        textureUnit0Uniform.SetValues({ 0 });
        shader.SetUniform(textureUnit0Uniform);

        Texture texture1("res/textures/awesomeface.png", GL_RGBA, GL_RGBA);
        texture1.Bind(1);

        Uniform1i textureUnit1Uniform("u_Texture1");
        textureUnit1Uniform.SetValues({ 1 });
        shader.SetUniform(textureUnit1Uniform);

Вот как выглядит реализация Texture:

#include "Texture.h"
#include "Renderer.h"
#include "stb_image/stb_image.h"

Texture::Texture(const std::string& path, unsigned int destinationFormat, unsigned int sourceFormat)
    : m_Path(path)
{
    stbi_set_flip_vertically_on_load(1);
    m_Buffer = stbi_load(path.c_str(), &m_Width, &m_Height, &m_BPP, 0);

    GLCALL(glGenTextures(1, &m_RendererID));
    GLCALL(glBindTexture(GL_TEXTURE_2D, m_RendererID));
    GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
    GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
    GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
    GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, destinationFormat, m_Width, m_Height, 0, sourceFormat, GL_UNSIGNED_BYTE, m_Buffer));
    glGenerateMipmap(GL_TEXTURE_2D);
    GLCALL(glBindTexture(GL_TEXTURE_2D, 0));

    if (m_Buffer)
        stbi_image_free(m_Buffer);
}

Texture::~Texture()
{
    GLCALL(glDeleteTextures(1, &m_RendererID));
}

void Texture::Bind(unsigned int unit) const
{
    GLCALL(glActiveTexture(GL_TEXTURE0 + unit));
    GLCALL(glBindTexture(GL_TEXTURE_2D, m_RendererID));
}

void Texture::Unbind() const
{
    GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
}

Теперь вместо того, чтобы фактически получить равномерное сочетание цветов из обеих текстур, я получаю только вторую текстуру, которая появляется и смешивается с фоном: enter image description here

Я точно определил проблемуconstructor реализации Texture, если я закомментирую инициализацию второй текстуры, например, что ее constructor никогда не вызывается, тогда я могу заставить отображаться первую текстуру.

Может кто-нибудьподсказать что я делаю не так?

1 Ответ

2 голосов
/ 25 октября 2019

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

Решение должно быть достаточно простым: не чередовать создание текстур и назначение текстурных блоков, сначала создавая текстуры и только , а затем , связывающие их явно.

Еще лучше, рассмотрите использование прямого доступа к состоянию , чтобы избежать всей этой привязки.

Чтобы подчеркнуть проблему для будущих читателей этого вопроса, это проблемная последовательностьвызовов:

// constructor of texture 1
glGenTextures(1, &container)
glBindTexture(GL_TEXTURE_2D, container) // Texture Unit 0 is now bound to container

// explicit texture0.Bind call
glActiveTexture(GL_TEXTURE0) // noop
glBindTexture(GL_TEXTURE_2D, container) // Texture Unit 0 is now bound to container

// constructor of texture 2
glGenTextures(1, &awesomeface)
glBindTexture(GL_TEXTURE_2D, awesomeface) // Texture Unit 0 is now bound to awesomeface instead of container.

// explicit texture1.Bind call
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_2D, awesomeface) // Texture Unit 0 and 1 are now bound to awesomeface.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...