OpenGL繪制文本

一:QPainter繪制

在 OpenGL 渲染的窗口中(如?QOpenGLWidget),通過?QPainter?直接繪制文本。Qt 會自動將 2D 內容(文本、圖形)與 OpenGL 內容合成。在paintGL()里面繪制,如果有其他紋理,在繪制紋理后解綁資源,再繪制文本。

    m_program.bind();// 綁定紋理m_texture->bind(0);m_program.setUniformValue("texture1", 0);// 繪制矩形glBindVertexArray(VAO[0]);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);// 解綁VAOglBindVertexArray(0);m_program.release();// ----------------- 繪制文字 -----------------QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(Qt::yellow);painter.setFont(QFont("Arial", 16, QFont::Bold));// 帶背景的文字QString text =  QString("%1:%2x%3").arg("寬高").arg(width()).arg(height());QRect textRect = painter.fontMetrics().boundingRect(text);textRect.moveTo(5, 5);painter.fillRect(textRect.adjusted(-1, -1, 1, 1), QColor(0, 0, 0, 128));painter.drawText(textRect, Qt::AlignLeft, text);painter.end();

二:生成文本紋理并渲染四邊形(高性能,適合動態文本)

將文本預渲染為紋理,通過 OpenGL 四邊形顯示,適合高頻更新或大量文本。

步驟 1:創建文本紋理
QImage MyGLWidget::createTextTexture(const QString& text, int width, int height) {QImage image(width, height, QImage::Format_ARGB32);image.fill(Qt::transparent);QPainter painter(&image);painter.setPen(Qt::white);painter.setFont(QFont("Arial", 24));painter.drawText(image.rect(), Qt::AlignCenter, text);painter.end();// OpenGL 紋理坐標系原點在左下角,需垂直翻轉圖像return image.mirrored(false, true);
}
步驟 2:綁定紋理并渲染四邊形
QImage MyGLWidget::createTextTexture(const QString& text, int width, int height) {QImage image(width, height, QImage::Format_ARGB32);image.fill(Qt::transparent);QPainter painter(&image);painter.setPen(Qt::white);painter.setFont(QFont("Arial", 24));painter.drawText(image.rect(), Qt::AlignCenter, text);painter.end();// OpenGL 紋理坐標系原點在左下角,需垂直翻轉圖像return image.mirrored(false, true);
}

?優化技巧?:

  • 使用 ?紋理緩存? 存儲常用文本,避免重復生成。
  • 動態更新紋理時,使用?glTexSubImage2D?局部更新數據。

三、使用 FreeType 庫 + OpenGL(靈活但復雜)?

通過 FreeType 加載字體文件生成字形紋理圖集,實現高度定制的文本渲染(如游戲引擎風格)。

步驟 1:集成 FreeType 庫

在?.pro?文件中添加依賴:

LIBS += -lfreetype

