C ++ / OpenGL-如何获取从类继承的正确变量

问题描述 投票:0回答:1

所以问题是我的代码没有运行正确的glUseProgram函数。

我已经测试了它需要什么值并且它可以工作,但是我显然不想对其进行硬编码。

Shader.cpp(我在头文件中声明了programID)

#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

如果我在构造函数中退出programID,我将得到值3,但如果我在Start函数中退出它,我将得到3435973836(总是..我认为)。

我猜继承可能有问题。但是,如果我在Start函数而不是programID中硬编码3,为什么还能工作?

控制台输出(我的programID值更改):

c++ opengl shader
1个回答
1
投票

问题出在对象TestShader的构造函数中:

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

Shader::Shader(VERTEX_FILE, FRAGMENT_FILE);语句没有执行您期望的操作。它不“构造”分别初始化基类,而是在构造函数的主体范围内生成一个全新的对象。

您必须在构造函数的初始化列表中指定基类的构造函数(请参见Constructors and member initializer lists:]

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

注意,在您的代码中,实际上从未设置对象programID的属性TestShader s,因为默认构造函数用于构造基类。但是,另一个对象在TestShader的构造函数的主体中生成。该对象成功生成了着色器程序,并设置了它自己的属性programID(即在输出的第一行中打印的属性)。当然,该对象会立即被销毁,但这没关系,因为OpenGL着色器程序对象仍然存在于GPU上。因此,(“硬编码”)调用glUsePrgram(3)将安装着色器程序。

© www.soinside.com 2019 - 2024. All rights reserved.