OpenGL 메서드만 사용하여 텍스트를 그리는 방법
OpenGL 메서드(즉, OpenGL 메서드) 외에는 사용할 수 있는 옵션이 없음glxxx()
방법). 글공법만으로 글씨를 그려야 해.빨간 책을 읽고 난 후, 오직 그 책을 통해서만 가능하다는 것을 이해한다.glBitmap()
수 것이다만약 이것이 유일한 방법이라면, 모든 등장인물에 대한 픽셀 배열 정보에 대해 나를 도와줄 수 있을까?텍스트를 그리는 다른 방법은 없을까?
이론
왜 힘든가
TrueType과 OpenType과 같은 인기 있는 글꼴 형식은 벡터 윤곽선 형식이다. 이들은 Bezier 곡선을 사용하여 문자의 경계를 정의한다.
특히 OpenGl에 비직선 원형이 없기 때문에(예: OpenGL에 원이나 타원이 없는 이유 참조) 이러한 형식을 픽셀 배열(래스터라이제이션)으로 변환하는 것은 너무 구체적이고 OpenGL의 범위를 벗어난다.
가장 쉬운 방법은 먼저 CPU에 래스터 글꼴을 입력한 다음 픽셀 배열을 OpenGL에 텍스처로 제공하는 것이다.
그러면 OpenGL은 질감을 통해 픽셀 배열을 처리하는 방법을 매우 잘 알고 있다.
텍스처 지도책
모든 프레임에 대해 문자를 래스터하고 텍스처를 다시 만들 수 있지만, 문자의 크기가 고정되어 있는 경우에는 특히 효율적이지 않다.
보다 효율적인 접근방식은 당신이 사용하고자 하는 모든 문자를 래스터링하고 그것들을 하나의 텍스쳐에 채우는 것이다.
그리고 그것을 GPU로 한 번 옮기고, 그 질감을 맞춤 UV 좌표로 사용하여 알맞은 문자를 선택한다.
이 접근 방식을 텍스처 아틀라스라고 하며, 텍스처뿐만 아니라 2D 게임이나 웹 UI 아이콘의 타일처럼 반복적으로 사용되는 다른 텍스처에도 사용할 수 있다.
위키피디아의 전체 질감의 그림은 그 자체로 자유형-글에서 찍은 것인데, 이것을 잘 보여준다.
나는 문자 배치를 가장 작은 질감 문제에 최적화하는 것이 NP-하드 문제라고 생각한다. 참조: 크기가 다른 직사각형을 가능한 가장 작은 직사각형으로 포장하는 데 어떤 알고리즘을 사용할 수 있는가?
(아이콘과 같은) 여러 개의 작은 영상을 한 번에 전송하기 위해 웹 개발에도 같은 기법을 사용하지만, https://css-tricks.com/css-sprites/이라고 하며 CPU/GPU 통신 대신 네트워크의 대기 시간을 숨기기 위해 사용된다.
비 CPU 래스터 방법
CPU 래스터를 텍스쳐에 사용하지 않는 방법도 있다.
CPU 래스터링은 GPU를 최대한 적게 사용하기 때문에 간단하지만, GPU 효율을 더 많이 사용할 수 있을지에 대해서도 생각하기 시작한다.
이 FOSDEM 2014 비디오는 기타 기존 기법을 설명한다.
- 테셀레이션: 글꼴을 작은 삼각형으로 변환한다.GPU는 삼각형 그리기를 정말 잘한다.단점:
- 삼각형 한 묶음을 생성하다.
- 삼각형의 O(n log n) CPU 계산
- 셰이더로 곡선을 계산하다블린-루프의 2005년 논문은 이 방법을 지도에 올렸다.단점: 복잡함.참고 항목: GPU(Blinn/Loop)의 분해능 독립 입방 베지어 도면
- OpenVG와 같은 직접 하드웨어 구현.단점: 어떤 이유에서인지 그다지 널리 시행되지 않는다.참조:
원근법을 사용한 3D 기하학 내부의 글꼴
3D 기하학 내부의 글꼴을 원근법으로 렌더링(직교 HUD와 비교)하는 것은 훨씬 더 복잡하다. 원근법은 캐릭터의 한 부분을 화면에 훨씬 가깝고 다른 부분보다 크게 만들 수 있기 때문에, 근접한 부분에서 균일한 CPU 디스커트화(예: 래스터, 테셀레이션)가 나쁘게 보일 수 있기 때문이다.이것은 실제로 활발한 연구 주제다.
- 버전 4.1의 OpenGL에서 텍스트 렌더링에 대한 최첨단이란?
- http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
거리 분야는 현재 인기 있는 기술 중 하나이다.
구현
다음의 예들은 모두 우분투 15.10에서 시험되었다.
이것은 앞에서 논의한 바와 같이 복잡한 문제이기 때문에, 대부분의 예는 크며, 이 답변의 30k char 한도를 날려버릴 것이므로, 각각의 Git 저장소를 복제하여 컴파일하기만 하면 된다.
하지만 그것들은 모두 완전히 열린 소스여서 당신은 RTFS만 사용할 수 있다.
FreeType 솔루션
FreeType은 지배적인 오픈 소스 글꼴 래스터화 라이브러리처럼 보이기 때문에 TrueType과 OpenType 글꼴을 사용할 수 있어 가장 우아한 솔루션이다.
https://github.com/rougier/freetype-gl
OpenGL과 자유형(freetype)을 예로 들었지만, 이를 수행하고 적절한 API를 제공하는 라이브러리로 진화하고 있다.
어떤 경우든, 일부 소스 코드를 복사하여 프로젝트에 통합하는 것이 이미 가능해야 한다.
텍스처 아틀라스와 원거리 필드 기법을 모두 제공한다.
데모 대상: https://github.com/rougier/freetype-gl/tree/master/demos
데비안 패키지는 없고, 우분투 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/
Anton의 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-tutorial 장 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 파일에서 생성된다.
자습서에서는 CBFG와 그림판을 사용하여 DDS 파일을 생성하는 방법을 설명한다.그물.
출력 미리 보기:
왠지 수잔은 나에게 없어졌지만, 시간 카운터는 괜찮다: https://github.com/opengl-tutorials/ogl/issues/15
프리글루트
GLUT가 가지고 있다.glutStrokeCharacter
그리고 FreeGLut은 오픈소스...https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255
오픈GLText
https://github.com/tlorach/OpenGLText
TrueType 래스터.NVIDIA 직원.재사용을 목표로 한다.아직 안 먹어봤어.
ARM Mali GLES SDK 샘플
아마존닷컴은 PNG에 있는 모든 문자를 인코딩하고 거기서 잘라낸 것 같다.
SDL_ttf
출처: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c
SDL에 이르는 별도의 트리에 살고 쉽게 통합됨.
그러나 텍스처 아틀라스 구현을 제공하지 않으므로 성능 제한:SDL2로 글꼴과 텍스트를 효율적으로 렌더링하는 방법
관련 스레드
이미지를 텍스쳐로 로드하고 원하는 문자에 따라 해당 텍스처의 부분을 그리십시오.페인트 프로그램을 사용하여 텍스처를 만들거나, 하드코드를 하거나, 윈도우 구성요소를 사용하여 이미지에 그림을 그리고 시스템 글꼴의 정확한 복사본을 위해 이미지를 검색할 수 있다.
글루트나 기타 확장을 사용할 필요가 없으며, 기본적인 OpenGL 운전가능성만 사용할 수 있다.그것은 전문 프로그래머들에 의해 수십 년 동안 매우 성공적인 게임과 다른 어플리케이션에서 이렇게 이루어졌다는 것은 말할 것도 없고, 그 일을 완수한다.
이 글은 다양한 기법을 사용하여 OpenGL에서 텍스트를 렌더링하는 방법을 설명한다.
Opengl만 사용할 경우 다음과 같은 몇 가지 방법이 있다.
- glBitmap 사용
- 텍스처 사용
- 표시 목록 사용
일반 OpenGL에서 텍스트를 그리는 것은 직선으로 전달되는 작업이 아니다.이 작업을 수행하는 라이브러리를 살펴보십시오(라이브러리를 사용하거나 구현 예시).
일부 좋은 시작점은 GLFont, OpenGL 글꼴 조사 및 비트맵 글꼴(Windows)용 NeHe 자습서일 수 있다.
글꼴 조사에 언급된 것처럼 비트맵이 OpenGL에서 텍스트를 얻는 유일한 방법은 아니라는 점에 유의하십시오.
OpenGL에서 텍스트를 그리는 가장 좋은 해결책은 텍스처 폰트라고 생각하는데, 나는 그들과 오랫동안 일한다.그들은 유연하고, 빠르고, 멋져 보인다.나는 폰트 파일(.ttf)을 텍스처로 변환하기 위해 특수 프로그램을 사용한다. 이 프로그램은 일부 내부 "콤플렉스" 포맷의 파일에 저장된다(내 버전은 원래 유니코드 등을 지원하는 것과는 다소 거리가 멀었지만 나는 http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System를 기반으로 포맷과 프로그램을 개발했다).기본 앱을 시작할 때 이 "내부" 형식에서 글꼴이 로드된다.자세한 내용은 위의 링크를 참조하십시오.
이러한 접근방식으로 메인 앱은 FreeType과 같은 특별한 라이브러리를 사용하지 않는데, 이것은 나 역시 바람직하지 않다.텍스트는 표준 OpenGL 기능을 사용하여 그리고 있다.
사용하다glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString)
.
예: 스타워즈 스크롤러.
#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;
}
참조URL: https://stackoverflow.com/questions/8847899/how-to-draw-text-using-only-opengl-methods
'Programing' 카테고리의 다른 글
공리 호출에 성공한 후 Vue.js 구성 요소가 상위 구성 요소로 방출되지 않음 (0) | 2022.05.15 |
---|---|
선행 0으로 Java 문자열을 포맷하는 방법 (0) | 2022.05.15 |
Spring Java Config: 런타임 인수를 사용하여 프로토타입 범위 @Bean을 만드는 방법 (0) | 2022.05.14 |
vue-i18n - '알 수 없는' 토큰 유형 감지 (0) | 2022.05.14 |
vuejs에서 재사용 가능한 api-properties 구성 요소를 구현하는 방법? (0) | 2022.05.14 |