步驟 2:加載字體并生成字形?
#include <ft2build.h>
#include FT_FREETYPE_Hstruct Character {GLuint textureID;glm::ivec2 size;glm::ivec2 bearing;GLuint advance;
};std::map<GLchar, Character> characters;void loadFont(const char* fontPath) {FT_Library ft;FT_Init_FreeType(&ft);FT_Face face;FT_New_Face(ft, fontPath, 0, &face);FT_Set_Pixel_Sizes(face, 0, 48);glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 禁用字節對齊限制for (GLubyte c = 0; c < 128; c++) {FT_Load_Char(face, c, FT_LOAD_RENDER);GLuint texture;glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,face->glyph->bitmap.width,face->glyph->bitmap.rows,0, GL_RED, GL_UNSIGNED_BYTE,face->glyph->bitmap.buffer);// 設置紋理參數glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);Character character = {texture,glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),static_cast<GLuint>(face->glyph->advance.x)};characters.insert(std::make_pair(c, character));}FT_Done_Face(face);FT_Done_FreeType(ft);
}
步驟 3:渲染文本?
void renderText(QOpenGLShaderProgram& program, const std::string& text, GLfloat x, GLfloat y, GLfloat scale) {program.bind();glActiveTexture(GL_TEXTURE0);for (auto c = text.begin(); c != text.end(); c++) {Character ch = characters[*c];GLfloat xpos = x + ch.bearing.x * scale;GLfloat ypos = y - (ch.size.y - ch.bearing.y) * scale;GLfloat w = ch.size.x * scale;GLfloat h = ch.size.y * scale;// 更新 VBO 數據(需預先創建)GLfloat vertices = {{xpos, ypos + h, 0.0, 0.0},{xpos, ypos, 0.0, 1.0},{xpos + w, ypos, 1.0, 1.0},{xpos, ypos + h, 0.0, 0.0},{xpos + w, ypos, 1.0, 1.0},{xpos + w, ypos + h, 1.0, 0.0}};glBindTexture(GL_TEXTURE_2D, ch.textureID);glBindBuffer(GL_ARRAY_BUFFER, m_vbo);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);glDrawArrays(GL_TRIANGLES, 0, 6);x += (ch.advance >> 6) * scale; // 單位轉換為像素}program.release();
}
關鍵問題解決
  1. ?文本模糊?:

    • 確保紋理過濾設置為?GL_LINEAR
    • 使用高分辨率字體或 MSDF(多通道有符號距離場)技術。
  2. ?中文支持?:

    • FreeType 方法需加載中文字體(如?.ttf),并遍歷 Unicode 字符集。
  3. ?性能優化?:

    • 批處理文本繪制調用,減少狀態切換。
    • 使用實例化渲染(Instancing)處理大量相同字體的文本。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75689.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75689.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從零構建大語言模型全棧開發指南:第二部分:模型架構設計與實現-2.1.3前饋網絡(FFN)與激活函數(GELU)優化

?? 點擊關注不迷路 ?? 點擊關注不迷路 ?? 點擊關注不迷路 文章大綱 2.1.3 前饋網絡(FFN)與激活函數(GELU)優化1. 前饋網絡(FFN)的架構設計與數學原理1.1 FFN在Transformer中的核心作用2. GELU激活函數的數學特性與優化2.1 GELU的數學形式與近似計算3. 逐行代碼實現…

React 中的錯誤邊界(Error Boundaries),如何使用它們捕獲組件錯誤

大白話React 中的錯誤邊界&#xff08;Error Boundaries&#xff09;&#xff0c;如何使用它們捕獲組件錯誤 在 React 里&#xff0c;錯誤邊界就像是一個“小衛士”&#xff0c;專門負責在組件出現錯誤時挺身而出&#xff0c;避免整個應用因為一個小錯誤就崩潰掉。接下來我會詳…

數據庫DBA認證,選哪個認證合適?

從 Oracle、MySQL 到 云數據庫&#xff0c;結合市場認可度、考試難度及職業回報&#xff0c;為你精選高性價比認證。 一、企業級數據庫認證&#xff08;傳統場景&#xff09; 1. Oracle認證 認證等級考試代碼核心內容費用適合人群OCA1Z0-082SQL基礎、數據庫安裝與配置$245零基…

力扣刷題-熱題100題-第24題(c++、python)

234. 回文鏈表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/palindrome-linked-list/description/?envTypestudy-plan-v2&envIdtop-100-liked 常規法 數組是連續的存儲空間&#xff0c;可以根據索引到達任意位置&#xff0c;鏈表只能一個個的順…

調用通義千問實現語音合成并將合成的音頻通過揚聲器播放

1. 作者介紹 郭建東&#xff0c;男&#xff0c;西安工程大學電子信息學院&#xff0c;2024級研究生 研究方向&#xff1a;機器視覺與人工智能 電子郵件&#xff1a;1229963266qq.com 高金年&#xff0c;男&#xff0c;西安工程大學電子信息學院&#xff0c;2024級研究生&…

Ubuntu軟件包離線下載安裝

1、下載軟件包tcpd&#xff0c;并在/var/cache/apt/archives目錄中查看。 rooteducoder:~# apt-get install -d tcpd Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed:tcpd …

您的數據是如何出現在暗網上的?

暗網是互聯網上的一個隱秘角落&#xff0c;人們可以在那里保持匿名。暗網經常與深網混淆&#xff0c;但它們并不完全相同。 深網是指網絡上所有未被搜索引擎索引的內容。這包括電子郵件帳戶、私人數據庫和付費服務等。這并不違法&#xff0c;只是無法通過簡單的 Google 搜索找…

原型模式及其應用

引言 原型模式&#xff08;Prototype Pattern&#xff09;是一種創建型設計模式&#xff0c;它允許通過復制現有對象來創建新對象&#xff0c;而無需通過構造函數來創建。這種模式通過克隆現有對象來創建新對象&#xff0c;從而避免了復雜的初始化過程。本文將探討原型模式的好…

thinkphp漏洞再現

Thinkphp5x遠程命令執行及getshell 1、開環境 2、使用工具攻擊 開啟工具 輸入地址&#xff0c;點擊漏洞檢測 存在漏洞之后&#xff0c;選擇漏洞&#xff0c;執行命令 3、也可以執行遠程命令 執行命令 ?sindex/think\app/invokefunction&functioncall_user_func_array&…

Day16 -實例:Web利用郵箱被動繞過CDN拿真實ip

本想測試一下全局ping&#xff0c;剛好注冊的時候收到了郵件&#xff0c;剛好去做一下復現。 原理&#xff1a;主動讓對方站點給我們發郵件&#xff08;注冊、修改密碼、訂閱推送等&#xff09;我們查看郵件原文&#xff0c;原文里存在真實的郵件站點ip 特點&#xff1a;郵件…

vue3 數據監聽(watch、watchEffect)

1、watch 1.1基本使用 作用&#xff1a;數據監聽 語法&#xff1a; watch(監聽的數據, (改變后的數據, 改變前的數據) > { console.log(newVal, oldVal); }) 注意點&#xff1a;watch寫法上支持一個或者多個監聽源&#xff0c;這些監聽源必須只能是getter/effect函數…

網盤解析工具更新,解決了一些bug

解析工具v1.2.1版本更新&#xff0c;本次是小版本更新&#xff0c;修復了一些bug。 之前小伙伴反應的網盤進入文件后不能返回上一級&#xff0c;現在這個bug修復了&#xff0c;已經可以點擊了。 點擊資源后會回到資源那一級目錄&#xff0c;操作上是方便了不少。 增加了檢查自…

推薦1款簡潔、小巧的實用收音機軟件,支持手機和電腦

聊一聊 沒想到現在還有人喜歡聽廣播。 我一直以為聽廣播必須要用那種小廣播機才可以。 原來手機或電腦上也是可以的。 今天給大家分享一款可以在電腦和手機上聽廣播的軟件。 軟件介紹 龍卷風收音機 電臺廣播收音機分電腦和手機兩個版本。 電腦端無需安裝&#xff0c;下載…

六十天前端強化訓練之第三十一天之Webpack 基礎配置 大師級講解(接下來幾天給大家講講工具鏈與工程化)

歡迎來到編程星辰海的博客講解 看完可以給一個免費的三連嗎&#xff0c;謝謝大佬&#xff01; 目錄 一、Webpack 核心概念解析 二、實戰&#xff1a;多資源打包配置&#xff08;含完整代碼&#xff09; 三、配置深度解析&#xff08;重點部分說明&#xff09; 四、效果演示…

機器學習——Bagging、隨機森林

相比于Boosting的集成學習框架&#xff0c;Bagging(Bootstrap Sampling&#xff0c;自助聚集法&#xff0c;又稱為自助采樣)作為一種自助聚集且并行化的集成學習方法&#xff0c;其通過組合多個基學習器的預測結果來提高模型的穩定性和泛化能力。其中隨機森林是Bagging學習框架…

【藍橋杯】每日練習 Day13

前言 今天做了不少題&#xff0c;但是感覺都太水了&#xff0c;深思熟慮之下主播決定拿出兩道相對不那么水的題來說一下&#xff08;其實還是很水&#xff09;。 兩道問題&#xff0c;一道是日期問題&#xff08;模擬&#xff09;&#xff0c;一道是區間合并問題。 日期差值 …

HTML輸出流

HTML 輸出流 JavaScript 中**「直接寫入 HTML 輸出流」**的核心是通過 document.write() 方法向瀏覽器渲染過程中的數據流動態插入內容。以下是詳細解釋&#xff1a; 一、HTML 輸出流的概念 1. 動態渲染過程 HTML 文檔的加載是自上而下逐行解析的。當瀏覽器遇到 <script&…

理解文字識別:一文讀懂OCR商業化產品的算法邏輯

文字識別是一項“歷久彌新”的技術。早在上世紀初&#xff0c;工程師們就開始嘗試使用當時有限的硬件設備掃描并識別微縮膠片、紙張上的字符。隨著時代和技術的發展&#xff0c;人們在日常生活中使用的電子設備不斷更新換代&#xff0c;文字識別的需求成為一項必備的技術基礎&a…

開源模型應用落地-語音轉文本-whisper模型-AIGC應用探索(五)

一、前言 在上一節中&#xff0c;學習了如何使用vLLM來部署Whisper-large-v3-turbo模型。不過&#xff0c;在實際使用時&#xff0c;模型一次只能處理30秒的音頻。今天&#xff0c;將結合實際業務&#xff0c;介紹如何處理一段完整的音頻&#xff0c;并生成相應的字幕文件。 相…

“十五五”時期航空彈藥發展環境分析

1&#xff0e;“十五五”時期航空彈藥發展環境分析 &#xff08;標題&#xff1a;小二號宋體居中&#xff09; 一、建言背景介紹 &#xff08;一級標題&#xff1a;黑體三號&#xff0c;首行空兩格&#xff09; 航空彈藥作為現代戰爭的核心裝備&#xff0c;其發展水平直接關乎…