OpenGL使用精灵图集

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/czhzasui/article/details/83545269

使用OpenGL绘制开机动画,fps30,使用精灵图集
使用OpenCV载入纹理。
运行环境ubuntu16,
废话不多说,上源码。

主程序main.cpp

//
// Created by czh on 18-9-10.
//

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "animation.h"
#include "dconfig.h"

Animation animation(SCREEN_WIDTH, SCREEN_HEIGHT);

void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
    if (key >= 0 && key < 1024) {
        if (action == GLFW_PRESS)
            animation.keys[key] = GL_TRUE;
        else if (action == GLFW_RELEASE)
            animation.keys[key] = GL_FALSE;
    }
}

void mainLoop() {

}

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);
    GLFWwindow *window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Blizzard", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, keyCallback);
    gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);

    animation.init();

    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        animation.render(window);

        glfwSwapBuffers(window);
        glfwPollEvents();

    }

    glfwTerminate();

    return 0;
}

animation类头文件

#ifndef OPENGL_PRO_ANIMATION_H
#define OPENGL_PRO_ANIMATION_H

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <map>
#include <GLFW/glfw3.h>
#include "resource_manager.h"
#include "sprite_renderer.h"

enum AnimationState {
    BOOT_ON,
    BOOT_OFF
};


class Animation {
public:

    AnimationState state;
    GLuint width, height;
    GLboolean keys[1024];

    Animation(GLuint width, GLuint height);

    ~Animation();

    void init();

    void destory();

    void processInput(float dt);

    void update();

    void displayVideo(GLFWwindow *window);

    void render(GLFWwindow *window);

    const char *defaultVshaderStr =
            "#version 330 core                                  \n"
            "layout (location = 0) in vec4 vertex;              \n"
            "out vec2 TexCoords;                                \n"
            "uniform mat4 model;                                \n"
            "uniform mat4 projection;                           \n"
            "uniform vec4 location;                             \n"
            "void main()                                        \n"
            "{                                                  \n"
            "   TexCoords.x = vertex.z * location.x + location.z;\n"
            "   TexCoords.y = vertex.w * location.y + location.w;\n"
            "   gl_Position = projection * model * vec4(vertex.xy, 0.0f, 1.0f);\n"
            "}                                                  \n";

    const char *defaultFshaderStr =
            "#version 330 core                                  \n"
            "precision mediump float;                           \n"
            "in vec2 TexCoords;                                 \n"
            "out vec4 color;                                    \n"
            "uniform sampler2D image;                           \n"
            "uniform vec3 spriteColor;                          \n"
            "void main()                                        \n"
            "{                                                  \n"
            "   color = vec4(spriteColor, 1.0) * texture(image, TexCoords);\n"
            "}                                                  \n";



private:
};


#endif //OPENGL_PRO_ANIMATION_H

aniamtion类源码

//
// Created by czh on 18-9-10.
//

#include <unistd.h>
#include "animation.h"

SpriteRenderer *spriteRender;

Animation::Animation(GLuint width, GLuint height) : state(BOOT_ON), width(width), height(height) {
}

Animation::~Animation() {

}

void Animation::init() {
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    this->state = BOOT_ON;

    ResourceManager::loadShader("sprite", defaultVshaderStr, defaultFshaderStr);

    glm::mat4 projection = glm::mat4(1.0f);
    projection = glm::ortho(0.0f, static_cast<GLfloat>(this->width), static_cast<GLfloat>(this->height), 0.0f, -1.0f, 1.0f);
    ResourceManager::getShader("sprite").setInteger("image", 0);
    ResourceManager::getShader("sprite").setMatrix4("projection", projection);
    ResourceManager::loadTexture2D("opening1", "../blizzard/res/textures/opening0,1.png");
    ResourceManager::loadTexture2D("opening2", "../blizzard/res/textures/opening1,2.png");
    ResourceManager::getShader("sprite").setVector4f("location", glm::vec4(1.0f, 1.0f, 0.0f, 0.0f));


    spriteRender = new SpriteRenderer(ResourceManager::getShader("sprite"));
}

void Animation::destory() {
    //ResourceManager::clear();
}

void Animation::processInput(float dt) {

}

void Animation::update() {

}

void Animation::displayVideo(GLFWwindow *window){
    int px, py;
    float scaleX, scaleY, moveX, moveY;
    scaleX = 1.0f / 3.0f;
    scaleY = 1.0f / 8.0f;
    static int i = 0;
    for(int i = 0; i < 48; i++){
        px = i % 3;
        py = i / 6;
        moveX = (float)px / 3.0f;
        moveY = (float)py / 8.0f;

        if(i%6 < 3){
            ResourceManager::getShader("sprite").setVector4f("location", glm::vec4(scaleX, scaleY, moveX, moveY));
            spriteRender->drawSprite(ResourceManager::getTexture2D("opening1"), glm::vec2(0.0f, 0.0f), glm::vec2(1280.0f, 480.0f), 0.0f,
                                     glm::vec3(1.0f, 1.0f, 1.0f));
        } else{
            ResourceManager::getShader("sprite").setVector4f("location", glm::vec4(scaleX, scaleY, moveX, moveY));
            spriteRender->drawSprite(ResourceManager::getTexture2D("opening2"), glm::vec2(0.0f, 0.0f), glm::vec2(1280.0f, 480.0f), 0.0f,
                                     glm::vec3(1.0f, 1.0f, 1.0f));
        }
#ifdef  SML
        std::cout << moveX << "," << moveY << std::endl;
#endif
        glfwSwapBuffers(window);
        glfwPollEvents();
        usleep(1000 * 33);
    }
}

