C++ Opengl着色器不能处理多个文件

C++ Opengl着色器不能处理多个文件,c++,opengl,C++,Opengl,我正在学习opengl,并遵循从开始的2D游戏教程,一旦我达到了屏幕上应该显示的部分,就什么也没有画出来。经过几天的挫折之后,我终于能够将问题缩小到程序停止前调用的着色器类析构函数。但是当我把所有的绘图代码放在一个文件中时,没有调用析构函数,所有的东西都画得很好。我最近通过从资源管理器中的getter返回指针修复了析构函数问题。然而,它仍然没有吸引人。我的代码在这里: Main.cpp #include <iostream> #include <GL/glew.h> #i

我正在学习opengl,并遵循从开始的2D游戏教程,一旦我达到了屏幕上应该显示的部分,就什么也没有画出来。经过几天的挫折之后,我终于能够将问题缩小到程序停止前调用的着色器类析构函数。但是当我把所有的绘图代码放在一个文件中时,没有调用析构函数,所有的东西都画得很好。我最近通过从资源管理器中的getter返回指针修复了析构函数问题。然而,它仍然没有吸引人。我的代码在这里:

Main.cpp

#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);}遗憾的是,这也不行。