ImGui添加背景图片的两种方式

给ImGui添加背景图片的两种方式

最近在使用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);

这样就可以添加背景到窗口中了

第二种 使用openGL纹理映射方式

第二种方式的话前提你的imgui是基于openGL的。这种方式就要稍微复杂一些了,如果没有openGL基础的话可能会觉得有点难。博主也是初学openGL,刚学完纹理那一节,所以就研究出了这个方法。关于openGL怎么映射纹理这里有更详细的教程,LearnOpenGL,我就不介绍了。基于着色类修改封装成了一个类,这样方便使用一些。

#include <GL/gl3w.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

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());//在这句代码以前加入

看一看效果:
这里写图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值