2013-08-13 2 views
1

freetype을 사용하고 있으며 텍스트를 렌더링하기 위해 수행해야 할 유일한 작업은 ft_bitmap을 OpenGL로 렌더링 할 수있는 것으로 변환하는 것입니다. 나는 glfw를 사용하고있다. 내가 텍스트 렌더러를 초기화하는 데 사용하고 무엇렌더링 텍스트 - freetype 빈 화면

#include <exception> 
    #include <iostream> 
    #include <string> 
    #include <glew.h> 
    #include <GL/glfw.h> 
    #include <iterator> 
    #include "../include/TextRenderer.h" 
    #include <ft2build.h> 
    #include FT_FREETYPE_H 
    #include <stdexcept> 
    #include <freetype/ftglyph.h> 


    using std::runtime_error; 
    using std::cout; 
    TextRenderer::TextRenderer(int x, int y, FT_Face Face, std::string s) 
    { 


     FT_Set_Char_Size(
      Face, /* handle to face object   */ 
      0,  /* char_width in 1/64th of points */ 
      16*64, /* char_height in 1/64th of points */ 
      0,  /* horizontal device resolution */ 
      0); /* vertical device resolution  */ 
     slot= Face->glyph; 

     text = s; 
     setsx(x); 
     setsy(y); 
     penX = x; 
     penY = y; 
     face = Face; 
     //shaders 
     GLuint v = glCreateShader(GL_VERTEX_SHADER) ; 
     const char* vs = "void main(){ gl_Position = ftransform();}"; 
     glShaderSource(v,1,&vs,NULL); 
     glCompileShader(v); 
     GLuint f = glCreateShader(GL_FRAGMENT_SHADER) ; 
     const char* fs = "uniform sampler2D texture1; void main() { gl_FragColor = texture2D(texture1, gl_TexCoord[0].st); //And that is all we need}"; 
     glShaderSource(f,1,&fs,NULL); 
     glCompileShader(f); 
     Program= glCreateProgram(); 
     glAttachShader(Program,v); 
     glAttachShader(Program,f); 
     glLinkProgram(Program); 


    } 
    void TextRenderer::render() 
    { 
     glUseProgram(Program); 
     FT_UInt glyph_index; 
     for (int n = 0; n < text.size(); n++) 
     { 
      /* retrieve glyph index from character code */ 

      glyph_index = FT_Get_Char_Index(face, text[n]); 

       /* load glyph image into the slot (erase previous one) */ 
       error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER); 

       draw(&face->glyph->bitmap,penX + slot->bitmap_left,penY - slot->bitmap_top); 

       penX += *(&face->glyph->bitmap.width)+3; 
       penY += slot->advance.y >> 6; /* not useful for now */ 
      } 
     } 
    void TextRenderer::draw(FT_Bitmap * bitmap,float x,float y) 
{ 



GLuint texture [0] ; 

    glGenTextures(1,texture); 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
glTexImage2D (GL_TEXTURE_2D, 0, GL_RED , bitmap->width, bitmap->rows, 0, GL_RED , GL_UNSIGNED_BYTE, bitmap); 


// int loc = glGetUniformLocation(Program, "texture1"); 
// glUniform1i(loc, 0); 
glBindTexture(GL_TEXTURE_2D, texture[0]); 
glEnable(GL_TEXTURE_2D); 
     int height=bitmap->rows/10; 
     int width=bitmap->width/10; 
     glBegin(GL_QUADS); 
     glTexCoord2f (0.0, 0.0); 
     glVertex2f(x,y); 
     glTexCoord2f (1.0, 0.0); 
     glVertex2f(x+width,y); 
     glTexCoord2f (1.0, 1.0); 
     glVertex2f(x+width,y+height); 
     glTexCoord2f (0.0, 1.0); 
     glVertex2f(x,y+height); 
     glEnd(); 
glDisable(GL_TEXTURE_2D); 

} 

가 :

FT_Library library; 
FT_Face  arial; 
FT_Error error = FT_Init_FreeType(&library); 
    if (error) 
    { 
     throw std::runtime_error("Freetype failed"); 
    } 

    error = FT_New_Face(library, 
         "C:/Windows/Fonts/Arial.ttf", 
         0, 
         &arial); 
    if (error == FT_Err_Unknown_File_Format) 
    { 
     throw std::runtime_error("font format not available"); 
    } 
    else if (error) 
    { 
     throw std::runtime_error("Freetype font failed"); 
    } 
TextRenderer t(5,10,arial,"Hello"); 
    t.render(); 
+0

처음에는 초기화되지 않은 원시 포인터를 null이 아닌 배열 * 기본 포인터가 필요한 함수 ('glGenTextures()')에 전달합니다. 텍스쳐 배열에 적절한 양의 메모리를 할당하거나 자동 고정 배열을 전달하십시오 (귀하의 경우에는 하나만 얻으므로 후자가 될 가능성이 큽니다). – WhozCraig

+0

기능이 적절하게 수정되었다는 잘못된 생각이 잘못되었습니다. 이제는 빈 화면이 나타납니다. – user2673108

답변

2

있어 내가 그냥 여기 빈 화면을 제공하고 그것을 할 시도하는 방식으로 내가 사용하고있는 코드는 OpenGL 또는 Freetype에 대한 각각의 호출이 무엇인지 이해하지 않아서 발생하는 프로그램의 많은 문제. 자습서를 서로 쌓는 대신 실제로 라이브러리에 대한 설명서를 읽어야합니다.

은 (는 glGetShaderiv로 컴파일하면 당신이 정말로 확인해야이 glGetProgramiv와 링크하는 경우)의 컴파일되지 않는 한

조각 쉐이더

