我沒有選擇使用除opengl方法以外(即glxxx()方法())。我只需要使用gl方法繪製文本。閱讀紅皮書後,我明白,只有通過glBitmap()方法纔有可能。如果這是唯一可行的方法,那麼任何人都可以幫助我獲得所有字符的像素數組信息。是否有其他方式來繪製文字?如何僅使用OpenGL方法繪製文本?
回答
純OpenGL繪圖文字不是straigth-使用紋理
一些很好的起點可能是GLFont,OpenGL Font Survey和NeHe Tutorial for Bitmap Fonts (Windows)。
請注意,位圖不是在字體調查中提到的在OpenGL中實現文本的唯一方法。
我認爲在OpenGL中繪製文本的最佳解決方案是紋理字體,我與他們合作了很長時間。他們靈活,快速和漂亮的外觀(有一些例外)。我使用特殊程序將字體文件(例如.ttf)轉換爲紋理,保存爲一些內部「字體」格式的文件(我已經開發了基於http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System的格式和程序,儘管我的版本與原始支持相差甚遠Unicode等)。啓動主應用程序時,字體將從此「內部」格式加載。查看上面的鏈接瞭解更多信息。
使用這種方法,主應用程序不使用任何特殊的庫,如FreeType,這對我也是不可取的。正在使用標準的OpenGL函數繪製文本。
如果我可以添加一些東西給這個alrea DY很好的答案,要注意任何字體渲染系統的optmization,因爲它可能非常有限的HW資源,如移動設備影響您的發動機的性能。 – 2012-01-13 09:48:34
使用glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString)
。
例如:星球大戰SCROLLER。
#include <windows.h>
#include <string.h>
#include <GL\glut.h>
#include <iostream.h>
#include <fstream.h>
GLfloat UpwardsScrollVelocity = -10.0;
float view=20.0;
char quote[6][80];
int numberOfQuotes=0,i;
//*********************************************
//* glutIdleFunc(timeTick); *
//*********************************************
void timeTick(void)
{
if (UpwardsScrollVelocity< -600)
view-=0.000011;
if(view < 0) {view=20; UpwardsScrollVelocity = -10.0;}
// exit(0);
UpwardsScrollVelocity -= 0.015;
glutPostRedisplay();
}
//*********************************************
//* printToConsoleWindow() *
//*********************************************
void printToConsoleWindow()
{
int l,lenghOfQuote, i;
for( l=0;l<numberOfQuotes;l++)
{
lenghOfQuote = (int)strlen(quote[l]);
for (i = 0; i < lenghOfQuote; i++)
{
//cout<<quote[l][i];
}
//out<<endl;
}
}
//*********************************************
//* RenderToDisplay() *
//*********************************************
void RenderToDisplay()
{
int l,lenghOfQuote, i;
glTranslatef(0.0, -100, UpwardsScrollVelocity);
glRotatef(-20, 1.0, 0.0, 0.0);
glScalef(0.1, 0.1, 0.1);
for( l=0;l<numberOfQuotes;l++)
{
lenghOfQuote = (int)strlen(quote[l]);
glPushMatrix();
glTranslatef(-(lenghOfQuote*37), -(l*200), 0.0);
for (i = 0; i < lenghOfQuote; i++)
{
glColor3f((UpwardsScrollVelocity/10)+300+(l*10),(UpwardsScrollVelocity/10)+300+(l*10),0.0);
glutStrokeCharacter(GLUT_STROKE_ROMAN, quote[l][i]);
}
glPopMatrix();
}
}
//*********************************************
//* glutDisplayFunc(myDisplayFunction); *
//*********************************************
void myDisplayFunction(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 30.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
RenderToDisplay();
glutSwapBuffers();
}
//*********************************************
//* glutReshapeFunc(reshape); *
//*********************************************
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1.0, 1.0, 3200);
glMatrixMode(GL_MODELVIEW);
}
//*********************************************
//* int main() *
//*********************************************
int main()
{
strcpy(quote[0],"Luke, I am your father!.");
strcpy(quote[1],"Obi-Wan has taught you well. ");
strcpy(quote[2],"The force is strong with this one. ");
strcpy(quote[3],"Alert all commands. Calculate every possible destination along their last known trajectory. ");
strcpy(quote[4],"The force is with you, young Skywalker, but you are not a Jedi yet.");
numberOfQuotes=5;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 400);
glutCreateWindow("StarWars scroller");
glClearColor(0.0, 0.0, 0.0, 1.0);
glLineWidth(3);
glutDisplayFunc(myDisplayFunction);
glutReshapeFunc(reshape);
glutIdleFunc(timeTick);
glutMainLoop();
return 0;
}
glutStrokeCharacter不是opengl函數 – 2013-05-16 12:04:59
它適合於glxxx()OP的要求,雖然:) – AndroidGecko 2013-11-03 18:58:19
這裏的代碼被修改爲在Ubuntu上工作(glutInit,包括):https://gist.github.com/tgandor/3963f112324030a2c833 – 2015-03-17 15:30:14
加載一個帶有字符的圖像作爲紋理,並根據您想要的字符繪製該紋理的一部分。您可以使用繪圖程序創建該紋理,對其進行硬編碼或使用窗口組件繪製圖像並檢索該圖像以獲取系統字體的精確副本。
無需使用Glut或任何其他擴展,只需基本的OpenGL可操作性。它完成了這項工作,更不用說數十年來由專業程序員在非常成功的遊戲和其他應用程序中這樣做了。
甚至有一些程序可以用來爲您生成圖像紋理。 – fintelia 2014-07-17 17:41:18
理論
爲什麼很難
流行的字體格式,如TrueType和OpenType是矢量輪廓格式:他們用貝塞爾曲線來定義字母的邊界。
轉化這些格式轉換爲像素陣列(光柵化)是過於具體,從OpenGL的範圍,特別是因爲OpenGL的沒有非直語(例如見Why is there no circle or ellipse primitive in OpenGL?)
最簡單的方法是先光柵字體我們自己在CPU上,然後將像素數組作爲紋理賦予OpenGL。
然後OpenGL知道如何通過紋理非常好地處理像素數組。
紋理圖集
我們可以光柵字符,每幀並重新創建的紋理,但不是非常有效,特別是如果字符大小是固定的。
更有效的方法是將您計劃使用的所有字符柵格化並將其填充到單個紋理中。
然後將其傳輸到GPU一次,並使用它與自定義uv座標的紋理來選擇正確的字符。
這種方法被稱爲https://en.wikipedia.org/wiki/Texture_atlas,它不僅可用於紋理,還可用於其他重複使用的紋理,如2D遊戲中的貼圖或Web UI圖標。
質感十足的維基百科圖片,這是本身的FreeType-GL拍攝,說明了這口井:
我懷疑優化字符的位置,以最小的結構問題是一個NP問題,請參閱:What algorithm can be used for packing rectangles of different sizes into the smallest rectangle possible in a fairly optimal way?
Web開發中使用同樣的技術來一次傳輸幾個小圖像(如圖標),但它被稱爲「CSS Sprites」:https://css-tricks.com/css-sprites/並用於隱藏網絡延遲而不是那個CPU/GPU通信。
非CPU光柵方法
也存在不使用的CPU光柵到紋理的方法。
CPU rastering很簡單,因爲它儘可能少地使用GPU,但我們也開始考慮是否可以進一步使用GPU效率。
這FOSDEM 2014視頻https://youtu.be/LZis03DXWjE?t=886說明其他現有技術:
- 鑲嵌:將字體轉換爲微小的三角形。 GPU非常擅長繪製三角形。缺點:
- 產生一束三角形
- 的O(N log n)的三角形上的着色器
- 計算曲線的CPU計算。 Blinn-Loop在2005年的一篇論文中提出了這種方法。下行:複雜。請參閱:Resolution independent cubic bezier drawing on GPU (Blinn/Loop)
- 直接硬件實現,如OpenVG https://en.wikipedia.org/wiki/OpenVG。下行:由於某種原因沒有得到廣泛實施。參見:
字體的3D幾何結構的內側透視
渲染與立體三維幾何的內部字體(相比於正交HUD )要複雜得多,因爲透視可以使角色的一部分更接近屏幕和la比另一個更高,從而實現統一的CPU離散化(例如,光柵,鑲嵌)在關閉部分看起來不好。這實際上是一個活躍的研究課題:
- What is state-of-the-art for text rendering in OpenGL as of version 4.1?
- http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
距離場是現在流行的技術之一。
實現
下面的示例是在Ubuntu 15.10所有測試。
因爲這是如前面所討論的複雜問題,大多數的例子是大,會炸掉這個答案的30K字符的限制,所以只克隆各自的Git代碼庫進行編譯。
但它們都是完全開源的,所以你可以只用RTFS。
FreeType的解決方案
FreeType貌似主導開源字體光柵化庫,所以這將允許我們使用TrueType和OpenType字體,使之成爲最完美的解決方案。
https://github.com/rougier/freetype-gl
是一套例子OpenGL和FreeType的,但或多或少進化爲做它暴露了一個體面的API庫。
在任何情況下,它應該已經能夠通過複製粘貼一些源代碼,它在你的項目整合。
它提供了開箱即用的紋理圖譜和距離場技術。下
演示:https://github.com/rougier/freetype-gl/tree/master/demos
不有Debian的軟件包,並有疼痛感在Ubuntu 15.10編譯:https://github.com/rougier/freetype-gl/issues/82#issuecomment-216025527(包裝的問題,一些上游),但它作爲了16.10更好。
不有一個很好的安裝方法:https://github.com/rougier/freetype-gl/issues/115
生成漂亮的輸出這樣的演示:
libdgx https://github.com/libgdx/libgdx/tree/1.9.2/extensions/gdx-freetype
例子/教程:
- 一個NEHE教程:http://nehe.gamedev.net/tutorial/freetype_fonts_in_opengl/24001/
- http://learnopengl.com/#!In-Practice/Text-Rendering提到它,但我找不到可運行的源代碼
- SO問題:
個其他字體光柵化
那些似乎比FreeType的那麼好,但可能更輕巧:
- https://github.com/nothings/stb/blob/master/stb_truetype.h
- http://www.angelcode.com/products/bmfont/
安東的OpenGL 4教程實例26 「位圖字體」
- 教程:http://antongerdelan.net/opengl/)
- 源:https://github.com/capnramses/antons_opengl_tutorials_book/blob/9a117a649ae4d21d68d2b75af5232021f5957aac/26_bitmap_fonts/main.cpp
的字體是由作者手動創建並且存儲在單個文件.png
。字母在圖像內以數組形式存儲。
這種方法當然不是很一般,而且你會遇到國際化的困難。
建設有:
make -f Makefile.linux64
輸出預覽:
OpenGL的教程第11章 「2D字體」
- 教程:http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-11-2d-text/
- 源:https://github.com/opengl-tutorials/ogl/blob/71cad106cefef671907ba7791b28b19fa2cc034d/tutorial11_2d_fonts/tutorial11.cpp
紋理是從DDS files生成。
本教程介紹瞭如何使用CBFG和Paint.Net創建DDS文件。
輸出預覽:
出於某種原因,蘇珊缺少我,但時間計數器工作正常:https://github.com/opengl-tutorials/ogl/issues/15
FreeGLUT
過多已經glutStrokeCharacter
和FreeGLUT是開源... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255
OpenGLText
https://github.com/tlorach/OpenGLText
的TrueType光柵。由NVIDIA員工提供。旨在重用。還沒有嘗試過。
的ARM Mali SDK GLES樣品
http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/似乎編碼一個PNG的所有字符,並從那裏砍他們。
SDL_ttf
來源:https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c
住在一個獨立的樹SDL,並可以輕鬆集成。
不提供紋理圖集實施然而,這樣的表現將受到限制:Rendering fonts and text with SDL2 efficiently
相關主題
- 1. 使用OpenGL在android上繪製文本
- 2. 如何在C++中使用GLUT/OpenGL繪製文本?
- 3. 如何使用OpenGL,SDL和C++繪製文本?
- 4. 如何使用QStyledItemDelegate僅繪製背景而不覆蓋文本?
- 5. 如何使用OpenGL ES繪製NURB
- 6. 使用Opengl繪製立方體3D
- 7. 如何在OpenGL中繪製立方體?
- 8. 使用OpenGL的Bresenham算法繪製圓
- 9. 如何使用方法繪製臉部
- 10. 如何在<canvas>上繪製文本,該文本遵循使用quadraticCurveTo方法繪製的二次曲線
- 11. 使用OpenGL從文本文件中繪製圖像
- 12. 如何使用OpenGL在中心按鈕上繪製正方形?
- 13. 如何使用imagemagick繪製文本?
- 14. 如何使用sdl_ttf繪製純文本?
- 15. 如何使用Libgdx/Java繪製文本?
- 16. 如何繪製文本和,使用R
- 17. 如何使用TextPainter繪製文本?
- 18. 繪製3D使用OpenGL
- 19. 使用OpenGL繪製NG
- 20. OpenGL 4:使用glVertexAttrib繪製
- 21. Opengl基本立方體繪圖,但立方體繪製單色
- 22. 繪圖文本使用OpenGL和Allegro 5
- 23. 如何僅繪製文本的輪廓,而不繪製填充本身?
- 24. OpenGL的繪製文本對象除了
- 25. 在OpenGL視圖中繪製文本
- 26. opengl顯示形狀和繪製文本
- 27. iOS OpenGL ES - 僅根據請求繪製
- 28. 什麼是不使用OpenGL繪製精靈的簡單方法?
- 29. 使用Java和OpenGL繪製3D樹的方法有哪些?
- 30. 使用SDL將文本繪製到OpenGL表面上
感謝訥河教程鏈接 – befzz 2014-08-09 15:36:02