给ImGui添加背景图片的两种方式
最近在使用ImGui做客户端程序,想给窗口添加背景图片,但是作者的文档里面好像并没有讲如何添加背景图片,研究了下找到了两种方式。
这应该也是最简单的一种ImGui添加背景的方式了。
ImGuiIO& io = ImGui::GetIO();
//设置窗口位置
ImGui::SetNextWindowPos(ImVec2(0,0), 0, ImVec2(0, 0));
//设置窗口的大小
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y));
//设置窗口为透明
ImGui::SetNextWindowBgAlpha(0);
//纹理ID
static ImTextureID bg_tex_id = 0;
if (!bg_tex_id)
{
//这里使用opencv加载图片当然你也可以使用其他方式加载图片
//loadTexture是一个自定义的函数用于图片字符加载为纹理,不知道怎么加载纹理的可以自行百度
bg_tex_id = (GLuint *)loadTexture(cvLoadImage("Template/bg2.jpg"));
}
//设置窗口的padding为0是图片控件充满窗口
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
//设置窗口为无边框
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
//创建窗口使其固定在一个位置
ImGui::Begin("背景", NULL, ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoInputs |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoScrollbar);
ImGui::Image(bg_tex_id, ImGui::GetContentRegionAvail());
ImGui::End();
ImGui::PopStyleVar(2);
这样就可以添加背景到窗口中了
第二种方式的话前提你的imgui是基于openGL的。这种方式就要稍微复杂一些了,如果没有openGL基础的话可能会觉得有点难。博主也是初学openGL,刚学完纹理那一节,所以就研究出了这个方法。关于openGL怎么映射纹理这里有更详细的教程,LearnOpenGL,我就不介绍了。基于着色类修改封装成了一个类,这样方便使用一些。
#include
#include
#include
#include
#include
class Shader {
public:
unsigned int ID;//着色器程序ID
unsigned int VAO, VBO, EBO;
unsigned int texture;
Shader(const char* vertexPath, const char* fragmentPath);
void use();
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void initArgument(const char *imagePath);
void loadTexture(unsigned char *data, int width, int height);
~Shader();
};
类实现:
//
// Created by root on 18-9-6.
//
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "Shader.h"
//从文件中读取顶点着色器程序和片段着色器程序
Shader::Shader(const char *vertexPath, const char *fragmentPath) {
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure failure){
std::cout<<"ERROR:SHADER::FILE_NOT_SUCESSFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vShaderCode, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
ID = glCreateProgram();
glAttachShader(ID, vertexShader);
glAttachShader(ID, fragmentShader);
glLinkProgram(ID);
// check for linking errors
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
//使用着色器并绘制图形
void Shader::use()
{
//使用着色器程序画出矩形
glUseProgram(ID);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
void Shader::setBool(const std::string &name, bool value) const {
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::setInt(const std::string &name, int value) const {
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setFloat(const std::string &name, float value) const {
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
//初始化渲染参数
void Shader::initArgument(const char *imagePath) {
float vertices[] = {
// ---- 位置 ---- ----纹理坐标----
//使矩形的面积占满窗口显示面积
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 右上
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // 右下
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // 左下
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
};
//绘制两个三角形组成矩形
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(sizeof(float) * 3));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);//上下颠倒
unsigned char *data = stbi_load(imagePath, &width, &height, &nrChannels, 0);
loadTexture(data, width, height);
stbi_image_free(data);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//创建纹理
void Shader::loadTexture(unsigned char *data, int width, int height)
{
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
printf("Failed to load texture");
}
}
Shader::~Shader() {
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
vShaderSource.vs:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 2) in vec2 aTexPos;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
TexCoord = aTexPos;
}
fShaderSource.fs:
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
那么这样使用就非常方便了
创建对象初始化参数
Shader shader("../src/vShaderSource.vs", "../src/fShaderSource.fs");
shader.initArgument("bg6.jpg");
在ImGui主循环里面使用着色器进行渲染
shader.use();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());//在这句代码以前加入