C++ Opengl着色器不能处理多个文件
我正在学习opengl,并遵循从开始的2D游戏教程,一旦我达到了屏幕上应该显示的部分,就什么也没有画出来。经过几天的挫折之后,我终于能够将问题缩小到程序停止前调用的着色器类析构函数。但是当我把所有的绘图代码放在一个文件中时,没有调用析构函数,所有的东西都画得很好。我最近通过从资源管理器中的getter返回指针修复了析构函数问题。然而,它仍然没有吸引人。我的代码在这里: Main.cppC++ Opengl着色器不能处理多个文件,c++,opengl,C++,Opengl,我正在学习opengl,并遵循从开始的2D游戏教程,一旦我达到了屏幕上应该显示的部分,就什么也没有画出来。经过几天的挫折之后,我终于能够将问题缩小到程序停止前调用的着色器类析构函数。但是当我把所有的绘图代码放在一个文件中时,没有调用析构函数,所有的东西都画得很好。我最近通过从资源管理器中的getter返回指针修复了析构函数问题。然而,它仍然没有吸引人。我的代码在这里: Main.cpp #include <iostream> #include <GL/glew.h> #i
#include <iostream>
#include <GL/glew.h>
#include <SFML/Graphics.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Game.hpp"
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "Test", sf::Style::Default, sf::ContextSettings(3, 3));
if (!glewInit() == GLEW_OK) {
std::cout << "Failed to initialize GLEW!";
return -1;
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Game::Game game(800.f, 600.f);
game.__init__();
sf::Clock clock;
float deltaTime = 0.f;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
glClearColor(0.1f, 0.1f, 0.1f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
game.render();
window.display();
}
Resource::ResourceManager::__delete__();
return 0;
}
#pragma once
#include "Resources/ResourceManager.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <map>
namespace Game {
enum class GameState {
TITLE,
ACTIVE,
PAUSED,
WIN,
LOOSE
};
class Game
{
public:
Game(float w_width, float w_height);
~Game();
void __init__();
void setKey(sf::Keyboard::Key key, bool isPressed);
void update();
void render();
private:
GLuint _vao;
float _w_width;
float _w_height;
std::map<sf::Keyboard::Key, bool> _key_states;
};
};
#include "Game.hpp"
namespace Game {
Game::Game(float w_width, float w_height)
{
_w_width = w_width;
_w_height = w_height;
}
Game::~Game()
{
}
void Game::__init__()
{
glm::mat4 Projection = glm::ortho(0.f, _w_width, _w_height, 0.f, -1.f, 1.f);
glm::mat4 Model = glm::scale(glm::mat4(1.f), glm::vec3(100.f, 70.f, 1.f));
Resource::ResourceManager::addShader(0, "Shaders/simpleVertexShader.glsl", "Shaders/simpleFragmentShader.glsl");
Resource::ResourceManager::addTexture(0, "Textures/block.png");
Resource::ResourceManager::addTexture(1, "Textures/block_solid.png");
Resource::ResourceManager::addTexture(2, "Textures/background.jpg");
Resource::Shader* main_shader = Resource::ResourceManager::getShader(0);
main_shader->setMat4("Projection", Projection);
main_shader->setMat4("Model", Model);
main_shader->setVec3("Color", glm::vec3(0.1, 0.8, 0.1));
glGenVertexArrays(1, &_vao);
GLfloat vertex_data[] = {
0.f, 0.f, 0.f, 0.f,
1.f, 0.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f,
0.f, 1.f, 0.f, 1.f,
0.f, 0.f, 0.f, 0.f
};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Game::setKey(sf::Keyboard::Key key, bool isPressed)
{
_key_states[key] = isPressed;
}
void Game::update()
{
}
void Game::render()
{
Resource::Texture* texture = Resource::ResourceManager::getTexture(0);
Resource::Shader* shader = Resource::ResourceManager::getShader(0);
texture->bind();
shader->use();
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
};
#pragma once
#include <unordered_map>
#include <fstream>
#include <string>
#include <iostream>
#include "Shader.hpp"
#include "Texture.hpp"
namespace Resource {
class ResourceManager {
public:
static void addShader(uint8_t id, std::string vertexShaderSource, std::string fragmentShaderSource);
static void addTexture(uint8_t id, std::string imageSource);
static Shader* getShader(uint8_t id);
static Texture* getTexture(uint8_t id);
static void __delete__();
private:
ResourceManager() {}
static std::string _loadShaderFromFile(std::string shaderSource);
public:
static std::unordered_map<uint8_t, Shader*> _shaders;
static std::unordered_map<uint8_t, Texture*> _textures;
};
};
#include "ResourceManager.hpp"
namespace Resource {
std::unordered_map<uint8_t, Shader*> ResourceManager::_shaders;
std::unordered_map<uint8_t, Texture*> ResourceManager::_textures;
void ResourceManager::addShader(uint8_t id, std::string vertexShaderSource, std::string fragmentShaderSource)
{
_shaders[id] = new Shader(_loadShaderFromFile(vertexShaderSource).c_str(), _loadShaderFromFile(fragmentShaderSource).c_str());
}
void ResourceManager::addTexture(uint8_t id, std::string imageSource)
{
_textures[id] = new Texture(imageSource);
}
Shader* ResourceManager::getShader(uint8_t id)
{
return _shaders[id];
}
Texture* ResourceManager::getTexture(uint8_t id)
{
return _textures[id];
}
void ResourceManager::__delete__()
{
for (auto iter : _shaders) {
delete iter.second;
}
for (auto iter : _textures) {
delete iter.second;
}
}
std::string ResourceManager::_loadShaderFromFile(std::string shaderSource)
{
std::ifstream file(shaderSource);
if (!file.is_open()) {
std::cout << "Failed to load shader: " << shaderSource << "!" << std::endl;
return "";
}
std::string line;
std::string lines;
while (std::getline(file, line)) {
lines += line + '\n';
}
return lines;
}
};
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
namespace Resource {
class Shader {
public:
Shader(const char* vertexShaderSource, const char* fragmentShaderSource);
Shader();
~Shader();
void use();
void setMat4(const char* location, glm::mat4 matrix);
void setVec3(const char* location, glm::vec3 vector);
void setVec4(const char* location, glm::vec4 vector);
void printID();
Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete;
private:
GLuint _id;
};
};
#include "Shader.hpp"
#include <iostream>
namespace Resource {
Shader::Shader(const char* vertexShaderSource, const char* fragmentShaderSource)
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
_id = glCreateProgram();
glAttachShader(_id, vertexShader);
glAttachShader(_id, fragmentShader);
glLinkProgram(_id);
glDetachShader(_id, vertexShader);
glDetachShader(_id, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
Shader::Shader()
{
}
Shader::~Shader()
{
glDeleteProgram(_id);
}
void Shader::use()
{
glUseProgram(_id);
}
void Shader::setMat4(const char* location, glm::mat4 matrix)
{
glUniformMatrix4fv(glGetUniformLocation(_id, location), 1, GL_FALSE, &matrix[0][0]);
}
void Shader::setVec3(const char* location, glm::vec3 vector)
{
glUniform3fv(glGetUniformLocation(_id, location), 1, &vector[0]);
}
void Shader::setVec4(const char* location, glm::vec4 vector)
{
glUniform4fv(glGetUniformLocation(_id, location), 1, &vector[0]);
}
void Shader::printID()
{
std::cout << _id << std::endl;
}
};
#pragma once
#include <GL/glew.h>
#include <SFML/Graphics/Image.hpp>
namespace Resource {
class Texture {
public:
Texture(std::string image_src);
Texture();
~Texture();
void bind();
Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete;
private:
GLuint _id;
};
}
#include "Texture.hpp"
namespace Resource {
Texture::Texture(std::string image_src)
{
glGenTextures(1, &_id);
bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
sf::Image texture;
texture.loadFromFile(image_src);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.getSize().x, texture.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getPixelsPtr());
}
Texture::Texture()
{
}
Texture::~Texture()
{
glDeleteTextures(1, &_id);
}
void Texture::bind()
{
glBindTexture(GL_TEXTURE_2D, _id);
}
};
ResourceManager.hpp
#include <iostream>
#include <GL/glew.h>
#include <SFML/Graphics.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Game.hpp"
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "Test", sf::Style::Default, sf::ContextSettings(3, 3));
if (!glewInit() == GLEW_OK) {
std::cout << "Failed to initialize GLEW!";
return -1;
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Game::Game game(800.f, 600.f);
game.__init__();
sf::Clock clock;
float deltaTime = 0.f;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
glClearColor(0.1f, 0.1f, 0.1f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
game.render();
window.display();
}
Resource::ResourceManager::__delete__();
return 0;
}
#pragma once
#include "Resources/ResourceManager.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <map>
namespace Game {
enum class GameState {
TITLE,
ACTIVE,
PAUSED,
WIN,
LOOSE
};
class Game
{
public:
Game(float w_width, float w_height);
~Game();
void __init__();
void setKey(sf::Keyboard::Key key, bool isPressed);
void update();
void render();
private:
GLuint _vao;
float _w_width;
float _w_height;
std::map<sf::Keyboard::Key, bool> _key_states;
};
};
#include "Game.hpp"
namespace Game {
Game::Game(float w_width, float w_height)
{
_w_width = w_width;
_w_height = w_height;
}
Game::~Game()
{
}
void Game::__init__()
{
glm::mat4 Projection = glm::ortho(0.f, _w_width, _w_height, 0.f, -1.f, 1.f);
glm::mat4 Model = glm::scale(glm::mat4(1.f), glm::vec3(100.f, 70.f, 1.f));
Resource::ResourceManager::addShader(0, "Shaders/simpleVertexShader.glsl", "Shaders/simpleFragmentShader.glsl");
Resource::ResourceManager::addTexture(0, "Textures/block.png");
Resource::ResourceManager::addTexture(1, "Textures/block_solid.png");
Resource::ResourceManager::addTexture(2, "Textures/background.jpg");
Resource::Shader* main_shader = Resource::ResourceManager::getShader(0);
main_shader->setMat4("Projection", Projection);
main_shader->setMat4("Model", Model);
main_shader->setVec3("Color", glm::vec3(0.1, 0.8, 0.1));
glGenVertexArrays(1, &_vao);
GLfloat vertex_data[] = {
0.f, 0.f, 0.f, 0.f,
1.f, 0.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f,
0.f, 1.f, 0.f, 1.f,
0.f, 0.f, 0.f, 0.f
};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Game::setKey(sf::Keyboard::Key key, bool isPressed)
{
_key_states[key] = isPressed;
}
void Game::update()
{
}
void Game::render()
{
Resource::Texture* texture = Resource::ResourceManager::getTexture(0);
Resource::Shader* shader = Resource::ResourceManager::getShader(0);
texture->bind();
shader->use();
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
};
#pragma once
#include <unordered_map>
#include <fstream>
#include <string>
#include <iostream>
#include "Shader.hpp"
#include "Texture.hpp"
namespace Resource {
class ResourceManager {
public:
static void addShader(uint8_t id, std::string vertexShaderSource, std::string fragmentShaderSource);
static void addTexture(uint8_t id, std::string imageSource);
static Shader* getShader(uint8_t id);
static Texture* getTexture(uint8_t id);
static void __delete__();
private:
ResourceManager() {}
static std::string _loadShaderFromFile(std::string shaderSource);
public:
static std::unordered_map<uint8_t, Shader*> _shaders;
static std::unordered_map<uint8_t, Texture*> _textures;
};
};
#include "ResourceManager.hpp"
namespace Resource {
std::unordered_map<uint8_t, Shader*> ResourceManager::_shaders;
std::unordered_map<uint8_t, Texture*> ResourceManager::_textures;
void ResourceManager::addShader(uint8_t id, std::string vertexShaderSource, std::string fragmentShaderSource)
{
_shaders[id] = new Shader(_loadShaderFromFile(vertexShaderSource).c_str(), _loadShaderFromFile(fragmentShaderSource).c_str());
}
void ResourceManager::addTexture(uint8_t id, std::string imageSource)
{
_textures[id] = new Texture(imageSource);
}
Shader* ResourceManager::getShader(uint8_t id)
{
return _shaders[id];
}
Texture* ResourceManager::getTexture(uint8_t id)
{
return _textures[id];
}
void ResourceManager::__delete__()
{
for (auto iter : _shaders) {
delete iter.second;
}
for (auto iter : _textures) {
delete iter.second;
}
}
std::string ResourceManager::_loadShaderFromFile(std::string shaderSource)
{
std::ifstream file(shaderSource);
if (!file.is_open()) {
std::cout << "Failed to load shader: " << shaderSource << "!" << std::endl;
return "";
}
std::string line;
std::string lines;
while (std::getline(file, line)) {
lines += line + '\n';
}
return lines;
}
};
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
namespace Resource {
class Shader {
public:
Shader(const char* vertexShaderSource, const char* fragmentShaderSource);
Shader();
~Shader();
void use();
void setMat4(const char* location, glm::mat4 matrix);
void setVec3(const char* location, glm::vec3 vector);
void setVec4(const char* location, glm::vec4 vector);
void printID();
Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete;
private:
GLuint _id;
};
};
#include "Shader.hpp"
#include <iostream>
namespace Resource {
Shader::Shader(const char* vertexShaderSource, const char* fragmentShaderSource)
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
_id = glCreateProgram();
glAttachShader(_id, vertexShader);
glAttachShader(_id, fragmentShader);
glLinkProgram(_id);
glDetachShader(_id, vertexShader);
glDetachShader(_id, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
Shader::Shader()
{
}
Shader::~Shader()
{
glDeleteProgram(_id);
}
void Shader::use()
{
glUseProgram(_id);
}
void Shader::setMat4(const char* location, glm::mat4 matrix)
{
glUniformMatrix4fv(glGetUniformLocation(_id, location), 1, GL_FALSE, &matrix[0][0]);
}
void Shader::setVec3(const char* location, glm::vec3 vector)
{
glUniform3fv(glGetUniformLocation(_id, location), 1, &vector[0]);
}
void Shader::setVec4(const char* location, glm::vec4 vector)
{
glUniform4fv(glGetUniformLocation(_id, location), 1, &vector[0]);
}
void Shader::printID()
{
std::cout << _id << std::endl;
}
};
#pragma once
#include <GL/glew.h>
#include <SFML/Graphics/Image.hpp>
namespace Resource {
class Texture {
public:
Texture(std::string image_src);
Texture();
~Texture();
void bind();
Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete;
private:
GLuint _id;
};
}
#include "Texture.hpp"
namespace Resource {
Texture::Texture(std::string image_src)
{
glGenTextures(1, &_id);
bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
sf::Image texture;
texture.loadFromFile(image_src);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.getSize().x, texture.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getPixelsPtr());
}
Texture::Texture()
{
}
Texture::~Texture()
{
glDeleteTextures(1, &_id);
}
void Texture::bind()
{
glBindTexture(GL_TEXTURE_2D, _id);
}
};
我也有点新的C++,所以如果有任何明显的改进,请提前表示歉意。
< P>指定当前程序对象的统一变量的值。 这意味着您必须调用以将propper程序对象安装为当前渲染状态的一部分,然后才能通过glUniform*
设置统一的值
这意味着您必须先安装main\u着色器
,然后才能在方法游戏中设置制服的值::\uuuuu init\uuuu
来解决此问题:
main_shader->use();
main_shader->setMat4("Projection", Projection);
main_shader->setMat4("Model", Model);
main_shader->setVec3("Color", glm::vec3(0.1, 0.8, 0.1));
或者,您可以使用(从OpenGL 4.1开始),它允许您指定程序对象,其中的值应设置为
第二个问题是,
GL\u ARRAY\u BUFFER
不是的有效枚举常量。如果您通过检查OpenGL错误,您将得到GL\u INVALID\u ENUM
错误
在您的情况下,您必须使用GL\u三角形
:
glDrawArrays(GL_TRIANGLES, 0, 6);
请在问题本身中包含重现问题所需的最低相关代码。与非网站资源的链接往往会中断,这使得答案对未来的访问者来说毫无用处。我稍微改变了这个问题。这与他们的问题不同。不是asnwer,而是带有双下划线的标识符是保留的,不应该使用:我尝试了你的建议,但仍然不起作用。当你调用glUniform*时,它需要为着色器中的变量提供一个id,你可以通过glGetUniformLocation获得该变量。因此,我认为您不需要绑定着色器程序。是的。这就是我在评论中打算使用的方式。例如,glUniformMatrix4fv(glGetUniformLocation(programmaid,“VARABLE_name”)、1、GL_FALSE和矩阵[0][0])。如果不是那样的话,我很抱歉。让这种事情发生我觉得很愚蠢。我现在修复了这个问题,不管出于什么原因,它仍然没有绘制;输出vec2uv;均匀mat4投影;统一mat4模型;void main(){uv=vertex.zw;gl_Position=Projection*Model*vec4(vertex.xy,0.0,1.0);}遗憾的是,这也不行。