// ----------------------------------------------------------- build_buffer --- void build_buffer( void ) { vec2 pen; texture_font_t *font; vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; vec4 color = white; if( p_invert ) { color = black; } markup_t markup = { .family = "Source Sans Pro", .size = 10.0, .bold = 0, .italic = 0, .spacing = p_interval, .gamma = p_gamma, .foreground_color = color, .background_color = none, .underline = 0, .underline_color = color, .overline = 0, .overline_color = color, .strikethrough = 0, .strikethrough_color = color, .font = 0, }; text_buffer_clear( text_buffer ); texture_atlas_t * atlas = font_manager->atlas; texture_atlas_clear( atlas ); if( p_family == VERA) { font = texture_font_new_from_file( atlas, p_size, "fonts/Vera.ttf" ); } else if( p_family == VERA_MONO) { font = texture_font_new_from_file( atlas, p_size, "fonts/VeraMono.ttf" ); } else if( p_family == LUCKIEST_GUY) { font = texture_font_new_from_file( atlas, p_size, "fonts/LuckiestGuy.ttf" ); } else if( p_family == SOURCE_SANS ) { font = texture_font_new_from_file( atlas, p_size, "fonts/SourceSansPro-Regular.ttf" ); } else if( p_family == SOURCE_CODE ) { font = texture_font_new_from_file( atlas, p_size, "fonts/SourceCodePro-Regular.ttf" ); } else if( p_family == OLD_STANDARD ) { font = texture_font_new_from_file( atlas, p_size, "fonts/OldStandard-Regular.ttf" ); } else if( p_family == LOBSTER ) { font = texture_font_new_from_file( atlas, p_size, "fonts/Lobster-Regular.ttf" ); } else { fprintf( stderr, "Error : Unknown family type\n" ); return; } if (!font) return; markup.font = font; font->hinting = p_hinting; font->kerning = p_kerning; font->filtering = 1; float norm = 1.0/(p_primary + 2*p_secondary + 2*p_tertiary); font->lcd_weights[0] = (unsigned char)(p_tertiary*norm*255); font->lcd_weights[1] = (unsigned char)(p_secondary*norm*255); font->lcd_weights[2] = (unsigned char)(p_primary*norm*255); font->lcd_weights[3] = (unsigned char)(p_secondary*norm*255); font->lcd_weights[4] = (unsigned char)(p_tertiary*norm*255); pen.x = 10; pen.y = 600 - font->height - 10; text_buffer_printf( text_buffer, &pen, &markup, text, NULL ); // Post-processing for width and orientation vertex_buffer_t * vbuffer = text_buffer->buffer; size_t i; for( i=0; i < vector_size( vbuffer->items ); ++i ) { ivec4 *item = (ivec4 *) vector_get( vbuffer->items, i); glyph_vertex_t * v0 = /* x0,y0 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+0 ); //glyph_vertex_t * v1 = /* x0,y1 */ // (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+1 ); glyph_vertex_t * v2 = /* x1,y1 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+2 ); glyph_vertex_t * v3 = /* x1,y0 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+3 ); float x0 = v0->x, y0 = v0->y; float x1 = v2->x, y1 = v2->y; v2->x = v3->x = x0 + (x1-x0)*p_width; float dy = fabs(y1-y0); float dx = tan(p_faux_italic/180.0 * M_PI) * dy; v0->x += dx; v0->shift = fmod(v0->shift + dx-(int)(dx),1.0); v3->x += dx; v3->shift = fmod(v3->shift + dx-(int)(dx),1.0); } glBindTexture( GL_TEXTURE_2D, font_manager->atlas->id ); GLenum gl_format = (font_manager->atlas->depth == LCD_FILTERING_OFF) ? GL_RED : GL_RGB; glTexImage2D( GL_TEXTURE_2D, 0, gl_format, font_manager->atlas->width, font_manager->atlas->height, 0, gl_format, GL_UNSIGNED_BYTE, font_manager->atlas->data ); texture_font_delete( font ); } // ------------------------------------------------------------------- quit --- void reset( void ) { p_family = VERA; p_size = 12.0; p_invert = 0; p_kerning = 1; p_hinting = 1; p_lcd_filtering = 1; p_gamma = 1.75; p_interval = 0.0; p_weight = 0.33; p_width = 1.0; p_faux_weight = 0.0; p_faux_italic = 0.0; // FT_LCD_FILTER_LIGHT p_primary = 1.0/3.0; p_secondary = 1.0/3.0; p_tertiary = 0.0/3.0; // FT_LCD_FILTER_DEFAULT // p_primary = 3.0/9.0; // p_secondary = 2.0/9.0; // p_tertiary = 1.0/9.0; build_buffer(); }
// ----------------------------------------------------------- build_buffer --- void build_buffer( void ) { vec2 pen; texture_font_t *font; vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; vec4 color = white; if( p_invert ) { color = black; } markup_t markup = { .family = "Source Sans Pro", .size = 10.0, .bold = 0, .italic = 0, .rise = 0.0, .spacing = p_interval, .gamma = p_gamma, .foreground_color = color, .background_color = none, .underline = 0, .underline_color = color, .overline = 0, .overline_color = color, .strikethrough = 0, .strikethrough_color = color, .font = 0, }; text_buffer_clear( buffer ); texture_atlas_t * atlas = buffer->manager->atlas; texture_atlas_clear( atlas ); if( p_family == VERA) { font = texture_font_new_from_file( atlas, p_size, "fonts/Vera.ttf" ); } else if( p_family == VERA_MONO) { font = texture_font_new_from_file( atlas, p_size, "fonts/VeraMono.ttf" ); } else if( p_family == LUCKIEST_GUY) { font = texture_font_new_from_file( atlas, p_size, "fonts/LuckiestGuy.ttf" ); } else if( p_family == SOURCE_SANS ) { font = texture_font_new_from_file( atlas, p_size, "fonts/SourceSansPro-Regular.ttf" ); } else if( p_family == SOURCE_CODE ) { font = texture_font_new_from_file( atlas, p_size, "fonts/SourceCodePro-Regular.ttf" ); } else if( p_family == OLD_STANDARD ) { font = texture_font_new_from_file( atlas, p_size, "fonts/OldStandard-Regular.ttf" ); } else if( p_family == LOBSTER ) { font = texture_font_new_from_file( atlas, p_size, "fonts/Lobster-Regular.ttf" ); } else { fprintf( stderr, "Error : Unknown family type\n" ); return; } if (!font) return; markup.font = font; font->hinting = p_hinting; font->kerning = p_kerning; 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); pen.x = 10; pen.y = 600 - font->height - 10; text_buffer_printf( buffer, &pen, &markup, text, NULL ); // Post-processing for width and orientation vertex_buffer_t * vbuffer = buffer->buffer; size_t i; for( i=0; i < vector_size( vbuffer->items ); ++i ) { ivec4 *item = (ivec4 *) vector_get( vbuffer->items, i); glyph_vertex_t * v0 = /* x0,y0 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+0 ); //glyph_vertex_t * v1 = /* x0,y1 */ // (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+1 ); glyph_vertex_t * v2 = /* x1,y1 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+2 ); glyph_vertex_t * v3 = /* x1,y0 */ (glyph_vertex_t *) vector_get( vbuffer->vertices, item->vstart+3 ); float x0 = v0->x, y0 = v0->y; float x1 = v2->x, y1 = v2->y; v2->x = v3->x = x0 + (x1-x0)*p_width; float dy = abs(y1-y0); float dx = tan(p_faux_italic/180.0 * M_PI) * dy; v0->x += dx; v0->shift = fmod(v0->shift + dx-(int)(dx),1.0); v3->x += dx; v3->shift = fmod(v3->shift + dx-(int)(dx),1.0); } texture_font_delete( font ); } // ---------------------------------------------------------------- display --- void display( GLFWwindow* window ) { vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; if( !p_invert ) { glClearColor( 0, 0, 0, 1 ); buffer->base_color = white; } else { glClearColor( 1, 1, 1, 1 ); buffer->base_color = black; } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glUseProgram( buffer->shader ); { glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "projection" ), 1, 0, projection.data); text_buffer_render( buffer ); } TwDraw( ); glfwSwapBuffers( window ); }
void init() { buffer = text_buffer_new( LCD_FILTERING_ON ); vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 yellow = {{1.0, 1.0, 0.0, 1.0}}; vec4 grey = {{0.5, 0.5, 0.5, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; char *f_normal = match_description("Droid Serif", 24, 0, 0); char *f_bold = match_description("Droid Serif", 24, 1, 0); char *f_italic = match_description("Droid Serif", 24, 0, 1); char *f_japanese = match_description("Droid Sans Japanese", 18, 0, 0); char *f_math = match_description("DejaVu Sans", 24, 0, 0); markup_t normal = { .family = f_normal, .size = 24.0, .bold = 0, .italic = 0, .rise = 0.0, .spacing = 0.0, .gamma = 2., .foreground_color = white, .background_color = none, .underline = 0, .underline_color = white, .overline = 0, .overline_color = white, .strikethrough = 0, .strikethrough_color = white, .font = 0, }; markup_t highlight = normal; highlight.background_color = grey; markup_t reverse = normal; reverse.foreground_color = black; reverse.background_color = white; reverse.gamma = 1.0; markup_t overline = normal; overline.overline = 1; markup_t underline = normal; underline.underline = 1; markup_t small = normal; small.size = 10.0; markup_t big = normal; big.size = 48.0; big.italic = 1; big.foreground_color = yellow; markup_t bold = normal; bold.bold = 1; bold.family = f_bold; markup_t italic = normal; italic.italic = 1; italic.family = f_italic; markup_t japanese = normal; japanese.family = f_japanese; japanese.size = 18.0; markup_t math = normal; math.family = f_math; vec2 pen = {{20, 200}}; text_buffer_printf( buffer, &pen, &underline, "The", &normal, " Quick", &big, " brown ", &reverse, " fox \n", &italic, "jumps over ", &bold, "the lazy ", &normal, "dog.\n", &small, "Now is the time for all good men " "to come to the aid of the party.\n", &italic, "Ég get etið gler án þess að meiða mig.\n", &japanese, "私はガラスを食べられます。 それは私を傷つけません\n", &math, "ℕ ⊆ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ", NULL ); mat4_set_identity( &projection ); mat4_set_identity( &model ); mat4_set_identity( &view ); } // ---------------------------------------------------------------- display --- void display( GLFWwindow* window ) { glClearColor(0.40,0.40,0.45,1.00); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glColor4f(1.00,1.00,1.00,1.00); glUseProgram( buffer->shader ); { glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( buffer->shader, "projection" ), 1, 0, projection.data); text_buffer_render( buffer ); } glfwSwapBuffers( window ); }
// ------------------------------------------------------------------- main --- int main_markup( int argc, char **argv ) { glutInit( &argc, argv ); glutInitWindowSize( 500, 220 ); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); glutCreateWindow( argv[0] ); glutReshapeFunc( reshape ); glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); GLenum err = glewInit(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ fprintf( stderr, "Error: %s\n", glewGetErrorString(err) ); exit( EXIT_FAILURE ); } fprintf( stderr, "Using GLEW %s\n", glewGetString(GLEW_VERSION) ); buffer = text_buffer_new( LCD_FILTERING_ON ); vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 yellow = {{1.0, 1.0, 0.0, 1.0}}; vec4 grey = {{0.5, 0.5, 0.5, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; char *f_normal = match_description("Droid Serif", 24, 0, 0); char *f_bold = match_description("Droid Serif", 24, 1, 0); char *f_italic = match_description("Droid Serif", 24, 0, 1); char *f_japanese = match_description("Droid Sans Japanese", 18, 0, 0); char *f_math = match_description("DejaVu Sans", 24, 0, 0); markup_t normal = { .family = f_normal, .size = 24.0, .bold = 0, .italic = 0, .rise = 0.0, .spacing = 0.0, .gamma = 2., .foreground_color = white, .background_color = none, .underline = 0, .underline_color = white, .overline = 0, .overline_color = white, .strikethrough = 0, .strikethrough_color = white, .font = 0, }; markup_t highlight = normal; highlight.background_color = grey; markup_t reverse = normal; reverse.foreground_color = black; reverse.background_color = white; reverse.gamma = 1.0; markup_t overline = normal; overline.overline = 1; markup_t underline = normal; underline.underline = 1; markup_t small = normal; small.size = 10.0; markup_t big = normal; big.size = 48.0; big.italic = 1; big.foreground_color = yellow; markup_t bold = normal; bold.bold = 1; bold.family = f_bold; markup_t italic = normal; italic.italic = 1; italic.family = f_italic; markup_t japanese = normal; japanese.family = f_japanese; japanese.size = 18.0; markup_t math = normal; math.family = f_math; vec2 pen = {{20, 200}}; text_buffer_printf( buffer, &pen, &underline, L"The", &normal, L" Quick", &big, L" brown ", &reverse, L" fox \n", &italic, L"jumps over ", &bold, L"the lazy ", &normal, L"dog.\n", &small, L"Now is the time for all good men " L"to come to the aid of the party.\n", &italic, L"Ég get etið gler án þess að meiða mig.\n", &japanese, L"私はガラスを食べられます。 それは私を傷つけません\n", &math, L"ℕ ⊆ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ", NULL ); mat4_set_identity( &projection ); mat4_set_identity( &model ); mat4_set_identity( &view ); glutMainLoop( ); return 0; }
void init() { text_shader = shader_load( "text.vert", "text.frag" ); font_manager = font_manager_new( 512, 512, LCD_FILTERING_ON ); buffer = text_buffer_new( ); vec4 black = {{0.0, 0.0, 0.0, 1.0}}; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 yellow = {{1.0, 1.0, 0.0, 1.0}}; vec4 grey = {{0.5, 0.5, 0.5, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; //char *f_normal = match_description("Vera:size=50"); char *f_normal = match_description("Arial"); char *f_bold = match_description("Arial", true); //char *f_bold = match_description("sans\\-serif:size=24"); char *f_italic = match_description("sans\\-serif", false, true); //char *f_italic = match_description("SimSun", false, true); //char *f_japanese = match_description("Droid Sans:size=18:lang=ja"); //char *f_japanese = match_description("sans-serif:size=18:lang=zh"); //char *f_japanese = match_description("sans\\-serif:size=18:lang=zh\\-CN"); //char *f_japanese = match_description("FZLanTingHeiS\\-UL\\-GB:size=18:lang=zh\\-CN"); //ok //char *f_japanese = match_description("FZLanTingHeiS\\-UL\\-GB"); //ok //char *f_japanese = match_description("Yu Gothic UI Semibold"); //ok //char *f_japanese = match_description("jj:size=18"); //ok //char *f_japanese = match_description("Brush Script MT"); //ok char *f_japanese = match_description("Microsoft JhengHei UI"); //ok //char *f_japanese = match_description("华文隶书:size=28:lang=zh\\-CN"); //no char *f_math = match_description("DejaVu Sans"); printf("init. f_normal: %s f_bold: %s f_italic: %s f_japanese: %s f_math: %s\n" , f_normal, f_bold, f_italic, f_japanese, f_math); //printf("init. f_japanese: %s\n" , f_japanese); //exit(0); markup_t normal = { .family = f_normal, .size = 20.0, .bold = 0, .italic = 0, .spacing = 0.0, .gamma = 2., .foreground_color = white, .background_color = none, .outline = 0, .outline_color = white, .underline = 0, .underline_color = white, .overline = 0, .overline_color = white, .strikethrough = 0, .strikethrough_color = white, .font = 0, }; markup_t highlight = normal; highlight.background_color = grey; markup_t reverse = normal; reverse.foreground_color = black; reverse.background_color = white; reverse.gamma = 1.0; markup_t overline = normal; overline.overline = 1; markup_t underline = normal; underline.underline = 1; markup_t small = normal; small.size = 10.0; markup_t big = normal; big.size = 48.0; big.italic = 1; big.foreground_color = yellow; markup_t bold = normal; bold.bold = 1; bold.family = f_bold; markup_t italic = normal; italic.italic = 1; italic.family = f_italic; markup_t japanese = normal; japanese.family = f_japanese; //markup_t japanese = normal; japanese.family = "C:/Windows/Fonts/simsun.ttc"; //markup_t japanese = normal; japanese.family = "c:/qtproject/opengl/freetype-gl/fonts/fireflysung.ttf"; japanese.size = 25.0; markup_t math = normal; math.family = f_math; #if 1 normal.font = font_manager_get_from_markup( font_manager, &normal ); highlight.font = font_manager_get_from_markup( font_manager, &highlight ); reverse.font = font_manager_get_from_markup( font_manager, &reverse ); overline.font = font_manager_get_from_markup( font_manager, &overline ); underline.font = font_manager_get_from_markup( font_manager, &underline ); small.font = font_manager_get_from_markup( font_manager, &small ); big.font = font_manager_get_from_markup( font_manager, &big ); bold.font = font_manager_get_from_markup( font_manager, &bold ); italic.font = font_manager_get_from_markup( font_manager, &italic ); japanese.font = font_manager_get_from_markup( font_manager, &japanese ); math.font = font_manager_get_from_markup( font_manager, &math ); #else japanese.font = font_manager_get_from_markup( font_manager, &japanese ); #endif vec2 pen = {{20, 200}}; #if 1 text_buffer_printf( buffer, &pen, &underline, "The", &normal, " Quick", &big, " brown ", &reverse, " fox \n", &italic, "jumps over ", &bold, "the lazy ", &normal, "dog.\n", &small, "Now is the time for all good men " "to come to the aid of the party.\n", &italic, "Ég get etið gler án þess að meiða mig.\n", &japanese, "aaa张私はガラスを食べられます。 それは私を傷つけません\n", &math, "ℕ ⊆ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ", NULL ); #else text_buffer_printf( buffer, &pen, &japanese, "Brush Script MT张私はガラスを食べられます。 それは私を傷つけません\n", NULL ); #endif glGenTextures( 1, &font_manager->atlas->id ); glBindTexture( GL_TEXTURE_2D, font_manager->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_RGB, font_manager->atlas->width, font_manager->atlas->height, 0, GL_RGB, GL_UNSIGNED_BYTE, font_manager->atlas->data ); printf("init font_manager->atlas->width: %d font_manager->atlas->height: %d\n" , font_manager->atlas->width, font_manager->atlas->height); text_buffer_align( buffer, &pen, ALIGN_CENTER ); vec4 bounds = text_buffer_get_bounds( buffer, &pen ); float left = bounds.left; float right = bounds.left + bounds.width; float top = bounds.top; float bottom = bounds.top - bounds.height; bounds_shader = shader_load( "v3f-c4f.vert", "v3f-c4f.frag" ); lines_buffer = vertex_buffer_new( "vertex:3f,color:4f" ); vertex_t vertices[] = { { left - 10, top, 0, 0,0,0,1}, // top {right + 10, top, 0, 0,0,0,1}, { left - 10, bottom, 0, 0,0,0,1}, // bottom {right + 10, bottom, 0, 0,0,0,1}, { left, top + 10, 0, 0,0,0,1}, // left { left, bottom - 10, 0, 0,0,0,1}, { right, top + 10, 0, 0,0,0,1}, // right { right, bottom - 10, 0, 0,0,0,1} }; GLuint indices[] = { 0,1,2,3,4,5,6,7 }; vertex_buffer_push_back( lines_buffer, vertices, 8, indices, 8); mat4_set_identity( &projection ); mat4_set_identity( &model ); mat4_set_identity( &view ); } // ---------------------------------------------------------------- display --- void display( GLFWwindow* window ) { glClearColor(0.40,0.40,0.45,1.00); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glColor4f(1.00,1.00,1.00,1.00); glUseProgram( text_shader ); { glUniformMatrix4fv( glGetUniformLocation( text_shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( text_shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( text_shader, "projection" ), 1, 0, projection.data); glUniform1i( glGetUniformLocation( text_shader, "tex" ), 0 ); glUniform3f( glGetUniformLocation( text_shader, "pixel" ), 1.0f/font_manager->atlas->width, 1.0f/font_manager->atlas->height, (float)font_manager->atlas->depth ); glEnable( GL_BLEND ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, font_manager->atlas->id ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendColor( 1, 1, 1, 1 ); vertex_buffer_render( buffer->buffer, GL_TRIANGLES ); glBindTexture( GL_TEXTURE_2D, 0 ); glBlendColor( 0, 0, 0, 0 ); glUseProgram( 0 ); } glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); glBlendColor( 1.0, 1.0, 1.0, 1.0 ); glUseProgram( bounds_shader ); { glUniformMatrix4fv( glGetUniformLocation( bounds_shader, "model" ), 1, 0, model.data); glUniformMatrix4fv( glGetUniformLocation( bounds_shader, "view" ), 1, 0, view.data); glUniformMatrix4fv( glGetUniformLocation( bounds_shader, "projection" ), 1, 0, projection.data); vertex_buffer_render( lines_buffer, GL_LINES ); } glfwSwapBuffers( window ); }