2012-01-13 51 views
27

Tôi không có tùy chọn để sử dụng khác hơn là phương pháp opengl (đó là phương thức glxxx()()). Tôi chỉ cần vẽ văn bản bằng cách sử dụng phương thức gl. Sau khi đọc cuốn sách đỏ tôi hiểu rằng nó chỉ có thể thông qua phương thức glBitmap(). Nếu đây là cách duy nhất có thể, thì bất kỳ ai có thể giúp tôi với thông tin mảng pixel cho tất cả các ký tự. Có cách nào khác để vẽ văn bản không?Làm cách nào để vẽ văn bản chỉ bằng các phương pháp OpenGL?

Trả lời

5

This article mô tả cách hiển thị văn bản trong OpenGL bằng các kỹ thuật khác nhau.

Với chỉ sử dụng OpenGL, có một số cách sau:

  • sử dụng glBitmap
  • sử dụng kết cấu
  • sử dụng danh sách hiển thị
7

Vẽ văn bản trong OpenGL đơn giản không phải là một straigth- nhiệm vụ chuyển tiếp. Bạn có lẽ nên có một cái nhìn tại các thư viện để làm điều này (hoặc bằng cách sử dụng một thư viện hoặc như là một ví dụ thực hiện).

Một số điểm khởi đầu tốt có thể là GLFont, OpenGL Font SurveyNeHe Tutorial for Bitmap Fonts (Windows).

Lưu ý rằng bitmap không phải là cách duy nhất để đạt được văn bản trong OpenGL như đã đề cập trong khảo sát phông chữ.

+0

nhờ cho Nehe hướng dẫn liên kết – befzz

1

Tôi nghĩ rằng giải pháp tốt nhất để vẽ văn bản trong OpenGL là phông chữ kết cấu, tôi làm việc với chúng trong một thời gian dài. Họ là linh hoạt, nhanh chóng và đẹp trai (với một số trường hợp ngoại lệ phía sau). Tôi sử dụng chương trình đặc biệt để chuyển đổi các tệp phông chữ (.ttf chẳng hạn) thành kết cấu, được lưu vào tệp của một số định dạng "phông chữ" bên trong (tôi đã phát triển định dạng và chương trình dựa trên http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System mặc dù phiên bản của tôi đã đi xa so với hỗ trợ ban đầu Unicode và vv). Khi bắt đầu ứng dụng chính, phông chữ được tải từ định dạng "nội bộ" này. Xem liên kết ở trên để biết thêm thông tin.

Với cách tiếp cận như vậy, ứng dụng chính không sử dụng bất kỳ thư viện đặc biệt nào như FreeType, điều này cũng không được mong đợi đối với tôi. Văn bản đang được vẽ bằng chức năng OpenGL tiêu chuẩn.

+0

Nếu tôi có thể thêm thứ gì đó vào dy tốt câu trả lời, chú ý đến optmization của bất kỳ font rendering hệ thống vì nó có thể tác động đến các buổi biểu diễn của động cơ của bạn trên rất hạn chế tài nguyên HW như thiết bị di động. –

8

enter image description here

Sử dụng glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString).

Ví dụ: STAR WARS 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; 
} 
+46

glutStrokeCharacter không phải là một hàm opengl –

+15

nó phù hợp với yêu cầu OPxxx() OP mặc dù :) – AndroidGecko

+1

Đây là mã được sửa đổi để hoạt động trên Ubuntu (glutInit, bao gồm): https://gist.github.com/tgandor/3963f112324030a2c833 –

2

Tải hình ảnh có ký tự làm kết cấu và vẽ phần kết cấu đó tùy thuộc vào ký tự bạn muốn. Bạn có thể tạo texture đó bằng cách sử dụng một chương trình vẽ, hardcode nó hoặc sử dụng một thành phần cửa sổ để vẽ một hình ảnh và lấy hình ảnh đó cho một bản sao chính xác của phông chữ hệ thống.

Không cần sử dụng Glut hoặc bất kỳ tiện ích mở rộng nào khác, chỉ khả năng hoạt động OpenGL cơ bản. Nó được thực hiện công việc, chưa kể rằng nó được thực hiện như thế này trong nhiều thập kỷ bởi các lập trình viên chuyên nghiệp trong các trò chơi rất thành công và các ứng dụng khác.

+1

Thậm chí còn có các chương trình mà bạn có thể sử dụng để tạo kết cấu hình ảnh cho bạn. – fintelia

36

Theory

Tại sao rất khó

được ưa thích định dạng phông chữ giống như chữ TrueType và OpenType là định dạng phác thảo vector: họ sử dụng các đường cong Bezier để xác định ranh giới của bức thư.

Image source.

Chuyển đổi những định dạng vào mảng các pixel (rasterization) là quá cụ thể và ra khỏi phạm vi OpenGL của, đặc biệt vì OpenGL không có nguyên thủy phi thẳng (ví dụ thấy Why is there no circle or ellipse primitive in OpenGL?)

Cách tiếp cận dễ nhất là phông chữ raster đầu tiên chính mình trên CPU, và sau đó cung cấp cho các mảng của điểm ảnh để OpenGL như là một kết cấu.

OpenGL sau đó biết cách xử lý các mảng pixel thông qua kết cấu rất tốt.

atlas Texture

