C ++ / OpenGL - Как получить правильную переменную, унаследованную от класса - PullRequest
0 голосов
/ 26 октября 2019

Таким образом, проблема в том, что мой код не выполняет правильную функцию glUseProgram.

Я проверил, какое значение ему нужно, и оно работает, но я, очевидно, не хочу его жестко кодировать.

Shader.cpp (я объявил ID программы в заголовочном файле)

#include "Shader.h"

#include <GL/glew.h>
#include <iostream>
#include <fstream>

GLuint vertexShaderID, fragmentShaderID;

Shader::Shader() {

}

Shader::Shader(const GLchar* vertexFile, const GLchar* fragmentFile) {
    GLint success;
    GLchar infoLog[512];

    vertexShaderID = loadShader(vertexFile, GL_VERTEX_SHADER);
    fragmentShaderID = loadShader(fragmentFile, GL_FRAGMENT_SHADER);
    programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);
    //glValidateProgram(programID);

    glGetProgramiv(programID, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(programID, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    //bindAttributes();

    std::cout << "SHADER::LOADED\n" << std::endl;

    glDeleteShader(vertexShaderID);
    glDeleteShader(fragmentShaderID);
    std::cout << "PROGRAM::" << programID << std::endl;
}

void Shader::Start() const
{
    glUseProgram(programID);
    std::cout << "p:" << programID << std::endl;
}

void Shader::cleanUp() {
    glUseProgram(0);
    glDetachShader(programID, vertexShaderID);
    glDetachShader(programID, fragmentShaderID);
    glDeleteShader(vertexShaderID);
    glDeleteShader(fragmentShaderID);
    glDeleteProgram(programID);
}

TestShader.cpp

#include "TestShader.h"
#include "Shader.h"

const GLchar* VERTEX_FILE = "shaders/shader.vs";
const GLchar* FRAGMENT_FILE = "shaders/shader.frag";

TestShader::TestShader() {
    Shader::Shader(VERTEX_FILE, FRAGMENT_FILE);

}

main.cpp

#include <iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

// SOIL
#include <SOIL2/SOIL2.h>

// GLM
#include <GLM/glm.hpp>

// Other includes
#include "TestShader.h"

// GameEngine
#include "Display.h"
#include "Mesh.h"

const GLuint WIDTH = 800, HEIGHT = 600;

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    Display display(WIDTH, HEIGHT, "GameEngine");

    glewExperimental = GL_TRUE;
    glewInit();

    TestShader s;

    Vertex vertices[] = {
        Vertex(glm::vec3(-0.5 , -0.5, 0)),
        Vertex(glm::vec3(0, 0.5, 0)),
        Vertex(glm::vec3(0.5, -0.5, 0))
    };

    Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));


    while (!display.IsClosed())
    {
        glfwPollEvents();

        display.Clear(0.0f, 0.0f, 0.3f, 0.0f);

        s.Start();

        mesh.Draw();

        s.cleanUp();

        display.Update();
    }

    glfwTerminate();
    return 0;
}

TestShader.h

#ifndef TESTSHADER_H
#define TESTSHADER_H

#include "Shader.h"

#include <GL/glew.h>
#include <iostream>

class TestShader : public Shader {
public:
    TestShader();
private:
protected:
    void bindAttributes() override;
};

#endif // TESTSHADER_H

Shader.h

#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>

class Shader
{
private:
    GLuint programID;

protected:
    int getUniformLocation(GLchar * uniformName);

public:
    Shader();
    Shader(const GLchar* vertexFile, const GLchar* fragmentFile);
    ~Shader();

    GLuint loadShader(const GLchar * shaderSourcePath, GLuint type);

    virtual void bindAttributes();
    void bindAttribute(int attribute, GLchar* variableName);
    void Start() const;
    void cleanUp();
};

#endif // !SHADER_H

Если я указываю ID программы в конструкторе, я получаю значение 3, но если я его показываю в функции Start, я получаюa 3435973836 (всегда .. я думаю).

Вероятно, есть проблема с наследованием, я думаю. Но почему это работает, если я жестко закодировал 3 в функции «Пуск» вместо идентификатора программы?

Вывод на консоли (изменилось значение моего ID программы):

1 Ответ

1 голос
/ 26 октября 2019

Проблема в конструкторе объекта TestShader:

TestShader::TestShader() {
   Shader::Shader(VERTEX_FILE, FRAGMENT_FILE);
}

Оператор Shader::Shader(VERTEX_FILE, FRAGMENT_FILE); не делает того, чего вы ожидаете. Он не «конструирует», соответственно, инициализирует базовый класс, он генерирует совершенно новый объект в области видимости тела конструктора.

Вы должны указать конструктор базового класса в списке инициализаторов. конструктора (см. Конструкторы и списки инициализаторов ):

TestShader::TestShader() 
  : Shader(VERTEX_FILE, FRAGMENT_FILE) {
}

Обратите внимание, что в вашем коде фактически атрибут programID объекта TestShader s никогда не устанавливается, потому чтоКонструктор по умолчанию используется для создания базового класса.
Но в теле конструктора TestShader создается другой объект. Этот объект успешно генерирует шейдерную программу и устанавливает свой собственный атрибут programID (то есть то, что напечатано в первой строке вывода).
Конечно, этот объект уничтожается сразу, но это не имеет значения, так какпрограммный объект шейдера OpenGL все еще существует в графическом процессоре. Поэтому («жестко закодированный») вызов glUsePrgram(3) устанавливает программу шейдера.

...