void Animation::render(GLFWwindow *window) {
    if (this->state == BOOT_ON) {
        this->displayVideo(window);
    }
}

开机动画一共48张图,由TexturePacker工具打包制作成精灵图集分别存入opening0,1.png、opening1,2.png。通过函数setVector4f可以设置每次绘图的视图大小和位置。

ResourceManager::getShader("sprite").setVector4f("location", glm::vec4(scaleX, scaleY, moveX, moveY));

ResourceManager类

//
// Created by czh on 18-9-10.
//

#ifndef OPENGL_PRO_RESOURCE_MANAGER_H
#define OPENGL_PRO_RESOURCE_MANAGER_H

#include <iostream>
#include <map>
#include <glad/glad.h>
#include <stb_image/stb_image.h>
#include "shader.h"
#include "texture.h"
#include "texture_vision.h"
#include "vision/vision.h"

class ResourceManager {
public:

    static std::map<std::string, Shader> shaders;

    static std::map<std::string, Texture2D> textures;

    static std::map<std::string, cv::Mat> images;

    static Shader loadShader(std::string name, const GLchar *vShader, const GLchar *fShader, const GLchar *gShader = nullptr);

    static Shader getShader(std::string name);

    static cv::Mat readTexture2D(std::string file);

    static int loadTexture2D(std::string name, std::string file, bool save = true);

    static int loadTexture2D(std::string name, cv::Mat image, bool save = true);

    static int writeTexture2D(std::string name, std::string file);

    static Texture2D getTexture2D(std::string name);

    static Texture2D loadTextureVision(std::string name, cv::Mat *img);

    static void clear();

private:
    ResourceManager() {}

};


#endif //OPENGL_PRO_RESOURCE_MANAGER_H
//
// Created by czh on 18-9-10.
//

#include "resource_manager.h"


std::map<std::string, Texture2D>    ResourceManager::textures;
std::map<std::string, Shader>   ResourceManager::shaders;
std::map<std::string, cv::Mat>   ResourceManager::images;

void ResourceManager::clear() {

}

Shader
ResourceManager::loadShader(std::string name, const GLchar *vShader, const GLchar *fShader, const GLchar *gShader) {
    Shader shader;
    shader.compile(vShader, fShader, gShader);
    shaders[name] = shader;
}

Shader ResourceManager::getShader(std::string name) {
    return shaders[name];
}