Chúng ta có thể raster ký tự cho mỗi khung và tái tạo các kết cấu, nhưng đó không phải là rất hiệu quả, đặc biệt nếu nhân vật có kích thước cố định.

Cách tiếp cận hiệu quả hơn là raster tất cả các ký tự bạn định sử dụng và nhồi nhét chúng trên một kết cấu duy nhất.

Sau đó chuyển nó tới GPU một lần và sử dụng kết cấu với tọa độ uv tùy chỉnh để chọn ký tự phù hợp.

Phương pháp này được gọi là https://en.wikipedia.org/wiki/Texture_atlas và nó có thể được sử dụng không chỉ cho kết cấu mà còn được sử dụng nhiều lần kết cấu khác, như gạch trong trò chơi 2D hoặc biểu tượng giao diện người dùng web.

Bức tranh Wikipedia của kết cấu đầy đủ, mà là bản thân lấy từ freetype-gl, minh họa này cũng:

Tôi nghi ngờ rằng việc tối ưu hóa vị trí nhân vật cho vấn đề kết cấu nhỏ nhất là một NP-cứng Vấn đề, xem: What algorithm can be used for packing rectangles of different sizes into the smallest rectangle possible in a fairly optimal way?

Kỹ thuật tương tự được sử dụng trong phát triển web để truyền một số hình ảnh nhỏ (như biểu tượng) cùng một lúc, nhưng nó được gọi là "CSS Sprites": https://css-tricks.com/css-sprites/ và được sử dụng để ẩn độ trễ của mạng thay vì Giao tiếp CPU/GPU.

Non-CPU phương pháp raster

Ngoài ra còn tồn tại phương pháp mà không sử dụng các raster CPU để kết cấu.

Rastering CPU rất đơn giản vì nó sử dụng GPU càng ít càng tốt, nhưng chúng tôi cũng bắt đầu nghĩ liệu có thể sử dụng hiệu quả GPU hơn nữa không.

này FOSDEM 2014 Video https://youtu.be/LZis03DXWjE?t=886 giải thích các kỹ thuật khác hiện có:

Fonts bên trong của hình học 3D với quan điểm

Rendering phông chữ bên trong của hình học 3D với quan điểm (so với một HUD trực giao) là phức tạp hơn nhiều, bởi vì quan điểm có thể làm cho một phần của nhân vật gần gũi hơn với màn hình và la rger hơn khác, làm cho một CPU cụ thể thống nhất (ví dụ raster, tesselation) trông xấu ở phần gần. Điều này thực sự là một chủ đề nghiên cứu hoạt động:

enter image description here

lĩnh vực Khỏang cách là một trong những kỹ thuật phổ biến hiện nay.

Triển khai

Ví dụ sau được kiểm tra trên Ubuntu 15.10.

Vì đây là một vấn đề phức tạp như đã thảo luận trước đây, hầu hết các ví dụ đều lớn, và sẽ làm tăng giới hạn 30k char của câu trả lời này, vì vậy hãy sao chép kho lưu trữ Git tương ứng để biên dịch.

Tuy nhiên, tất cả đều là nguồn mở hoàn toàn, vì vậy bạn chỉ có thể RTFS.

giải pháp FreeType

FreeType trông giống như thư viện rasterization phông chữ mã nguồn mở chiếm ưu thế, vì vậy nó sẽ cho phép chúng ta sử dụng chữ TrueType và OpenType, khiến nó trở thành giải pháp thanh lịch nhất.

Ví dụ/hướng dẫn:

rasterizers phông chữ khác

Những dường như ít tốt hơn FreeType, nhưng có thể nhẹ hơn:

Anton của OpenGL 4 Hướng dẫn dụ 26 "Bitmap phông chữ"

Phông chữ được tạo ra bởi tác giả bằng tay và lưu trữ trong một tập tin duy nhất .png. Các chữ cái được lưu trữ dưới dạng mảng bên trong hình ảnh.

Phương pháp này tất nhiên không phải là rất chung chung và bạn sẽ gặp khó khăn với quốc tế.

Xây dựng với:

make -f Makefile.linux64 

Output preview:

enter image description here

OpenGL-tutorial chương 11 "2D phông chữ"

Kết cấu được tạo từ DDS files.

Hướng dẫn giải thích cách các tệp DDS được tạo, sử dụng CBFGPaint.Net.

Output preview:

enter image description here

Đối với một số lý do Suzanne là mất tích đối với tôi, nhưng bộ đếm thời gian hoạt động tốt: https://github.com/opengl-tutorials/ogl/issues/15

FreeGLUT

GLUT có glutStrokeCharacter và FreeGLUT là mã nguồn mở ... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255

OpenGLText

https://github.com/tlorach/OpenGLText

TrueType raster. Bởi nhân viên NVIDIA. Nhằm mục đích sử dụng lại. Chưa thử nó.

ARM Mali GLES SDK Sample

http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ dường như để mã hóa tất cả các ký tự trên một PNG, và cắt chúng từ đó.

SDL_ttf

enter image description here

Nguồn: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c

Sống ở một cây riêng biệt để SDL, và tích hợp một cách dễ dàng.

Không cung cấp một thực hiện bản đồ kết cấu Tuy nhiên, vì vậy hiệu suất sẽ được giới hạn: Rendering fonts and text with SDL2 efficiently

đề liên quan

Các vấn đề liên quan