当前位置: 首页 > news >正文

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

一、作用原理

1、作用:将一张图片(纹理)映射到几何体表面,提升视觉真实感,不增加几何复杂度。
2、原理:加载图片为纹理 → 上传到 GPU;为顶点设置纹理坐标(如 0~1 范围);GPU 在渲染时 插值纹理坐标;片元着色器中采样纹理颜色 → 显示图案。简单说,就是“把图贴上去”。

二、实现效果
在这里插入图片描述
三、参考代码

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

//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); // positionshader.setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(float));shader.enableAttributeArray(1); // texCoordshader.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);
}

欢迎关注我,一起交流!

相关文章:

  • 【C++核心技术深度解析:从继承多态到STL容器 】
  • Nacos源码—4.Nacos集群高可用分析四
  • Python爬虫+代理IP+Header伪装:高效采集亚马逊数据
  • 【AI知识库云研发部署】RAGFlow + DeepSeek
  • python打卡day17
  • 解决android studio 中gradle 出现task list not built
  • 使用Unsloth微调DeepSeek-R1蒸馏模型:低显存高效训练实践
  • 效率提升利器:解锁图片处理新姿势
  • x-cmd install | Tuistash - Logstash 实时监控,告别图形界面,高效便捷!
  • 餐饮部绩效考核管理制度与综合评估方法
  • STL之stackqueue
  • Linux主机时间设置操作指南及时间异常影响
  • 开个帖子记录一下自己学spring源码的过程
  • LLM评估指标:WSC和WebNLG 是什么
  • mysql协议详解
  • Waymo公司正在加快其位于亚利桑那州新工厂的无人驾驶出租车(robotaxi)生产进度
  • 使用 AddressSanitizer 检测堆越界错误
  • 小刚说C语言刷题—1044 -找出最经济型的包装箱型号
  • 资产管理系统选型避坑:2025年核心技术趋势洞察
  • 凌晨三点的数据库崩溃现场
  • 新消费观察| 零售品牌 “走出去” ,如何开辟“新蓝海”?
  • 三大交易所多举措支持科创债再扩容,约160亿证券公司科创债有望近期落地
  • 【社论】跑赢12级狂风,敦煌做对了什么
  • 世界羽联主席巴达玛:中国组织赛事的能力无与伦比
  • 五一假期,新任杭州市委书记刘非到嘉兴南湖瞻仰红船
  • 深入景区、文化街区及消费一线,多地省委书记调研文旅市场