使用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;
}
}
}
开机动画效果图就不放了,会被炒鱿鱼