OpenGl实战笔记(2)基于qt5.15.2+mingw64+opengl实现纹理贴图

一、作用原理

1、作用:将一张图片(纹理)映射到几何体表面,提升视觉真实感,不增加几何复杂度。

2、原理:加载图片为纹理 → 上传到 GPU;为顶点设置纹理坐标(如 0~1 范围);GPU 在渲染时 插值纹理坐标;片元着色器中采样纹理颜色 → 显示图案。简单说,就是"把图贴上去"。

二、实现效果

三、参考代码

读取本地的png图片贴到四边形几何体表面

cpp 复制代码
//TextureRenderer 类
#pragma once
#include "RenderModuleInterface.h"
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QImage>
#include <QMatrix4x4>

// 简单纹理渲染器:负责初始化 OpenGL 资源、加载纹理并进行屏幕渲染
class TextureRenderer : public RenderModuleInterface, protected QOpenGLFunctions
{
public:
    TextureRenderer();
    ~TextureRenderer();

    // 初始化 OpenGL 状态与资源,只执行一次
    void initialize() override;

    // 设置视口大小(通常来自窗口resize事件)
    void resize(int w, int h) override;

    // 执行渲染流程(清屏、绑定shader和纹理、绘制)
    void render() override;

    // 设置外部纹理图像(功能扩展)
    void setTextureImage(const QImage& image);

    // 设置 MVP(模型视图投影)矩阵,可用于变换控制
    void setModelMatrix(const QMatrix4x4& model);

private:
    QOpenGLShaderProgram shader;      // 着色器程序
    QOpenGLTexture* texture = nullptr;// 纹理对象
    QOpenGLBuffer vbo;                // 顶点缓冲对象
    QOpenGLVertexArrayObject vao;     // 顶点数组对象

    QMatrix4x4 mvpMatrix;             // 模型视图投影矩阵
    int viewportWidth = 0;            // 视口宽度
    int viewportHeight = 0;           // 视口高度
    bool isInitialized = false;       // 初始化标志
};
#include "TextureRenderer.h"
#include <QDebug>

// 顶点着色器源码:传递位置与纹理坐标,并应用 MVP 变换
static const char* vertexShaderSrc = R"(
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texCoord;
out vec2 TexCoord;
uniform mat4 u_mvp;
void main()
{
    TexCoord = texCoord;
    gl_Position = u_mvp * vec4(position, 0.0, 1.0);
})";
// 片段着色器源码:根据纹理坐标采样颜色输出
static const char* fragmentShaderSrc = R"(
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D u_texture;
void main()
{
    FragColor = texture(u_texture, TexCoord);
})";
TextureRenderer::TextureRenderer() {}
TextureRenderer::~TextureRenderer()
{
    if (texture) {
        delete texture;
        texture = nullptr;
    }
    vao.destroy();
    vbo.destroy();
}
void TextureRenderer::initialize()
{
    if (isInitialized) return;
    initializeOpenGLFunctions();

    if (shader.isLinked()) return;

    // 设置清除背景色
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

    // 默认创建蓝色纹理(128x128)
    QImage img(128, 128, QImage::Format_RGBA8888);
    img.fill(QColor(0, 0, 255, 255));
    texture = new QOpenGLTexture(img.mirrored());

    // 编译并链接着色器
    bool vs = shader.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSrc);
    bool fs = shader.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSrc);
    if (!vs || !fs || !shader.link()) {
        qDebug() << "Shader Compile Error:" << shader.log();
        return;
    }

    // 顶点数据(位置 + 纹理坐标)
    GLfloat vertices[] = {
        -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.0f, 0.0f
    };

    shader.bind();
    vao.create();
    vao.bind();

    vbo.create();
    vbo.bind();
    vbo.allocate(vertices, sizeof(vertices));

    // 配置顶点属性指针
    shader.enableAttributeArray(0); // position
    shader.setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(float));
    shader.enableAttributeArray(1); // texCoord
    shader.setAttributeBuffer(1, GL_FLOAT, 2 * sizeof(float), 2, 4 * sizeof(float));

    vao.release();
    vbo.release();
    shader.release();

    // 设置默认正交投影矩阵
    mvpMatrix.ortho(-1, 1, -1, 1, -1, 1);

    isInitialized = true;
}
void TextureRenderer::resize(int w, int h)
{
    glViewport(0, 0, w, h);
    viewportWidth = w;
    viewportHeight = h;
}
void TextureRenderer::render()
{
    if (!isInitialized) return;

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    shader.bind();
    vao.bind();

    // 设置变换矩阵
    shader.setUniformValue("u_mvp", mvpMatrix);

    // 绑定纹理并设置纹理单元
    glActiveTexture(GL_TEXTURE0);
    texture->bind();
    shader.setUniformValue("u_texture", 0);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    texture->release();
    vao.release();
    shader.release();
}
void TextureRenderer::setTextureImage(const QImage& image)
{
    if (!image.isNull()) {
        if (texture) {
            delete texture;
            texture = nullptr;
        }
        texture = new QOpenGLTexture(image.mirrored());
    }
}
void TextureRenderer::setModelMatrix(const QMatrix4x4& model)
{
    mvpMatrix = model;
}

//使用,这里默认创建的是蓝色纹理,设置图片后将其覆盖了
modules["纹理贴图"] = new TextureRenderer();
// 加载砖墙纹理图片
QImage image(":/images/wall.png");
modules["纹理贴图"]->initialize();
if (!image.isNull()) {
     dynamic_cast<TextureRenderer*>(modules["纹理贴图"])->setTextureImage(image);
}

欢迎关注我,一起交流!

相关推荐
xixixiLucky11 分钟前
Selenium Web自动化测试学习笔记(一)
笔记·学习·selenium
HHONGQI1231 小时前
ESP32- 开发笔记- 软件开发 6 蓝牙协议栈 1
笔记
TJ-周月年1 小时前
2025FIC初赛(手机)
笔记·网络安全
yxc_inspire1 小时前
基于Qt的app开发第六天
开发语言·c++·qt
一点.点2 小时前
李沐动手深度学习(pycharm中运行笔记)——09.softmax回归+图像分类数据集+从零实现+简洁实现
pytorch·笔记·python·深度学习·动手深度学习·softmax回归
江安的猪猪3 小时前
大连理工大学选修课——机器学习笔记(4):NBM的原理及应用
笔记·机器学习·概率论
胡楚昊3 小时前
B站pwn教程笔记-7
笔记
Generalzy3 小时前
Model Context Protocol (MCP)笔记
笔记·ai·mcp
懒惰的bit4 小时前
QT人工智能篇-opencv
人工智能·qt·opencv