commit e477202e98ed097509a65a7bcbc4127cb8a7b8b8 parent 8eb5ec9610d15114639fb1d98008fd98c54f594c Author: Michael Savage <mikejsavage@gmail.com> Date: Mon Aug 24 22:16:04 +0200 Better but still bad font rendering Diffstat:
assets.h | | | 42 | ++++++++++++++++++++++++++++++++++++++++++ |
game.h | | | 11 | +++++++++++ |
hm.cc | | | 143 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
diff --git a/assets.h b/assets.h @@ -0,0 +1,42 @@ +#ifndef _ASSETS_H_ +#define _ASSETS_H_ + +#include "platform_opengl.h" + +enum AssetType { + AT_BITMAP, + AT_SOUND, +}; + +enum AssetHandle { + // bitmaps + ASSET_FONT, + + // sounds + + ASSET_COUNT, +}; + +struct Bitmap { + u32 width; + u32 height; + u8 * data; +}; + +struct Sound { + u32 num_samples; + u8 * data; +}; + +struct Asset { + AssetType type; + union { + struct { + Bitmap bitmap; + GLuint texture; + }; + Sound sound; + }; +}; + +#endif // _ASSETS_H_ diff --git a/game.h b/game.h @@ -4,12 +4,14 @@ #include <glm/glm.hpp> #include "intrinsics.h" +#include "assets.h" #include "terrain_manager.h" #include "bsp.h" #include "bsp_renderer.h" #include "immediate.h" #include "work_queue.h" #include "keys.h" +#include "stb_truetype.h" struct GameState { glm::vec3 pos; @@ -26,7 +28,16 @@ struct GameState { GLint test_at_colour; GLint test_un_VP; + GLuint test_tex_shader; + GLint test_tex_at_pos; + GLint test_tex_at_colour; + GLint test_tex_at_uv; + GLint test_tex_un_tex; + ImmediateContext test_immediate; + + Asset assets[ ASSET_COUNT ]; + stbtt_bakedchar test_chars[ 256 ]; }; struct GameMemory { diff --git a/hm.cc b/hm.cc @@ -136,19 +136,86 @@ extern "C" GAME_INIT( game_init ) { red ); immediate_triangle( &state->test_immediate, - glm::vec3( -crosshair_thickness / aspect, crosshair_length * aspect , 0 ), - glm::vec3( crosshair_thickness / aspect, crosshair_length * aspect , 0 ), - glm::vec3( crosshair_thickness / aspect, -crosshair_length * aspect , 0 ), + glm::vec3( -crosshair_thickness / aspect, crosshair_length * aspect, 0 ), + glm::vec3( crosshair_thickness / aspect, crosshair_length * aspect, 0 ), + glm::vec3( crosshair_thickness / aspect, -crosshair_length * aspect, 0 ), red ); immediate_triangle( &state->test_immediate, - glm::vec3( crosshair_thickness / aspect, -crosshair_length * aspect , 0 ), - glm::vec3( -crosshair_thickness / aspect, -crosshair_length * aspect , 0 ), - glm::vec3( -crosshair_thickness / aspect, crosshair_length * aspect , 0 ), + glm::vec3( crosshair_thickness / aspect, -crosshair_length * aspect, 0 ), + glm::vec3( -crosshair_thickness / aspect, -crosshair_length * aspect, 0 ), + glm::vec3( -crosshair_thickness / aspect, crosshair_length * aspect, 0 ), red ); glClearColor( 0, 0.5, 0.7, 1 ); + + // TODO + u8 * const arial = file_get_contents( "Arial.ttf" ); + + u8 * const font_memory = reserve_persistent( mem, 512 * 256 ); + const int offset = stbtt_GetFontOffsetForIndex( arial, 0 ); + const int ok = stbtt_BakeFontBitmap( arial, offset, 48, font_memory, 512, 512, ' ', 127 - ' ', state->test_chars ); + assert( ok > 0 ); + + free( arial ); + + Bitmap font_bitmap = { }; + font_bitmap.width = 512; + font_bitmap.height = 256; + font_bitmap.data = font_memory; + + Asset font_asset = { }; + font_asset.type = AT_BITMAP; + font_asset.bitmap = font_bitmap; + + glGenTextures( 1, &font_asset.texture ); + glBindTexture( GL_TEXTURE_2D, font_asset.texture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, font_bitmap.width, font_bitmap.height, 0, GL_RED, GL_UNSIGNED_BYTE, font_memory ); + + state->assets[ ASSET_FONT ] = font_asset; + + state->test_tex_shader = compile_shader( textured_vert_src, textured_frag_src, "screen_colour" ); + state->test_tex_at_pos = glGetAttribLocation( state->test_tex_shader, "position" ); + state->test_tex_at_colour = glGetAttribLocation( state->test_tex_shader, "colour" ); + state->test_tex_at_uv = glGetAttribLocation( state->test_tex_shader, "uv" ); + state->test_tex_un_tex = glGetUniformLocation( state->test_tex_shader, "tex" ); +} + +static void draw_string( const GameState * state, + float x, float y, + const char * str, + const GLint at_pos, const GLint at_colour, const GLint at_uv, const GLint un_tex +) { + const float scale = 1.0f / 32.0f / 5.0f; + const glm::vec4 white( 1, 1, 1, 1 ); + + ImmediateContext imm; + ImmediateTriangle triangles[ 256 ]; + immediate_init( &imm, triangles, array_count( triangles ) ); + + glBindTexture( GL_TEXTURE_2D, state->assets[ ASSET_FONT ].texture ); + + while( *str != '\0' ) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad( ( stbtt_bakedchar * ) state->test_chars, 512, 256, *str - ' ', &x, &y, &q, true ); + + const ImmediateVertex v1A = { glm::vec3( q.x0 * scale, -q.y0 * scale, 0 ), white, glm::vec2( q.s0, q.t0 ) }; + const ImmediateVertex v2A = { glm::vec3( q.x1 * scale, -q.y0 * scale, 0 ), white, glm::vec2( q.s1, q.t0 ) }; + const ImmediateVertex v3A = { glm::vec3( q.x0 * scale, -q.y1 * scale, 0 ), white, glm::vec2( q.s0, q.t1 ) }; + const ImmediateVertex v4A = { glm::vec3( q.x1 * scale, -q.y1 * scale, 0 ), white, glm::vec2( q.s1, q.t1 ) }; + + immediate_triangle( &imm, v1A, v2A, v3A ); + immediate_triangle( &imm, v3A, v2A, v4A ); + + str++; + } + + immediate_render( &imm, at_pos, at_colour, true, at_uv, un_tex ); + + glBindTexture( GL_TEXTURE_2D, 0 ); } extern "C" GAME_FRAME( game_frame ) { @@ -197,18 +264,12 @@ extern "C" GAME_FRAME( game_frame ) { glDisable( GL_DEPTH_TEST ); glEnable( GL_BLEND ); + glUseProgram( state->test_tex_shader ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); ImmediateContext imm; ImmediateTriangle asdf[ 32 ]; immediate_init( &imm, asdf, 32 ); - const GLuint texshader = compile_shader( textured_vert_src, textured_frag_src, "screen_colour" ); - glUseProgram( texshader ); - const GLint at_pos = glGetAttribLocation( texshader, "position" ); - const GLint at_colour = glGetAttribLocation( texshader, "colour" ); - const GLint at_uv = glGetAttribLocation( texshader, "uv" ); - const GLint un_tex = glGetUniformLocation( texshader, "tex" ); - GLuint tex; glGenTextures( 1, &tex ); glBindTexture( GL_TEXTURE_2D, tex ); @@ -232,57 +293,21 @@ extern "C" GAME_FRAME( game_frame ) { const glm::vec4 white( 1, 1, 1, 1 ); const int num_checks = 20; - const ImmediateVertex v1 = { glm::vec3( -1.0, 1.0, 0 ), white, glm::vec2( 0, 0 ) }; - const ImmediateVertex v2 = { glm::vec3( -0.5, 1.0, 0 ), white, glm::vec2( num_checks, 0 ) }; - const ImmediateVertex v3 = { glm::vec3( -1.0, 0.5, 0 ), white, glm::vec2( 0, num_checks / aspect ) }; - const ImmediateVertex v4 = { glm::vec3( -0.5, 0.5, 0 ), white, glm::vec2( num_checks, num_checks / aspect ) }; + const ImmediateVertex v1 = { glm::vec3( 0.5, 1.0, 0 ), white, glm::vec2( 0, 0 ) }; + const ImmediateVertex v2 = { glm::vec3( 1.0, 1.0, 0 ), white, glm::vec2( num_checks, 0 ) }; + const ImmediateVertex v3 = { glm::vec3( 0.5, 0.5, 0 ), white, glm::vec2( 0, num_checks / aspect ) }; + const ImmediateVertex v4 = { glm::vec3( 1.0, 0.5, 0 ), white, glm::vec2( num_checks, num_checks / aspect ) }; immediate_triangle( &imm, v1, v2, v3 ); immediate_triangle( &imm, v3, v2, v4 ); - immediate_render( &imm, at_pos, at_colour, true, at_uv, un_tex ); - - s32 width, height; - u8 * const arial = file_get_contents( "Arial.ttf" ); - stbtt_fontinfo font; - int ok = stbtt_InitFont( &font, arial, stbtt_GetFontOffsetForIndex( arial, 0 ) ); - assert( ok == 1 ); - - u8 * const A = stbtt_GetCodepointBitmap( &font, - 0, stbtt_ScaleForPixelHeight( &font, 256 ), - 'A', &width, &height, 0, 0 ); - - // we able to use a single channel (GL_RED) but I couldn't get it to work - u8 * const A4 = ( u8 * const ) malloc( width * height * 4 ); - for( s32 i = 0; i < width * height; i++ ) { - A4[ i * 4 + 0 ] = A[ i ]; - A4[ i * 4 + 1 ] = A[ i ]; - A4[ i * 4 + 2 ] = A[ i ]; - A4[ i * 4 + 3 ] = A[ i ]; - } - - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, A4 ); - - stbtt_FreeBitmap( A, nullptr ); - free( A4 ); - free( arial ); - - immediate_clear( &imm ); - - const ImmediateVertex v1A = { glm::vec3( -1.0, 1.0, 0 ), white, glm::vec2( 0, 0 ) }; - const ImmediateVertex v2A = { glm::vec3( -0.5, 1.0, 0 ), white, glm::vec2( 1, 0 ) }; - const ImmediateVertex v3A = { glm::vec3( -1.0, 0.5, 0 ), white, glm::vec2( 0, 1 ) }; - const ImmediateVertex v4A = { glm::vec3( -0.5, 0.5, 0 ), white, glm::vec2( 1, 1 ) }; + immediate_render( &imm, state->test_tex_at_pos, state->test_tex_at_colour, true, state->test_tex_at_uv, state->test_tex_un_tex ); + glDeleteTextures( 1, &tex ); + glBindTexture( GL_TEXTURE_2D, 0 ); - immediate_triangle( &imm, v1A, v2A, v3A ); - immediate_triangle( &imm, v3A, v2A, v4A ); - immediate_render( &imm, at_pos, at_colour, true, at_uv, un_tex ); + // TODO: the positions don't make sense + draw_string( state, -140, -100, "hello", state->test_tex_at_pos, state->test_tex_at_colour, state->test_tex_at_uv, state->test_tex_un_tex ); - glBindTexture( GL_TEXTURE_2D, 0 ); - glDeleteTextures( 1, &tex ); - glDeleteProgram( texshader ); + glUseProgram( 0 ); glDisable( GL_BLEND ); glEnable( GL_DEPTH_TEST ); }