// ---------------------------------------------------------------------------- void text_buffer_clear( text_buffer_t * self ) { assert( self ); vertex_buffer_clear( self->buffer ); self->line_start = 0; self->line_ascender = 0; self->line_descender = 0; }
// ---------------------------------------------------------------- display --- void display( void ) { static int frame=0, time, timebase=0; static int count = 0; if( count == 0 && frame == 0 ) { printf( "Computing FPS with text generation and rendering at each frame...\n" ); printf( "Number of glyphs: %d\n", (int)wcslen(text)*line_count ); } frame++; time = glutGet( GLUT_ELAPSED_TIME ); if( time-timebase > (2500) ) { printf( "FPS : %.2f (%d frames in %.2f second, %.1f glyph/second)\n", frame*1000.0/(time-timebase), frame, (time-timebase)/1000.0, frame*1000.0/(time-timebase) * wcslen(text)*line_count ); timebase = time; frame = 0; ++count; if( count == 5 ) { printf( "\nComputing FPS with text rendering at each frame...\n" ); printf( "Number of glyphs: %d\n", (int)wcslen(text)*line_count ); } if( count > 9 ) { exit( EXIT_SUCCESS ); } } if( count < 5 ) { size_t i; vec4 color = {{0,0,0,1}}; vec2 pen = {{0,0}}; vertex_buffer_clear( buffer ); pen.y = -font->descender; for( i=0; i<line_count; ++i ) { pen.x = 10.0; add_text( buffer, font, text, &color, &pen ); pen.y += font->height - font->linegap; } } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glColor4f( 0,0,0,1 ); glBindTexture( GL_TEXTURE_2D, atlas->id ); vertex_buffer_render( buffer, GL_TRIANGLES, "vtc" ); glutSwapBuffers( ); }
void FontRenderer::RenderText(unsigned int x, unsigned int y, const char* pText) { bool IsCullEnabled = glIsEnabled(GL_CULL_FACE); glDisable(GL_CULL_FACE); assert(strlen(pText) < MAX_STRING_LEN); wchar_t text[MAX_STRING_LEN] = { 0 }; int len = mbstowcs(text, pText, strlen(pText)); assert(len > 0); vertex_buffer_clear( m_pTextBuffer ); TextureGlyph* pGlyph = texture_font_get_glyph( m_pFont, text[0] ); assert(pGlyph); Pen pen = {(float)x, (float)y}; texture_glyph_add_to_vertex_buffer( pGlyph, m_pTextBuffer, &markup, &pen, 0 ); for( size_t i=1; i<wcslen(text); ++i ) { pGlyph = texture_font_get_glyph( m_pFont, text[i] ); assert(pGlyph); int kerning = texture_glyph_get_kerning( pGlyph, text[i-1] ); texture_glyph_add_to_vertex_buffer( pGlyph, m_pTextBuffer, &markup, &pen, kerning ); } glActiveTexture(GL_TEXTURE0); glBindTexture( GL_TEXTURE_2D, m_pManager->atlas->texid ); m_fontShader.Enable(); int viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); float xScale = 2.0f / (float)viewport[2]; float yScale = 2.0f / (float)viewport[3]; GLfloat Trans[] = { xScale, 0.0f, 0.0f, -1.0f, 0.0f, yScale, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; m_fontShader.SetTransformation(Trans); vertex_buffer_render( m_pTextBuffer, GL_TRIANGLES, "vtc" ); if (IsCullEnabled) { glEnable(GL_CULL_FACE); } }
void Font::Draw2D(const Vector2Df& pos, const char* text) { add_text(m_buffer, m_font, m_fontFile->m_buffer, m_fontFile->m_bufLength, text, ((vec2*)&pos), m_currentSize); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); m_glProgram->SetModelViewProjection(); m_glProgram->SetUnifromTexture("diffuseMap", m_textureAtlas); m_glProgram->UseProgram(); vertex_buffer_render(m_buffer, GL_TRIANGLES); vertex_buffer_clear(m_buffer); }
// ---------------------------------------------------------------------------- void text_buffer_clear( text_buffer_t * self ) { assert( self ); vertex_buffer_clear( self->buffer ); self->line_start = 0; self->line_ascender = 0; self->line_descender = 0; vector_clear( self->lines ); self->bounds.left = 0.0; self->bounds.top = 0.0; self->bounds.width = 0.0; self->bounds.height = 0.0; }
void FontBufferCache::Add(const std::string &text, const Point3 &position, const GameColor &color, texture_font_t *font) { HashedString hash(text.c_str()); vertex_buffer_t *buffer = 0; if(Contains(text)) { buffer = m_vertexBufferMap.find(hash.getHashValue())->second; vertex_buffer_clear(buffer); } else { buffer = vertex_buffer_new("vertex:3f,tex_coord:2f,color:4f"); m_vertexBufferMap[hash.getHashValue()] = buffer; } F32 r = color.GetX(), g = color.GetY(), b = color.GetZ(), a = color.GetW(); F32 x = 0.0f; U32 size = (U32)text.size(); for(U32 i = 0; i < size; ++i) { texture_glyph_t *glyph = texture_font_get_glyph(font, text[i]); if(glyph != NULL) { I32 kerning = 0; if(i > 0) { kerning = texture_glyph_get_kerning(glyph, text[i - 1]); } x += (float)kerning; F32 x0 = (F32)(position.GetX() + x + glyph->offset_x); F32 y0 = (F32)(position.GetY() + glyph->offset_y); F32 x1 = (F32)(x0 + glyph->width); F32 y1 = (F32)(y0 - glyph->height); F32 s0 = glyph->s0; F32 t0 = glyph->t0; F32 s1 = glyph->s1; F32 t1 = glyph->t1; GLuint indices[6] = {0, 1, 2, 0, 2, 3}; vertex_t vertices[4] = { { x0, y0, 0.0f, s0, t0, r, g, b, a }, { x0, y1, 0.0f, s0, t1, r, g, b, a }, { x1, y1, 0.0f, s1, t1, r, g, b, a }, { x1, y0, 0.0f, s1, t0, r, g, b, a } }; vertex_buffer_push_back(buffer, vertices, 4, indices, 6); x += glyph->advance_x; } } }
// ----------------------------------------------------------- build_buffer --- void build_buffer( void ) { vec2 pen; size_t i; texture_font_t *font; texture_glyph_t *glyph; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; markup_t markup = { .family = "Arial", .size = 10.0, .bold = 0, .italic = 0, .rise = 0.0, .spacing = 0.0, .gamma = 2.2, .foreground_color = white, .background_color = none, .underline = 0, .underline_color = white, .overline = 0, .overline_color = white, .strikethrough = 0, .strikethrough_color = white, .font = 0, }; vertex_buffer_clear( buffer ); texture_atlas_clear( atlas ); if( p_family == VERA) { font = texture_font_new( atlas, "fonts/Vera.ttf", p_size ); } else if( p_family == VERA_MONO) { font = texture_font_new( atlas, "fonts/VeraMono.ttf", p_size ); } else if( p_family == GEORGIA) { font = texture_font_new( atlas, "fonts/Georgia.ttf", p_size ); } else if( p_family == TIMES ) { font = texture_font_new( atlas, "fonts/Times.ttf", p_size ); } else if( p_family == TAHOMA ) { font = texture_font_new( atlas, "fonts/Tahoma.ttf", p_size ); } else if( p_family == ARIAL ) { font = texture_font_new( atlas, "fonts/Arial.ttf", p_size ); } else if( p_family == VERDANA ) { font = texture_font_new( atlas, "fonts/Verdana.ttf", p_size ); } else { fprintf( stderr, "Error : Unknown family type\n" ); return; } font->hinting = p_hinting; font->filtering = 1; float norm = 1.0/(p_primary + 2*p_secondary + 2*p_tertiary); font->lcd_weights[0] = (unsigned char)(p_tertiary*norm*256); font->lcd_weights[1] = (unsigned char)(p_secondary*norm*256); font->lcd_weights[2] = (unsigned char)(p_primary*norm*256); font->lcd_weights[3] = (unsigned char)(p_secondary*norm*256); font->lcd_weights[4] = (unsigned char)(p_tertiary*norm*256); texture_font_load_glyphs( font, L" !\"#$%&'()*+,-./0123456789:;<=>?" L"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" L"`abcdefghijklmnopqrstuvwxyz{|}~" ); pen.x = 10; pen.y = 600 - font->height - 10; glyph = texture_font_get_glyph( font, text[0] ); add_glyph( glyph, buffer, &markup, &pen, 0 ); for( i=1; i<wcslen(text); ++i ) { if( text[i] == '\n' ) { pen.x = 10; pen.y -= font->height; // + 0.01*(size - (int)size)*font->height; } else { glyph = texture_font_get_glyph( font, text[i] ); float kerning = 0.0; if( p_kerning ) { kerning = texture_glyph_get_kerning( glyph, text[i-1] ); } add_glyph( glyph, buffer, &markup, &pen, kerning ); } } texture_font_delete (font ); } // ---------------------------------------------------------------- display --- void display(void) { if( p_invert ) { glClearColor( 0, 0, 0, 1 ); } else { glClearColor( 1, 1, 1, 1 ); } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, atlas->id ); if( !p_lcd_filtering ) { glEnable( GL_COLOR_MATERIAL ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( p_invert ) { glColor4f(1,1,1,1); } else { glColor4f(0,0,0,1); } } else { glEnable( GL_COLOR_MATERIAL ); glBlendFunc( GL_CONSTANT_COLOR_EXT, GL_ONE_MINUS_SRC_COLOR ); glEnable( GL_BLEND ); glColor3f( 1,1,1 ); if( p_invert ) { glBlendColor( 1, 1, 1, 1 ); } else { glBlendColor( 0, 0, 0, 1 ); } } if( !p_lcd_filtering ) { vertex_buffer_render( buffer, GL_TRIANGLES, "vt" ); } else { glUseProgram( program ); glUniform1i( texture_location, 0 ); glUniform1f( gamma_location, p_gamma ); float norm = 1.0/(p_primary+2*p_secondary+2*p_tertiary); glUniform1f( primary_location, p_primary*norm ); glUniform1f( secondary_location, p_secondary*norm ); glUniform1f( tertiary_location, p_tertiary*norm ); glUniform2f( pixel_location, 1.0/atlas->width, 1.0/atlas->height ); vertex_buffer_render( buffer, GL_TRIANGLES, "vtc" ); glUseProgram( 0 ); } TwDraw( ); glutSwapBuffers( ); } // ---------------------------------------------------------------- reshape --- void reshape( int width, int height ) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glMatrixMode(GL_MODELVIEW); TwWindowSize( width, height ); }
// ---------------------------------------------------------------- display --- void display( GLFWwindow* window ) { static int frame=0; static int count = 0; static double time; if( count == 0 && frame == 0 ) { printf( "Computing FPS with text generation and rendering at each frame...\n" ); printf( "Number of glyphs: %d\n", (int)strlen(text)*line_count ); } frame++; time = glfwGetTime( ); if( time > 2.5 ) { printf( "FPS : %.2f (%d frames in %.2f second, %.1f glyph/second)\n", frame/time, frame, time, frame/time * strlen(text)*line_count ); glfwSetTime( 0.0 ); frame = 0; ++count; if( count == 5 ) { printf( "\nComputing FPS with text rendering at each frame...\n" ); printf( "Number of glyphs: %d\n", (int)strlen(text)*line_count ); } if( count > 9 ) { glfwSetWindowShouldClose( window, GL_TRUE ); } } if( count < 5 ) { size_t i; vec4 color = {{0,0,0,1}}; vec2 pen = {{0,0}}; vertex_buffer_clear( buffer ); pen.y = -font->descender; for( i=0; i<line_count; ++i ) { pen.x = 10.0; add_text( buffer, font, text, &color, &pen ); pen.y += font->height - font->linegap; } } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glBindTexture( GL_TEXTURE_2D, atlas->id ); glUseProgram( shader ); { glUniform1i( glGetUniformLocation( shader, "texture" ), 0 ); glUniformMatrix4fv( glGetUniformLocation( shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( shader, "projection" ), 1, 0, projection.data); vertex_buffer_render( buffer, GL_TRIANGLES ); } glfwSwapBuffers( window ); }
// -------------------------------------------------------- console_render --- void console_render( console_t *self ) { int viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); size_t i, index; self->pen.x = 0; self->pen.y = viewport[3]; vertex_buffer_clear( console->buffer ); int cursor_x = self->pen.x; int cursor_y = self->pen.y; markup_t markup; // console_t buffer markup = self->markup[MARKUP_FAINT]; self->pen.y -= markup.font->height; for( i=0; i<self->lines->size; ++i ) { wchar_t *text = * (wchar_t **) vector_get( self->lines, i ) ; if( wcslen(text) > 0 ) { console_add_glyph( console, text[0], L'\0', &markup ); for( index=1; index < wcslen(text)-1; ++index ) { console_add_glyph( console, text[index], text[index-1], &markup ); } } self->pen.y -= markup.font->height - markup.font->linegap; self->pen.x = 0; cursor_x = self->pen.x; cursor_y = self->pen.y; } // Prompt markup = self->markup[MARKUP_BOLD]; if( wcslen( self->prompt ) > 0 ) { console_add_glyph( console, self->prompt[0], L'\0', &markup ); for( index=1; index < wcslen(self->prompt); ++index ) { console_add_glyph( console, self->prompt[index], self->prompt[index-1], &markup ); } } cursor_x = (int) self->pen.x; // Input markup = self->markup[MARKUP_NORMAL]; if( wcslen(self->input) > 0 ) { console_add_glyph( console, self->input[0], L'\0', &markup ); if( self->cursor > 0) { cursor_x = (int) self->pen.x; } for( index=1; index < wcslen(self->input); ++index ) { console_add_glyph( console, self->input[index], self->input[index-1], &markup ); if( index < self->cursor ) { cursor_x = (int) self->pen.x; } } } // Cursor (we use the black character (-1) as texture ) texture_glyph_t *glyph = texture_font_get_glyph( markup.font, -1 ); float r = markup.foreground_color.r; float g = markup.foreground_color.g; float b = markup.foreground_color.b; float a = markup.foreground_color.a; int x0 = cursor_x+1; int y0 = cursor_y + markup.font->descender; int x1 = cursor_x+2; int y1 = y0 + markup.font->height - markup.font->linegap; float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint indices[] = {0,1,2, 0,2,3}; vertex_t vertices[] = { { x0,y0,0, s0,t0, r,g,b,a }, { x0,y1,0, s0,t1, r,g,b,a }, { x1,y1,0, s1,t1, r,g,b,a }, { x1,y0,0, s1,t0, r,g,b,a } }; vertex_buffer_push_back( self->buffer, vertices, 4, indices, 6 ); glEnable( GL_TEXTURE_2D ); glUseProgram( shader ); { glUniform1i( glGetUniformLocation( shader, "texture" ), 0 ); glUniformMatrix4fv( glGetUniformLocation( shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( shader, "projection" ), 1, 0, projection.data); vertex_buffer_render( console->buffer, GL_TRIANGLES ); } }
size_t sen_render_flush(int clear_buff) { // gl_check_error(); //_logfi("1"); blend_group_t* bg; khint_t i,k,j; size_t total = 0; khash_t(hmsp)* tgs; camera_t* cam = sen_camera(); tex_group_t* tg; khash_t(hmsp)* sgs; shader_group_t* sg; vector_clear(zsorter); for (k = kh_begin(g_bgs); k != kh_end(g_bgs); ++k) { if (!kh_exist(g_bgs,k)) continue; bg = kh_val(g_bgs, k); if (bg->num == 0) { kh_del(hmip,g_bgs,k); continue; } tgs = bg->tgs; // set_blending( (blend_func) (kh_key(g_bgs, k)) ); for (i = kh_begin(tgs); i != kh_end(tgs); ++i) { if (!kh_exist(tgs,i)) continue; tg = kh_val(tgs, i); if (tg->num == 0) { kh_del(hmsp,tgs,i); continue; } /* if (tg->tex) sen_texture_bind(tg->tex); else if (tg->font) sen_font_bind(tg->font); */ sgs = tg->sgs; for (j = kh_begin(sgs); j != kh_end(sgs); ++j) { if (!kh_exist(sgs,j)) continue; sg = kh_val(sgs, j); if (sg->num == 0 || !sg->buff) { kh_del(hmsp,sgs,j); continue; } if (sg->buff) { /* sen_shader_use(sg->program); { if (tg->tex || tg->font) sen_uniform_1iN(sg->program, "u_tex0", 0); sen_uniform_m4fN(sg->program, "u_mvp", cam->view_proj.data); vertex_buffer_render( sg->buff, GL_TRIANGLES); total+=vertex_buffer_size(sg->buff); if (clear_buff) vertex_buffer_clear( sg->buff ); //sen_shader_use(NULL); }*/ vector_push_back( zsorter, &sg ); } sg->num = 0; } tg->num = 0; } bg->num = 0; } if (zsorter->size > 0) vector_sort(zsorter, zcmp); for (j = 0; j < zsorter->size; j++) { shader_group_t* sg = *(shader_group_t**)vector_get(zsorter, j); // _logfi("%s %d",sg->name, sg->z); set_blending( (blend_func) (sg->bg->key) ); if (sg->tg->tex) sen_texture_bind(sg->tg->tex); else if (sg->tg->font) sen_font_bind(sg->tg->font); sen_shader_use(sg->program); { if (sg->tg->tex || sg->tg->font) sen_uniform_1iN(sg->program, "u_tex0", 0); sen_uniform_m4fN(sg->program, "u_mvp", sg->z > 9500 ? cam->proj.data : cam->view_proj.data); vertex_buffer_render( sg->buff, GL_TRIANGLES); total+=vertex_buffer_size(sg->buff); if (clear_buff) vertex_buffer_clear( sg->buff ); //sen_shader_use(NULL); } } // _logfi("-------------------------------------------------"); return total; }
static void update_buffer(sprite_t* self) { int status = ((node_t*)self)->updated; const vec4* col = &(((node_t*)self)->color); float r = col->r; float g = col->g; float b = col->b; float a = col->a; vec4* bbox = & ( ((node_t*) self)->bbox ); vec2* size = & ( ((node_t*) self)->size ); const vec4* coords; float sw, sh; float x0,y0,x1,y1,s0,s1,t0,t1; V4F_T2F_C4F vertices[4]; int update_model; if (status & SEN_NODE_UPDATE_INVALIDATE_BUFFER) { vertex_buffer_invalidate(self->quad); status &= ~SEN_NODE_UPDATE_INVALIDATE_BUFFER; } if (status & SEN_NODE_UPDATE_BBOX) { vertex_buffer_clear(self->quad); sw = self->tex->img_width / 2.0f; sh = self->tex->img_height / 2.0f; x0 = -sw; x1 = sw; y0 = -sh; y1 = sh; coords = &(self->tex->coords); s0 = coords->s0; t0 = coords->t0; s1 = coords->s1; t1 = coords->t1; /* V4F_T2F_C4F vertices[4] = {{ -sw,-sh,0,1, coords->s0,coords->t1, col->r,col->g,col->b,col->a,}, { -sw, sh,0,1, coords->s0,coords->t0, col->r,col->g,col->b,col->a,}, { sw, sh,0,1, coords->s1,coords->t0, col->r,col->g,col->b,col->a,}, { sw,-sh,0,1, coords->s1,coords->t1, col->r,col->g,col->b,col->a,}};*/ vertices[0].x = (float)x0; vertices[0].y = (float)y0; vertices[0].z = 0.0f; vertices[0].w = 1.0f; vertices[0].s = s0; vertices[0].t = t1; vertices[0].r = r; vertices[0].g = g; vertices[0].b = b; vertices[0].a = a; vertices[1].x = (float)x0; vertices[1].y = (float)y1; vertices[1].z = 0.0f; vertices[1].w = 1.0f; vertices[1].s = s0; vertices[1].t = t0; vertices[1].r = r; vertices[1].g = g; vertices[1].b = b; vertices[1].a = a; vertices[2].x = (float)x1; vertices[2].y = (float)y1; vertices[2].z = 0.0f; vertices[2].w = 1.0f; vertices[2].s = s1; vertices[2].t = t0; vertices[2].r = r; vertices[2].g = g; vertices[2].b = b; vertices[2].a = a; vertices[3].x = (float)x1; vertices[3].y = (float)y0; vertices[3].z = 0.0f; vertices[3].w = 1.0f; vertices[3].s = s1; vertices[3].t = t1; vertices[3].r = r; vertices[3].g = g; vertices[3].b = b; vertices[3].a = a; bbox->x = -sw; bbox->y = -sh; bbox->z = sw; bbox->w = sh; size->x = (float) (self->tex->img_width); size->y = (float) (self->tex->img_height); vertex_buffer_push_back( self->quad, vertices, 4, indices, 6 ); // vertex_buffer_push_back_vertices( self->quad, vertices, 4); memcpy(self->vertices, vertices, sizeof(vertices)); status &= ~SEN_NODE_UPDATE_BBOX; status |= SEN_NODE_UPDATE_MODEL; } update_model = status & SEN_NODE_UPDATE_MODEL; if ( status & (SEN_NODE_UPDATE_MODEL | SEN_NODE_UPDATE_COLOR)) { //V4F_T2F_C4F vertices[4]; // memcpy(vertices, self->vertices, 4*sizeof(V4F_T2F_C4F)); const mat4* model = sen_node_model(self); int i; for (i=0; i<4; ++i) { if (update_model) { // vec4* v = (vec4*) ( i*sizeof(V4F_T2F_C4F )+(self->quad->vertices->items)); //vec4* v = (vec4*) ( i*sizeof(V4F_T2F_C4F )+(vertices)); //vec4* v = (vec4*) (& vertices[i]);// ( i*sizeof(V4F_T2F_C4F )+(vertices)); vec4* vp = (vec4*) (& (self->vertices[i]) ); vec4* v = (vec4*) ( (char*)(self->quad->vertices->items) + i*sizeof(V4F_T2F_C4F ) ); //v4_transform(model->data, v->data,v->data); v4_transform(model->data, vp->data,v->data); if ( i ) { if (v->x < bbox->x) bbox->x = v->x; else if (v->x > bbox->z) bbox->z = v->x; if (v->y < bbox->y) bbox->y = v->y; else if (v->y > bbox->w) bbox->w = v->y; } else { bbox->x = bbox->z = v->x; bbox->y = bbox->w = v->y; } } if (status & SEN_NODE_UPDATE_COLOR) { vec4* c = (vec4*) ( (char*)(self->quad->vertices->items)+ i*sizeof(V4F_T2F_C4F )+ sizeof(float)*6); // vec4* c = (vec4*) ( i*sizeof(V4F_T2F_C4F )+sizeof(float)*6+(vertices)); //vec4* c = (vec4*) (& (vertices[i].r) );// i*sizeof(V4F_T2F_C4F )+sizeof(float)*6+(vertices)); // vec4* c = (vec4*) (& (self->vertices[i].r) );// i*sizeof(V4F_T2F_C4F )+sizeof(float)*6+(vertices)); memcpy(c,col,sizeof(vec4)); } } //self->quad->state = 1; status &= ~(SEN_NODE_UPDATE_COLOR|SEN_NODE_UPDATE_MODEL|SEN_NODE_UPDATE_PARENT_MODEL); } ((node_t*)self)->updated = status; }
// -------------------------------------------------------- console_render --- void console_render( console_t *self ) { char* cur_char; char* prev_char; int viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); size_t i, index; self->pen.x = 0; self->pen.y = viewport[3]; vertex_buffer_clear( console->buffer ); int cursor_x = self->pen.x; int cursor_y = self->pen.y; markup_t markup; // console_t buffer markup = self->markup[MARKUP_FAINT]; self->pen.y -= markup.font->height; for( i=0; i<self->lines->size; ++i ) { char *text = * (char **) vector_get( self->lines, i ) ; if( strlen(text) > 0 ) { cur_char = text; prev_char = NULL; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; for( index=1; index < strlen(text)-1; ++index ) { cur_char = text + index; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; } } self->pen.y -= markup.font->height - markup.font->linegap; self->pen.x = 0; cursor_x = self->pen.x; cursor_y = self->pen.y; } // Prompt markup = self->markup[MARKUP_BOLD]; if( strlen( self->prompt ) > 0 ) { cur_char = self->prompt; prev_char = NULL; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; for( index=1; index < strlen(self->prompt); ++index ) { cur_char = self->prompt + index; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; } } cursor_x = (int) self->pen.x; // Input markup = self->markup[MARKUP_NORMAL]; if( strlen(self->input) > 0 ) { cur_char = self->input; prev_char = NULL; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; if( self->cursor > 0) { cursor_x = (int) self->pen.x; } for( index=1; index < strlen(self->input); ++index ) { cur_char = self->input + index; console_add_glyph( console, cur_char, prev_char, &markup ); prev_char = cur_char; if( index < self->cursor ) { cursor_x = (int) self->pen.x; } } } if( self->lines->size || self->prompt[0] != '\0' || self->input[0] != '\0' ) { glBindTexture( GL_TEXTURE_2D, self->atlas->id ); 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_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RED, self->atlas->width, self->atlas->height, 0, GL_RED, GL_UNSIGNED_BYTE, self->atlas->data ); } // Cursor (we use the black character (NULL) as texture ) texture_glyph_t *glyph = texture_font_get_glyph( markup.font, NULL ); float r = markup.foreground_color.r; float g = markup.foreground_color.g; float b = markup.foreground_color.b; float a = markup.foreground_color.a; int x0 = cursor_x+1; int y0 = cursor_y + markup.font->descender; int x1 = cursor_x+2; int y1 = y0 + markup.font->height - markup.font->linegap; float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint indices[] = {0,1,2, 0,2,3}; vertex_t vertices[] = { { x0,y0,0, s0,t0, r,g,b,a }, { x0,y1,0, s0,t1, r,g,b,a }, { x1,y1,0, s1,t1, r,g,b,a }, { x1,y0,0, s1,t0, r,g,b,a } }; vertex_buffer_push_back( self->buffer, vertices, 4, indices, 6 ); glEnable( GL_TEXTURE_2D ); glUseProgram( shader ); { glUniform1i( glGetUniformLocation( shader, "texture" ), 0 ); glUniformMatrix4fv( glGetUniformLocation( shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( shader, "projection" ), 1, 0, projection.data); vertex_buffer_render( console->buffer, GL_TRIANGLES ); } }
// ---------------------------------------------------------------------------- void text_buffer_clear( text_buffer_t * self ) { vertex_buffer_clear (self->buffer); }