cv::Mat ResourceManager::readTexture2D(std::string file) {
    cv::Mat image = Vision::read(file, cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
    return image;
}

int ResourceManager::loadTexture2D(std::string name, std::string file, bool save) {
    Texture2D texture2D;
    cv::Mat image = readTexture2D(file);
    if (image.data == nullptr) {
        printf("#loadTexture2D err\n");
        return -1;
    }
    if (image.channels() == 3) {
        texture2D.Image_Format = GL_BGR;
        texture2D.Internal_Format = GL_RGB;
    } else if (image.channels() == 4) {
        texture2D.Image_Format = GL_BGRA;
        texture2D.Internal_Format = GL_RGBA;
    }
    texture2D.update(image.size().width, image.size().height, image.data);
    textures[name] = texture2D;
    if (save) {
        images[name] = image;
    }
    return 0;
}

int ResourceManager::loadTexture2D(std::string name, cv::Mat image, bool save) {
    Texture2D texture2D;
    if (image.data == nullptr) {
        printf("#loadTexture2D err\n");
        return -1;
    }
    if (image.channels() == 3) {
        texture2D.Image_Format = GL_BGR;
        texture2D.Internal_Format = GL_RGB;
    } else if (image.channels() == 4) {
        texture2D.Image_Format = GL_BGRA;
        texture2D.Internal_Format = GL_RGBA;
    }
    texture2D.update(image.size().width, image.size().height, image.data);
    textures[name] = texture2D;
    if (save) {
        images[name] = image;
    }
    return 0;
}

int ResourceManager::writeTexture2D(std::string name, std::string file) {
    Texture2D texture2D;
    cv::Mat image = readTexture2D(file);
    if (images.find(name) == images.end()) {
        printf("#writeTexture2D error, w/o %s\n", name.data());
        return false;
    }
    cv::imwrite(file, images[name]);
    return true;
}

Texture2D ResourceManager::getTexture2D(std::string name) {
    if (images.find(name) == images.end()) {
        printf("#getTexture2D error, w/o %s\n", name.data());
    }
    return textures[name];
}

Texture2D ResourceManager::loadTextureVision(std::string name, cv::Mat *img) {
    //PicData picData = Vision::read(file_path);
    TextureVision textureVision;
    textureVision.update(img);
    textures[name] = textureVision;
}

shader类

//
// Created by czh on 18-9-10.
//

#ifndef OPENGL_PRO_SHADER_H
#define OPENGL_PRO_SHADER_H

#include <iostream>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "dconfig.h"

class Shader {
public:

    Shader() {};

    int ID;

    Shader &use();

    void compile(const GLchar *vShaderSource, const GLchar *fShaderSource, const GLchar *gShaderSource);

    void setInteger(const GLchar *name, GLint value, GLboolean useShader = true);

    void setVector2f(const GLchar *name, const glm::vec2 &value, GLboolean useShader = true);

    void setVector3f(const GLchar *name, const glm::vec3 &value, GLboolean useShader = true);

    void setVector4f(const GLchar *name, const glm::vec4 &value, GLboolean useShader = true);

    void setMatrix4(const GLchar *name, const glm::mat4 &matrix, GLboolean useShader = true);

private:
    void checkCompileErrors(GLuint object, std::string type);
};


#endif //OPENGL_PRO_SHADER_H

//
// Created by czh on 18-9-10.
//

#include "shader.h"

void Shader::compile(const GLchar *vShaderSource, const GLchar *fShaderSource, const GLchar *gShaderSource) {
    GLuint sVertex, sFragment, gShader;

    sVertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(sVertex, 1, &vShaderSource, nullptr);
    glCompileShader(sVertex);
    checkCompileErrors(sVertex, "VERTEX");

    sFragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(sFragment, 1, &fShaderSource, NULL);
    glCompileShader(sFragment);
    checkCompileErrors(sFragment, "FRAGMENT");

    if (gShaderSource != nullptr) {
        gShader = glCreateShader(GL_GEOMETRY_SHADER);
        glShaderSource(gShader, 1, &gShaderSource, NULL);
        glCompileShader(gShader);
        checkCompileErrors(gShader, "GEOMETRY");
    }

    this->ID = glCreateProgram();
#ifdef SML
    std::cout << "#glCreateProgram ID:" << this->ID;
    if (gShaderSource == nullptr) {
        std::cout << " w/o_gShader" << std::endl;
    } else {
        std::cout << " w/_gShader" << std::endl;
    }
#endif
    glAttachShader(this->ID, sVertex);
    glAttachShader(this->ID, sFragment);
    if (gShaderSource != nullptr)
        glAttachShader(this->ID, gShader);
    glLinkProgram(this->ID);
    checkCompileErrors(this->ID, "PROGRAM");

    glDeleteShader(sVertex);
    glDeleteShader(sFragment);
    if (gShaderSource != nullptr)
        glDeleteShader(gShader);

}

Shader &Shader::use() {
    glUseProgram(this->ID);
    //std::cout << "#Use glUseProgram: " << this->ID << std::endl;
    return *this;
}

void Shader::setInteger(const GLchar *name, GLint value, GLboolean useShader) {
    if (useShader)
        this->use();
    glUniform1i(glGetUniformLocation(this->ID, name), value);
}

void Shader::setVector2f(const GLchar *name, const glm::vec2 &value, GLboolean useShader) {
    if (useShader)
        this->use();
    glUniform2f(glGetUniformLocation(this->ID, name), value.x, value.y);
}

void Shader::setVector3f(const GLchar *name, const glm::vec3 &value, GLboolean useShader) {
    if (useShader)
        this->use();
    glUniform3f(glGetUniformLocation(this->ID, name), value.x, value.y, value.z);
}

void Shader::setVector4f(const GLchar *name, const glm::vec4 &value, GLboolean useShader) {
    if (useShader)
        this->use();
    glUniform4f(glGetUniformLocation(this->ID, name), value.x, value.y, value.z, value.w);
}

void Shader::setMatrix4(const GLchar *name, const glm::mat4 &matrix, GLboolean useShader) {
    if (useShader)
        this->use();
    glUniformMatrix4fv(glGetUniformLocation(this->ID, name), 1, GL_FALSE, glm::value_ptr(matrix));
}

void Shader::checkCompileErrors(GLuint object, std::string type) {
    GLint success;
    GLchar infoLog[1024];
    if (type != "PROGRAM") {
        glGetShaderiv(object, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(object, 1024, NULL, infoLog);
            std::cout << "| ERROR::SHADER: Compile-time error: Type: " << type << "\n"
                      << infoLog << "\n -- ----------------------------------------------------- "
                      << std::endl;
        }
    } else {
        glGetProgramiv(object, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(object, 1024, NULL, infoLog);
            std::cout << "| ERROR::Shader: Link-time error: Type: " << type << "\n"
                      << infoLog << "\n -- ----------------------------------------------------- "
                      << std::endl;
        }
    }
}

开机动画效果图就不放了,会被炒鱿鱼

猜你喜欢

转载自blog.csdn.net/czhzasui/article/details/83545269