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

C++/QT环境下图像在窗口下等比例渲染绘制

本文中通过QT获取到opengl上下文环境,通过opengl3.0API将图像等比例渲染到QOpenGLWidget组件上面,相比cpu,渲染能力更强。
有以下四步骤。opengl基本知识点可参照之前文章OPENGL初学习

  1. 定义opengl渲染表面属性
  2. 通过initializeGL接口初始化opengl上下文环境,然后加载并链接着色器程序,创建顶点以及纹理,
  3. 通过paintGL接口完成单帧渲染
  4. 通过``接口实现窗口缩放逻辑,这一步比较简单,只需要接口内调用glViewport(0, 0, w, h);即可

下面展开步骤讲解

定义opengl渲染表面属性

通过QSurfaceFormat 的设置,QSurfaceFormat 用于定义 OpenGL 渲染表面的属性,例如缓冲区大小、颜色深度、双缓冲、OpenGL 版本等。
这些属性必须在 OpenGL 上下文创建之前设置,因为它们是创建 OpenGL 上下文的基础。
如果尝试在 initializeGL() 中设置 QSurfaceFormat,OpenGL 上下文已经创建,此时修改格式是无效的。

  1. OpenGL 版本兼容性:
    确保硬件和驱动程序支持指定的 OpenGL 版本(如 3.3)。
    如果不支持,OpenGL 上下文将无法创建。
  2. 缓冲区大小:
    深度缓冲区和模板缓冲区的大小应根据应用程序的需求设置。
    24 位深度缓冲区和 8 位模板缓冲区是常见的配置。
  3. 核心模式:
    核心模式仅支持现代 OpenGL 功能,确保代码不使用已弃用的功能(如固定功能管线)。
  4. 默认格式:
    通过 QSurfaceFormat::setDefaultFormat(format) 设置默认格式后,所有后续创建的 OpenGL 表面都会使用此格式。
  QSurfaceFormat format;
  format.setDepthBufferSize(24);
  format.setStencilBufferSize(8);
  format.setVersion(3, 3);
  format.setProfile(QSurfaceFormat::CoreProfile);
  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
  QSurfaceFormat::setDefaultFormat(format);

initializeGL

这一步中要对顶点信息、纹理以及着色器程序进行初始化
顶点信息用于映射顶点以及纹理坐标,以此实现将图像等比例显示在窗口中心,顶点着色器程序将顶点位置转换为齐次坐标,并将将顶点颜色和纹理坐标传递给片段着色器;片段着色器程序使用纹理坐标从纹理中采样颜色赋值给 FragColor进行渲染

顶点

  1. 创建顶点数据,4*8,每一行数据分别代表右上 右下 左下 左上顶点。每行数据有8个元素,前三个数据是顶点坐标,由于是二维图像,因此z是0,;中间三个是颜色数据,最后两个是纹理坐标。

    GLfloat vertices_tmp[] = {
      2.0f,  2.0f,  0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
      1.0f,  // 右上
      2.0f,  -2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
      0.0f,  // 右下
      -2.0f, -2.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
      0.0f,  // 左下
      -2.0f, 2.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
      1.0f  // 左上
    };
    memcpy(vertices, vertices_tmp, sizeof(vertices));  
    
  2. 纹理坐标映射:映射逻辑是保持纹理坐标不变,将图像等比例四个点在宽度与高度方向计算图像缩放比,然后将缩放值填充到vertices对应位置,即是将图像渲染到窗口等比例显示的区域

    void GLShowPicWidget::generate_vertex(int img_w, int img_h) {
      float w_delta_ratio1 = 1;
      float h_delta_ratio1 = 1;
    
      if (img_w != -1 && img_h != -1) {
        float w_ratio = (float)img_w / width();
        float h_ratio = (float)img_h / height();
        float ratio = std::max(w_ratio, h_ratio);
    
        _img_label_fix_width = img_w / ratio;
        _img_label_fix_height = img_h / ratio;
    
        w_delta_ratio1 = (float)_img_label_fix_width / width();
        h_delta_ratio1 = (float)_img_label_fix_height / height();
    	  } else {
    	    _img_label_fix_width = width();
    	    _img_label_fix_height = height();
    	  }
    	  _img_lx = (width() - _img_label_fix_width) / 2;
    	  _img_ly = (height() - _img_label_fix_height) / 2;
    	
    	  vertices[0] = w_delta_ratio1;
    	  vertices[1] = h_delta_ratio1;
    	  vertices[8] = w_delta_ratio1;
    	  vertices[9] = 

http://www.kler.cn/a/509351.html

相关文章:

  • 第8篇:从入门到精通:掌握Python异常处理
  • YoloV10改进策略:Neck层改进|EFC,北理提出的适用小目标的特征融合模块|即插即用
  • php-2025面试题准备
  • Android 12.0 息屏休眠后立即启动屏保功能实现
  • Golang学习笔记_26——通道
  • Golang结合MySQL和DuckDB提高查询性能
  • OpenEuler学习笔记(一):常见命令
  • UDP 单播、多播、广播:原理、实践
  • 【C++笔记】红黑树封装map和set深度剖析
  • 高性能、并发安全的 Go 嵌入式缓存库 如何使用?
  • 浅谈云计算22 | Kubernetes容器编排引擎
  • ASP.NET Core全球化与本地化:打造多语言应用
  • vulnhub靶场【jangow】靶机,考察反弹shell的流量及端口的选择
  • Transformer之Encoder
  • 如何在openEuler中编译安装Apache HTTP Server并设置服务管理(含Systemd和Init脚本)
  • 【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现
  • linux下springboot项目nohup日志或tomcat日志切割处理方案
  • Redis集群部署详解:主从复制、Sentinel哨兵模式与Cluster集群的工作原理与配置
  • leetcode707-设计链表
  • 电脑风扇声音大怎么办? 原因及解决方法
  • github 端口22 超时问题解决
  • AWS物联网连接的数据记录器在冰川环境中的性能比较:Campbell CR1000X与ESP32开源
  • 【react】使用antd Table渲染数据遇到的报错问题
  • 用Cursor生成一个企业官网前端页面(生成腾讯、阿里官网静态页面)
  • redis安装教程(windows)
  • 从零到一:Spring Boot 与 RocketMQ 的完美集成指南