Gl_UseProgram не влияет на шейдеры - PullRequest
0 голосов
/ 12 октября 2018

Кажется, что моя useProgram не привязывает шейдер, поэтому я не могу установить для него униформу.Но когда я использую GlUseProgram в коде компиляции для шейдера, я могу установить униформу.Я использую менеджер ресурсов для управления шейдерами и текстурами, а также файл Game для управления настройками шейдеров / текстеров / игр.

Shader.h:

class Shader
{
    Shader() {};
    void Compile(const std::string& vertexSource, const std::string& fragmentSource, const char* geometrySource = nullptr);
    Shader  &Use();
}

Shader.cpp

Shader & Shader::Use()
}
    glUseProgram(this->ID);
    return *this;
{

void Shader::Compile(const std::string& vertexSource, const std::string& 
    fragmentSource, const char* geometrySource)
{
    unsigned int vShader, fShader, gShader;

    const char* src1 = vertexSource.c_str();
    const char* src2 = fragmentSource.c_str();

    vShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vShader, 1, &src1, NULL);
    glCompileShader(vShader);
    checkCompileErrors(vShader, "VERTEX");

    fShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShader, 1, &src2, NULL);
    glCompileShader(fShader);
    checkCompileErrors(fShader, "FRAGMENT");

    if (geometrySource != nullptr)
    {
        gShader = glCreateShader(GL_GEOMETRY_SHADER);
        glShaderSource(gShader, 1, &geometrySource, NULL);
        glCompileShader(gShader);
        checkCompileErrors(gShader, "error");
    }

    this->ID = glCreateProgram();
    glAttachShader(this->ID, vShader);
    glAttachShader(this->ID, fShader);

    if (geometrySource != nullptr)
    {
        glAttachShader(this->ID, gShader);
    }
    glLinkProgram(this->ID);
    checkCompileErrors(this->ID, "PROGRAM");

    //glUseProgram(this->ID);

    glDeleteShader(vShader);
    glDeleteShader(fShader);
    if (geometrySource != nullptr)
    {
        glDeleteShader(gShader);
    }
}

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

ResourceManager.h:

class ResourceManager
{
public:
    // Resource storage
    static std::unordered_map<std::string, Shader>    shader;
    static Shader loadShader(const std::string& vShaderSource, std::string filename);
    static Shader getShader(std::string name);
    static Shader loadShaderFromFile(const std::string& vShaderFile);

ResourceManager.cpp

std::unordered_map<std::string, Shader> ResourceManager::shader;
Shader ResourceManager::loadShader(const std::string& vShaderSource, std::string filename)
{
    shader[filename] = loadShaderFromFile(vShaderSource);
    return shader[filename];
}

Shader ResourceManager::getShader(std::string filename)
{
    return shader[filename];
}

Shader ResourceManager::loadShaderFromFile(const std::string& vShaderFile)
{
    enum class ShaderType
    {
        none = -1, vertex = 0, fragment = 1
    };

    std::fstream path(vShaderFile);
    std::stringstream ss[2];
    std::string string;
    ShaderType type = ShaderType::none;

    while (std::getline(path, string))
    {
        if (string.find("shader") != std::string::npos) 
        {
            if (string.find("vertex") != std::string::npos)
            {
                type = ShaderType::vertex;
            }
            if (string.find("fragment") != std::string::npos)
            {
                type = ShaderType::fragment;
            }
        }
        else
            ss[(int)type] << string << "\n";
    }

    std::string vertexCode = ss[0].str();
    std::string fragmentCode = ss[1].str();
    const char* geomtryCode = nullptr;

    Shader shader;
    shader.Compile(vertexCode, fragmentCode);

    return shader;
}

И наконец.Game.cpp:

void Game::Init()
{
    ResourceManager::loadShader("res/Shader/shader.shader", "sprite");
    ResourceManager::getShader("sprite").Use().setUniform1i("image", 0);
    ResourceManager::getShader("sprite").setUniformMatrix4fv("projection", projection);
}

Кто-нибудь объяснит, почему это не работает?

1 Ответ

0 голосов
/ 12 октября 2018

В спецификации 4.6 , раздел 7.1, о DeleteShader() говорится только:

Если шейдер не присоединен к какому-либо программному объекту, он немедленно удаляется.В противном случае шейдер помечается для удаления и будет удален, когда он больше не будет прикреплен к какому-либо программному объекту.

В разделе 7.3 о UseProgram()

INVALID_OPERATIONошибка генерируется, если программа не была успешно связана.Текущее состояние рендеринга не изменяется.

и

Пока используется программный объект, приложения могут изменять вложенные шейдерные объекты, компилировать прикрепленные шейдерные объекты, прикреплятьдополнительные шейдерные объекты и отсоединение шейдерных объектов.Эти операции не влияют на состояние ссылки или исполняемый код программного объекта.

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

Но прочитайте его еще раз и обратите внимание, что он рассказывает о отсоединении шейдеров, а не удалении шейдеров.

Короче говоря, отсоедините aшейдер (glDetachShader) перед его удалением (glDeleteShader).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...