const char* fs = "uniform sampler2D texture1; 
        void main() { 
         gl_FragColor = texture2D(texture1, gl_TexCoord[0].st); 
        //And that is all we need}";` 

이 쉐이더하여이 일을하자. 들여 쓰기를 올바르게했다면 }이 같은 행에 있고 // 이후에 주석 처리 된 것을 볼 수 있습니다. 따라서 댓글을 삭제하거나 \n을 사용하여 댓글을 종료해야합니다.

또한 최신 버전의 gl_TexCoord을 사용하는 OpenGL은 더 이상 사용되지 않지만 호환 프로필을 사용하는 경우 작동합니다.

버텍스 쉐이더

단지 조각 쉐이더처럼이되지 않는의 기능, 즉 ftransform() 사용했다.

더 큰 문제는 조각 쉐이더에서 버텍스 쉐이더를 통과하지 않고 gl_TexCoord[0]을 사용한다는 것입니다. 따라서 버텍스 쉐이더에 gl_TexCoord[0]=gl_MultiTexCoord0; 행을 추가해야합니다. 당신은 glTexImage2Dbitmap에 대한 포인터를 전달하고 있지만 bitmap 유형 FT_Bitmap *이다

텍스처 통과 (당신이 짐작 하듯이 그 또한 더 이상 사용되지 않습니다) 대신 bitmap->buffer을 통과해야합니다.

모든 문자마다 새로운 질감을 생성하지 않아야합니다 (특히 삭제하지 않는 경우는 제외). glGentextures을 한 번만 호출해야합니다 (다른 모든 초기화 항목을 거기에 넣기 때문에 TextRenderer 생성자에 넣을 수 있습니다).

그러면 컴파일러 오류가 발생하는 GLuint texture [0];이 있습니다.이 정수 부서입니다

int height=bitmap->rows/10; 
int width=bitmap->width/10; 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->width, bitmap->rows, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmap->buffer); 

기타 : 당신이 정말로 하나 개의 요소로 배열을해야하는 경우 다음 구문은 GLuint texture [1];

그래서 최종 호출이 다음과 같이 보일 것입니다 bitmap->width에 대한 값이 10보다 작 으면 결과로 0을 얻을 수 있습니다. 그러면 쿼티가 invi를 그리게됩니다. sible (높이 또는 너비 0). 개체를 볼 때 문제가 발생하면보기로 변환하거나 크기를 조정해야합니다. 이것은 또한 사용되지 않지만 다른 물건을 계속 사용하면 창의 크기가 [-100, -100]에서 [100,100] (왼쪽 아래에서 오른쪽으로)의 좌표계를 갖게됩니다.

glLoadIdentity(); 
glScalef(0.01f, 0.01f, 1.0f); 

당신은 또한에서 OpenGL에 FreeType에서에서 좌표 변환 놓치고,하는 Freetype는이 y이 상태에서 오른쪽으로 오프셋 왼쪽 상단의 [0,0]과 x에서 시작 좌표 시스템을 사용 아래쪽으로 오프셋. 따라서 OpenGL에서 이러한 좌표를 사용하면 모든 것이 거꾸로됩니다. 한 질감을 용도 변경과 편지를 그리기, 당신의 일반적인 방법에 관해서는

glfw Window

: 당신이 모든 결과는이 같은 (회색 배경 강조 다각형 시작과 끝을)보고해야 할 경우

편지를 재사용하고 동일한 질감을 덮어 쓰는 것은 비효율적 인 접근 방법처럼 보입니다. 하나의 큰 텍스처를 할당 한 다음 glTexSubImage2D을 사용하여 글리프를 작성하는 것이 좋습니다. freetype 재 렌더링 문자가 병목 현상이라면 필요한 모든 심볼을 시작 부분 (예 : 전체 ASCII 범위)에 하나의 텍스처로 작성한 다음 해당 텍스처를 텍스처지도로 사용할 수도 있습니다.

내 일반적인 조언은 또한 OpenGL을 배우고 싶지 않고 저수준 항목에 신경 쓸 필요없이 일부 크로스 플랫폼 렌더링을 사용하려는 경우 대신 렌더링 프레임 워크를 사용하는 것이 좋습니다.

+0

응답 해 주셔서 감사합니다. 몇 가지 질문이 있습니다. 먼저 tex 이미지에서 2d로 전화하여 glluminance로 변경하는 것이 중요합니까? 또한 광산을 렌더링 할 때 다음 http://imgur.com/NptMgk6을 볼 수 있습니다. 내 코드는 여기에서 볼 수 있습니다. http://pastebin.com/0M54fwpf 내 프로그램에 모든 문자의지도가 포함될 예정이며이 문자 처음에 추가되거나 처음 사용될 때 추가 될 것입니다. – user2673108

+0

@ user2673108'GLuint texture [1];'뒤에'glBindTexture (GL_TEXTURE_2D, texture [0]);'를 넣고 텍스쳐와 관련된 설정을 변경하기 전에 (그냥 바로 뒤에 넣으십시오) 현재 접근법을 유지하고 싶다면 메소드 끝에 glBindTexture (GL_TEXTURE_2D, 0);와'glDeleteTextures (1, texture [0];); '를 추가하는 것이 좋습니다. 또한 좌표 변환을 수행하지 않았으므로 여전히 거꾸로되어 있습니다. – PeterT

+0

@ user2673108 그리고'GL_RED'는 텍스처를 적색 채널에 업로드하기 때문에 텍스트는 표시되지만 붉은 색으로 표시되며 GL_LUMINANCE는 값을 모든 3 개의 채널 (빨강, 초록, 파랑)에 복사하여 흰색으로 보입니다. – PeterT