所以问题是我的代码没有运行正确的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,为什么还能工作?
问题出在对象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)
将安装着色器程序。