diff --git a/data/shaders/textoverlay/generate-spirv.bat b/data/shaders/textoverlay/generate-spirv.bat new file mode 100644 index 00000000..cb22c267 --- /dev/null +++ b/data/shaders/textoverlay/generate-spirv.bat @@ -0,0 +1,4 @@ +glslangvalidator -V text.vert -o text.vert.spv +glslangvalidator -V text.frag -o text.frag.spv +glslangvalidator -V mesh.vert -o mesh.vert.spv +glslangvalidator -V mesh.frag -o mesh.frag.spv diff --git a/data/shaders/textoverlay/mesh.frag b/data/shaders/textoverlay/mesh.frag new file mode 100644 index 00000000..a11e501d --- /dev/null +++ b/data/shaders/textoverlay/mesh.frag @@ -0,0 +1,29 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D samplerColorMap; + +layout (location = 0) in vec3 inNormal; +layout (location = 1) in vec3 inColor; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inViewVec; +layout (location = 4) in vec3 inLightVec; + +layout (location = 0) out vec4 outFragColor; + +void main() +{ + vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); + + vec3 N = normalize(inNormal); + vec3 L = normalize(inLightVec); + vec3 V = normalize(inViewVec); + vec3 R = reflect(-L, N); + vec3 diffuse = max(dot(N, L), 0.0) * inColor; + vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); + outFragColor = vec4(diffuse * color.rgb + specular, 1.0); + + outFragColor.rgb = vec3(diffuse + specular); +} \ No newline at end of file diff --git a/data/shaders/textoverlay/mesh.frag.spv b/data/shaders/textoverlay/mesh.frag.spv new file mode 100644 index 00000000..37023da1 Binary files /dev/null and b/data/shaders/textoverlay/mesh.frag.spv differ diff --git a/data/shaders/textoverlay/mesh.vert b/data/shaders/textoverlay/mesh.vert new file mode 100644 index 00000000..df49c062 --- /dev/null +++ b/data/shaders/textoverlay/mesh.vert @@ -0,0 +1,36 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + vec4 lightPos; +} ubo; + +layout (location = 0) out vec3 outNormal; +layout (location = 1) out vec3 outColor; +layout (location = 2) out vec2 outUV; +layout (location = 3) out vec3 outViewVec; +layout (location = 4) out vec3 outLightVec; + +void main() +{ + outNormal = inNormal; + outColor = inColor; + outUV = inUV; + gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); + + vec4 pos = ubo.model * vec4(inPos, 1.0); + outNormal = /*mat3(ubo.model) */ inNormal; + vec3 lPos = /*mat3(ubo.model) */ ubo.lightPos.xyz; + outLightVec = lPos - pos.xyz; + outViewVec = -pos.xyz; +} \ No newline at end of file diff --git a/data/shaders/textoverlay/mesh.vert.spv b/data/shaders/textoverlay/mesh.vert.spv new file mode 100644 index 00000000..54e8d7b1 Binary files /dev/null and b/data/shaders/textoverlay/mesh.vert.spv differ diff --git a/data/shaders/textoverlay/text.frag b/data/shaders/textoverlay/text.frag new file mode 100644 index 00000000..83ceb1ea --- /dev/null +++ b/data/shaders/textoverlay/text.frag @@ -0,0 +1,13 @@ +#version 450 core + +layout (location = 0) in vec2 inUV; + +layout (binding = 0) uniform sampler2D samplerFont; + +layout (location = 0) out vec4 outFragColor; + +void main(void) +{ + float color = texture(samplerFont, inUV).r; + outFragColor = vec4(vec3(color), 1.0); +} diff --git a/data/shaders/textoverlay/text.frag.spv b/data/shaders/textoverlay/text.frag.spv new file mode 100644 index 00000000..4aea3bdf Binary files /dev/null and b/data/shaders/textoverlay/text.frag.spv differ diff --git a/data/shaders/textoverlay/text.vert b/data/shaders/textoverlay/text.vert new file mode 100644 index 00000000..3143256f --- /dev/null +++ b/data/shaders/textoverlay/text.vert @@ -0,0 +1,12 @@ +#version 450 core + +layout (location = 0) in vec2 inPos; +layout (location = 1) in vec2 inUV; + +layout (location = 0) out vec2 outUV; + +void main(void) +{ + gl_Position = vec4(inPos, 0.0, 1.0); + outUV = inUV; +} diff --git a/data/shaders/textoverlay/text.vert.spv b/data/shaders/textoverlay/text.vert.spv new file mode 100644 index 00000000..e086b48d Binary files /dev/null and b/data/shaders/textoverlay/text.vert.spv differ diff --git a/external/stb/stb_font_consolas_24_latin1.inl b/external/stb/stb_font_consolas_24_latin1.inl new file mode 100644 index 00000000..b47a4e06 --- /dev/null +++ b/external/stb/stb_font_consolas_24_latin1.inl @@ -0,0 +1,732 @@ +// Font generated by stb_font_inl_generator.c (4/1 bpp) +// +// Following instructions show how to use the only included font, whatever it is, in +// a generic way so you can replace it with any other font by changing the include. +// To use multiple fonts, replace STB_SOMEFONT_* below with STB_FONT_consolas_24_latin1_*, +// and separately install each font. Note that the CREATE function call has a +// totally different name; it's just 'stb_font_consolas_24_latin1'. +// +/* // Example usage: + +static stb_fontchar fontdata[STB_SOMEFONT_NUM_CHARS]; + +static void init(void) +{ + // optionally replace both STB_SOMEFONT_BITMAP_HEIGHT with STB_SOMEFONT_BITMAP_HEIGHT_POW2 + static unsigned char fontpixels[STB_SOMEFONT_BITMAP_HEIGHT][STB_SOMEFONT_BITMAP_WIDTH]; + STB_SOMEFONT_CREATE(fontdata, fontpixels, STB_SOMEFONT_BITMAP_HEIGHT); + ... create texture ... + // for best results rendering 1:1 pixels texels, use nearest-neighbor sampling + // if allowed to scale up, use bilerp +} + +// This function positions characters on integer coordinates, and assumes 1:1 texels to pixels +// Appropriate if nearest-neighbor sampling is used +static void draw_string_integer(int x, int y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0, cd->t0); glVertex2i(x + cd->x0, y + cd->y0); + glTexCoord2f(cd->s1, cd->t0); glVertex2i(x + cd->x1, y + cd->y0); + glTexCoord2f(cd->s1, cd->t1); glVertex2i(x + cd->x1, y + cd->y1); + glTexCoord2f(cd->s0, cd->t1); glVertex2i(x + cd->x0, y + cd->y1); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance_int; + } + glEnd(); +} + +// This function positions characters on float coordinates, and doesn't require 1:1 texels to pixels +// Appropriate if bilinear filtering is used +static void draw_string_float(float x, float y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0f, cd->t0f); glVertex2f(x + cd->x0f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t0f); glVertex2f(x + cd->x1f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t1f); glVertex2f(x + cd->x1f, y + cd->y1f); + glTexCoord2f(cd->s0f, cd->t1f); glVertex2f(x + cd->x0f, y + cd->y1f); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance; + } + glEnd(); +} +*/ + +#ifndef STB_FONTCHAR__TYPEDEF +#define STB_FONTCHAR__TYPEDEF +typedef struct +{ + // coordinates if using integer positioning + float s0,t0,s1,t1; + signed short x0,y0,x1,y1; + int advance_int; + // coordinates if using floating positioning + float s0f,t0f,s1f,t1f; + float x0f,y0f,x1f,y1f; + float advance; +} stb_fontchar; +#endif + +#define STB_FONT_consolas_24_latin1_BITMAP_WIDTH 256 +#define STB_FONT_consolas_24_latin1_BITMAP_HEIGHT 170 +#define STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 256 + +#define STB_FONT_consolas_24_latin1_FIRST_CHAR 32 +#define STB_FONT_consolas_24_latin1_NUM_CHARS 224 + +#define STB_FONT_consolas_24_latin1_LINE_SPACING 16 + +static unsigned int stb__consolas_24_latin1_pixels[]={ + 0x08262131,0xff904400,0x3ffe1fff,0x3b2206ff,0x2007913f,0x0000defa, + 0x64c00f32,0x0de5c402,0x00a614c0,0x4002ae62,0x98014c19,0x01aa881c, + 0x00d54400,0xb880154c,0x8330020b,0x1e980029,0xaa7d5dd4,0x2001d94f, + 0x3332a6e8,0x999ff0ff,0x37ffa207,0x2600df12,0x8000fffd,0x3fa005fd, + 0xfdff700f,0x8ffc409f,0x3ea02ff8,0x200dffff,0x0bfe0ff8,0x7d407ee0, + 0xfd10001f,0x9fff5007,0xcffff880,0x1ff104eb,0x320017fc,0x7d77e40f, + 0x17ee9f54,0xfd027ec0,0x7dc01fe1,0x0037c40d,0xb0017f22,0xffe8007f, + 0x7dc3fd80,0x741ff104,0x59ff701f,0x7401dfd7,0x2003f60e,0x3fa200fc, + 0x0ff44001,0x7dc6fdc0,0x32236604,0x3ba00eff,0x31003f60,0xdf90dd57, + 0xd93ea9f5,0x037e403f,0x803fc3fa,0x06f882fd,0x2006f980,0xa8800098, + 0xf903fb81,0x88040401,0x1ff441ff,0x0fb00000,0x00000000,0x00020000, + 0xffffa800,0xfadfb86f,0x7fc49f54,0x803ff301,0x200ff0fe,0x06f880fe, + 0x0000ff00,0x05f88000,0x40000fe6,0x0ff504fc,0x81540153,0x100affb9, + 0x22001573,0x31000ab9,0x26200157,0x731000ab,0xcffb8015,0x7dc4ffda, + 0x89f54fad,0x3fe80ff9,0x0ff0fe80,0x3e203fa0,0x807ddb36,0x01dd107f, + 0xdddb076c,0x1fb8bddd,0x1dd12fc0,0x3ff076c0,0x3f60ffc0,0xe98ff102, + 0xa84fffff,0x00dfffff,0x37ffffea,0x3fffea00,0x3fea00df,0x2a00dfff, + 0x80dfffff,0x3bb61ff8,0x3eb3ea3f,0x7f909f54,0xfd005fa8,0x7f401fe1, + 0xffaef880,0x1fe05ffe,0xdf504fd8,0xfffffff8,0x9db33746,0x09fb1b6b, + 0x80ff1bea,0x817ec2fd,0x33fe67f8,0x7dc3acfa,0x0efebacf,0xebacffb8, + 0xcffb80ef,0xb80efeba,0xefebacff,0xbacffb80,0x27e40efe,0x20df59f1, + 0x509f54fa,0x003fd8bf,0x401fe1fd,0x9fff107e,0x7407fe61,0x20ff500f, + 0x6f9803fd,0x777ccfe2,0x7fa8db6f,0x37cc7fb0,0x5fb0ff60,0x3fe9fe20, + 0x3ff105f3,0x7c43fe88,0x21ff441f,0x7f441ff8,0x220ffc43,0x0ffc43fe, + 0x3ff0ffa2,0x267f97d4,0x9f54fadf,0x1ff8ff10,0x1fe1fd00,0x7c417e20, + 0x704fb84f,0x217f405f,0xf9800ff8,0x47f47ea6,0xfd0f95f8,0x260ff885, + 0x21fe406f,0x2ff102fd,0x207ea6f9,0x8ff504fc,0x8ff504fc,0x8ff504fc, + 0x8ff504fc,0x8ff504fc,0x3fd3e47f,0x553eafea,0x261ff04f,0x1fd000ff, + 0xefcc81fe,0x260ff101,0x9bfb105f,0x7d45fb81,0x64df3005,0x9f34f98f, + 0x517ee1f2,0x407f98bf,0x817ec2fd,0x5cbf57f8,0x201ff80f,0x807fe1ff, + 0x807fe1ff,0x807fe1ff,0x807fe1ff,0xf8df31ff,0x47e4bf65,0x203514fa, + 0x00df52fd,0x107f87f4,0x7c403fff,0x440df306,0x7fc41ffe,0x4c00bf60, + 0x97ddf66f,0xf10db2fa,0x2217ec1f,0x20ff407f,0x2ff102fd,0x7c1f64fb, + 0xff17ec07,0x1fe2fd80,0x03fc5fb0,0x407f8bf6,0x4cdf32fd,0x9d4ff22f, + 0x9f7004fa,0xfe8013ee,0x6cc40ff0,0x20df103f,0x3bf506f9,0x7c4ff601, + 0xd9be6007,0x47f23f96,0x227fb06d,0x203ff07f,0x17ec0ff8,0x4df57f88, + 0x406f986e,0x80df33fd,0x80df33fd,0x80df33fd,0x80df33fd,0x64ff13fd, + 0x2a0bf60f,0x29f9004f,0x3fa005fa,0x1be00ff0,0x5fa837c4,0xfa801f90, + 0x4c009f76,0x87edba6f,0x2a09f0fd,0x3209f76f,0xb0bf704f,0x4dfe205f, + 0xf30bf0ff,0xf33fc80d,0xf33fc80d,0xf33fc80d,0xf33fc80d,0x3e3fc80d, + 0x03fd1ba7,0x3f6009f5,0x7400ff13,0x3a00ff0f,0x906f880f,0x401fa07f, + 0x001fe9ff,0xf96e9be6,0x017cdfe3,0x203fd3ff,0x7fd43ff9,0xf102fd81, + 0x27d7fecf,0xfb01fe63,0xfb01fe65,0xfb01fe65,0xfb01fe65,0xfb01fe65, + 0x1fc4ff45,0x9f501ff1,0xfe8bfe00,0x3e1fd001,0x101fd007,0x40df50df, + 0xfbf9007e,0x26f9800d,0xfdb9f56d,0x7e401fb7,0x7fdc06fd,0xb02ffede, + 0x89fe205f,0x4feefffc,0x1fe80ff1,0x1fe80ff1,0x1fe80ff1,0x1fe80ff1, + 0x1fe80ff1,0xb87ef7f2,0x2a9f505f,0x647f984f,0x21fd002f,0x01fd007f, + 0xfb99dff1,0x803f403f,0x4003fff8,0x6c5f26f9,0x01ffe8ef,0x401fffc4, + 0x01dfffda,0x2fd40ff2,0x0e77ff4c,0x3fe203ff,0x7c407fe0,0x4407fe0f, + 0x407fe0ff,0x07fe0ff8,0xff107fc4,0x807fd4fd,0x509f54fa,0x004fa8bf, + 0x401fe1fd,0xfff880fe,0x7400deff,0x01ff6007,0x0fb9be60,0x7ec00302, + 0x027dc007,0x4fc827dc,0x3f203f70,0xfc8bf704,0xfc8bf704,0xfc8bf704, + 0xfc8bf704,0xf30bf704,0x07ffd9df,0x84faa7d4,0x07fc41fe,0x07f87f40, + 0xdf101fd0,0x07f80022,0x2000ff60,0x00fe65fa,0x001fec00,0x98103fe6, + 0x0ffcc1ff,0xff100fc8,0x440ffa87,0x07fd43ff,0xff50ffe2,0x543ff881, + 0x1ffc40ff,0x7dc03fea,0x5401dfff,0xfc89f54f,0xd00df705,0x6c01fe1f, + 0x006f883f,0xf5006f98,0x9fb0001f,0xa80006e8,0xfd8000ff,0xfc86fcdf, + 0x04ffecdf,0xdff701f6,0x2e07ffd9,0x3ffeceff,0xfd9dff70,0x3bfee07f, + 0xf703ffec,0x07ffd9df,0x5000cfec,0xfa93ea9f,0x013f600f,0x401fe1fd, + 0x37c41efb,0x013f6600,0x33007fea,0x2e07fdc4,0xf500505f,0x7e40003f, + 0xfd703fff,0x6e805dff,0xdfffea80,0x7fff5401,0x7ff5401d,0x7f5401df, + 0x75401dff,0x7c01dfff,0x54fa8005,0x00bfe29f,0x775c3fd1,0xddff0ffe, + 0x7fff409d,0x2600df12,0xf300effe,0xf7007fff,0x207fffdf,0x7fdcdffb, + 0x07ffff30,0x80022000,0x0017e001,0x00060003,0x0018000c,0x07220030, + 0x7d53ea00,0x26007fb4,0x3bbbae6f,0x9ddddb0e,0xd12ecb80,0x0f3a600b, + 0x0019bd30,0x073bbb22,0x17bdb730,0x00337a60,0x00000000,0x00000000, + 0x00000000,0x00000000,0x4d3ea9f5,0x00154004,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x20000000,0x009f54fa, + 0x77777400,0xeeeeeeee,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x4c000000,0x0007d33e,0x77777740,0x0eeeeeee, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x54400000,0x2a20001a,0x0154c01a,0x54400b20, + 0xaaa98000,0x99953100,0x032e0059,0x10053066,0x22004177,0x04c801aa, + 0x01aa8800,0x500d5440,0x51017997,0x51000035,0x0bb88035,0x00d54402, + 0x0007fea0,0xf500ffa2,0x3e6009ff,0x3fef9803,0xfffff700,0xffffb89f, + 0xf8804fff,0x3e0ff886,0x3ffe202f,0x5404ebcf,0x0fec01ff,0x07fd1000, + 0x103fe880,0x05fffffd,0x80007fea,0x7c403fe8,0x04ebcfff,0x88003ff5, + 0x3a2001fe,0x46fdc01f,0x7dc404fb,0x6baec00b,0xabcffd80,0x3fff24ec, + 0x804fb9df,0x41dd03fb,0x236600fd,0x800effc8,0x3e601fe8,0x3fd10005, + 0x01fe8800,0x008833f6,0x20007fa2,0xd9801fe8,0x00effc88,0x00007fa2, + 0x00000000,0x9fffffd5,0x036cf640,0x98407bee,0xf54fffff,0x001fd009, + 0x00020000,0x0007f400,0x44000000,0x0000007f,0x00200000,0x40153000, + 0xa802a62a,0x2a802a62,0x33fb7ff2,0x3bfa204d,0x007fe201,0x53fffff2, + 0x27d404fa,0x40015540,0x553002aa,0x50555555,0x01aa807f,0x554c1544, + 0xf82aaaaa,0x2aa8002f,0x802aa800,0x50aa02a9,0x55555555,0xf102fd81, + 0xf8817ecf,0x7c40bf67,0x1f61ff37,0x5c02aa80,0xfff9005f,0x013ea9ff, + 0xff8803fb,0x3fe2002f,0xfffc802f,0xdf07ffff,0x6406fb80,0xffffc85f, + 0xffb87fff,0x3ffe2003,0x3ffe2002,0x41ffe402,0x7fffc6f8,0x6c0fffff, + 0x6cff102f,0x6cff102f,0x2eff102f,0x4401ba5f,0x3f202fff,0xffff7003, + 0x8813ea9f,0xfffa805f,0x3ffea004,0xaacfc804,0x5f902aaa,0xf103ff80, + 0x559f901f,0xff985555,0xfa802eff,0x3ea004ff,0x7fe404ff,0x5546f886, + 0x0aaadfda,0x7f8817ec,0x3fc40bf6,0x5fe205fb,0x4017e7fa,0x3604fffa, + 0xfff3002f,0x813ea9ff,0xafd802fc,0x2bf6007f,0x03fc807f,0x2a02fc40, + 0x04fd80ff,0x3fa007f9,0x404ffd89,0x2007fafd,0x6407fafd,0x37c42fef, + 0xfd809f70,0x7ecff102,0x7ecff102,0x3e2ff102,0xb004faef,0x7f40ff5f, + 0x3fff2002,0x7c09f54f,0xfd7f8807,0x3aff1003,0x01fe401f,0x3a00fec0, + 0x807fcc4f,0x5f9803fc,0xf8827fd4,0xf1003fd7,0xfc807faf,0x037c46fb, + 0x2fd809f7,0x17ecff10,0x0bf67f88,0xffd33fc4,0x7f88019f,0x0bfa03fd, + 0x29ffd500,0x07f504fa,0x13ee9f50,0x27dd3ea0,0x2000ff20,0x7fcc04fa, + 0xfc80ff60,0x886f9803,0x74fa81ff,0x29f5009f,0x2bf204fb,0x81be22fd, + 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0x3fae1fe2,0x53ea03ff,0x07fb04fb, + 0x4fa84c00,0xfb001fd0,0x3601fe65,0xc80ff32f,0x1fd0003f,0xdf34fd80, + 0xf003fc80,0xb07f905f,0x201fe65f,0x40ff32fd,0x226faafc,0x013ee06f, + 0x9fe205fb,0x4ff102fd,0x0ff102fd,0x417ff7ee,0x20ff32fd,0x500006fb, + 0x00bf309f,0x01fe8ff1,0x03fd1fe2,0x777777e4,0x01fdc04e,0x0bf63fe2, + 0xdddddf90,0x43ffa89d,0x23fc43fb,0x1fe201fe,0x4bf203fd,0x40df11fe, + 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0x9be41fe2,0x23fc43ff,0x2ff881fe, + 0x84fa8000,0x5fa801fc,0xbf5027e4,0x3f204fc8,0x06ffffff,0x7e4037c4, + 0xffc806fe,0xa86fffff,0x0ff89eff,0x13f22fd4,0x27e45fa8,0x2bf52fc8, + 0x13ee06f8,0x3e205fb0,0x7c40bf67,0x7c40bf67,0x2fdcdb07,0x09f917ea, + 0x0620bff2,0x3e227d40,0x985fb006,0x30bf607f,0x01fe40ff,0x8803f900, + 0xfc801fff,0x7fec4003,0x42fd82ff,0x0bf607f9,0x8bf20ff3,0x206f89ff, + 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0xb2f41fe2,0x4c2fd89f,0x3fff607f, + 0x5004fedd,0x802fb89f,0x99999ff8,0x9ff881ff,0x01ff9999,0x4c0007f9, + 0x05fb805f,0x20007f90,0xff886fe9,0x1ff99999,0x9999ff88,0x2fc81ff9, + 0x81be33ee,0x1fe404fb,0x0ff25fa8,0x07f92fd4,0x9f04d7ea,0x7c43ff71, + 0xff99999f,0x3fffaa01,0x7f9002ce,0xff5007e8,0x9fffffff,0xffffff50, + 0x3f209fff,0x07f40003,0x64013ee0,0x3a20003f,0x7fffd42f,0xa84fffff, + 0xffffffff,0x222fc84f,0x2e06f9ff,0x827dc04f,0x413ee4fc,0x413ee4fc, + 0xfdffb4fc,0xfa87ffff,0xffffffff,0x0077c404,0x9f517f40,0x3337f600, + 0xd86fdccc,0xdcccccdf,0x007f906f,0x5c04fa80,0x07f9004f,0x6c2fe800, + 0xdcccccdf,0xccdfd86f,0xc86fdccc,0x37e7e42f,0xf9809f70,0x30ffcc1f, + 0x1ff983ff,0xff307fe6,0x3fffb6a3,0xcdfd80ce,0x06fdcccc,0x37601fd4, + 0x6c6fd989,0x0ff8800f,0xff887fe0,0x3207fe00,0x7f80003f,0xc8027dc0, + 0x4c15003f,0x3fe20ffb,0xf887fe00,0x907fe00f,0x6fff885f,0x32013ee0, + 0x4ffecdff,0xfecdffc8,0xcdffc84f,0x3f704ffe,0xf007fc40,0x00fe403f, + 0xdfffffb1,0xa802fcc3,0x527ec05f,0x84fd80bf,0xeeeeeefc,0x80bee006, + 0xdf9004fb,0xf8dddddd,0x41ffffff,0x27ec05fa,0x4fd80bf5,0x7fe417e4, + 0x7ff776c6,0xfd700eee,0x75c05dff,0x2e02efff,0x202efffe,0x17ea00fc, + 0x14c09fb0,0x82cdba80,0x7fb001ca,0x3f66fa80,0x6437d403,0x7fffffff, + 0xb80f2200,0xfff9004f,0xcb8fffff,0x7fb02cdd,0x3f66fa80,0x3237d403, + 0x46ff882f,0xffffffff,0x8001800f,0x90018001,0x403fd80b,0x000006fa, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0d544000,0x2600aa60,0x54c014c1,0x14c19802,0x400154c0, + 0xcb9802c9,0x0332e02c,0x30a60f22,0x00332a05,0x4000b260,0x0cca83cc, + 0x01e64000,0x2e200b26,0x6644020b,0x00cca801,0xe8803ca8,0x7ffd403f, + 0xf83fe204,0x3ffea02f,0xf83fe204,0x3ffea02f,0x3f7ee004,0x3ffff604, + 0x7f7ec0ef,0x220fe40f,0x05ff11ff,0xa8003bee,0x6c003fff,0x03bee05f, + 0x202fec00,0x2203fffa,0x4eacffff,0x9d95ff70,0x9003bee0,0x1fe880bf, + 0x7dc6fdc0,0xfd83ba04,0xf71bf700,0xfb077409,0x2e37ee01,0x2a7d004f, + 0x261bf907,0x54fea4fd,0x2213ea3f,0x807fa0ff,0xfa800ef9,0xb003fc8d, + 0x1df3007f,0x403fd800,0x03fc8dfa,0xdffb31d3,0xfffdb881,0x3be603ef, + 0x0017f200,0x00000000,0x00000000,0x7b8dd800,0x6f981ff0,0x8a7c47ee, + 0x020200ee,0x22002620,0x4c400cc1,0x00262000,0x18800988,0x011000cc, + 0x0ffb7fe2,0xf9004c40,0x5555550b,0xaa981555,0x982aaaaa,0x2aaaaaaa, + 0xaaaaaaa8,0x555540aa,0x200aaaaa,0x7cc002aa,0x86f882ff,0x44bee5fa, + 0x0005f94f,0x00000000,0x00000000,0x00000000,0x001ff982,0xff0bf900, + 0x1fffffff,0xffffffc8,0xffffc87f,0xfff87fff,0x40ffffff,0xffffffff, + 0x5fff100f,0x26013000,0x30ffd45f,0xf33fb3bf,0x9dfb7009,0xcefdb801, + 0x677edc00,0x677edc00,0xdfdb7100,0x3b6e203b,0xb7101def,0x2203bdfd, + 0x01defedb,0x01bffb2a,0x7039dfb7,0xfb5550bf,0xfc81555b,0x82aaaaac, + 0xaaaaacfc,0xdfdaaa82,0x55540aaa,0x00aaadfd,0x1009fff5,0x83bdfdb7, + 0x07bee5f9,0x7f4fffee,0x76f7ec00,0xbdfb02ff,0x3f605ffd,0xb02ffede, + 0x05ffdbdf,0xfffddff7,0xfddff705,0xdff705ff,0xf705fffd,0x05fffddf, + 0x5ffddffb,0xffdffd30,0x404fb87f,0x1fe404fb,0x0007f900,0xfb8013ee, + 0xff5fb004,0xfddff700,0x8afcc5ff,0x426200ff,0x27e402fc,0x9f903fea, + 0x7e40ffa8,0x3207fd44,0x207fd44f,0x43fdc419,0x43fdc419,0x43fdc419, + 0x23fdc419,0x1bea0dfc,0x3ff513fa,0x3ee027dc,0x001fe404,0x2e0007f9, + 0x13ee004f,0x0ff5fe20,0xff710660,0x07f8afcc,0xf1017e60,0xf88ff20d, + 0x7c47f906,0x7c47f906,0x4007f906,0x3fe000ff,0x003fe000,0x0df30ff8, + 0x05fa87fa,0x027dcbf9,0x7f9013ee,0x001fe400,0x2e004fb8,0x74fa804f, + 0x7fc0009f,0x27fcbf30,0x5400fe80,0x549f504f,0x549f504f,0x549f504f, + 0x009f504f,0xfb000fec,0x00fec003,0x0fee3fb0,0x05f927e4,0x04fb9be2, + 0x3f2027dc,0x00ff2003,0x70027dc0,0x25fb009f,0x360007f9,0x7ccbf31f, + 0x4bee00df,0x77dc1dec,0x5feeeeee,0x3bbbbbee,0x3bee5fee,0x5feeeeee, + 0x3bbbbbee,0xec985fee,0x981ffffe,0x1ffffeec,0xfffeec98,0xfeec981f, + 0x05fb1fff,0x01fe97ea,0x403fa9fe,0x77e404fb,0xc84eeeee,0x4eeeeeef, + 0x70027dc0,0x47f8809f,0x764c01fe,0xf31ffffe,0x80efe98b,0xffbfd5f8, + 0x77777e43,0x3f24eeee,0xeeeeeeee,0x3bbbbf24,0x3f24eeee,0xeeeeeeee, + 0x6677fdc4,0x7fdc1ffc,0x41ffccce,0xfccceffb,0x677fdc1f,0x3fb1ffcc, + 0x1fe97ea0,0x03fa9fe0,0x3f2027dc,0x86ffffff,0xfffffffc,0x0027dc06, + 0x5fa809f7,0xff7027e4,0x23ff999d,0x4fe885f9,0x33f98fe8,0x002fdc9f, + 0x7dc00bf7,0x017ee005,0xfd81ff88,0x3607fe21,0x207fe21f,0x07fe21fd, + 0x817e47f6,0x40bf64fb,0x007266f8,0x3fc809f7,0x000ff200,0xf70027dc, + 0x4c2fd809,0x03ff107f,0x417e63fb,0xb9fdc6f9,0xffa97e1f,0x01ff5000, + 0x4003fea0,0xf5000ffa,0xfa87fa0b,0x7d43fd05,0x7d43fd05,0x3ee3fd05, + 0x7e45fb05,0x000bf704,0x3fc809f7,0x000ff200,0xf70027dc,0x4cffc409, + 0xa81ff999,0x263fd05f,0x44df305f,0x7c4bea6f,0x80067f44,0xfd000cfe, + 0x33fa0019,0x446fa800,0x1bea1ffd,0x7d43ffb1,0x50ffec46,0x1ffd88df, + 0x7fa85ff1,0x3e60ffc4,0x700faa1f,0x03fc809f,0x4000ff20,0x3ee004fb, + 0x3fffea04,0xa84fffff,0x8ffec46f,0xfb9935f9,0xf10fec5f,0xf983fb7d, + 0x0eccbdff,0x65efffcc,0x7ffcc0ec,0x4c0eccbd,0xeccbdfff,0x373bfe20, + 0x3e21feff,0xfeffdcef,0x373bfe21,0x3e21feff,0xfeffdcef,0x3737fee1, + 0xdffb82ff,0x7fc3ffdc,0x2027dc07,0x3f2003fc,0x09f70003,0xfb027dc0, + 0xfb99999b,0xb9dff10d,0x3e63fdff,0x45dfff35,0xfffa83fa,0xffffb102, + 0xffb101df,0xb101dfff,0x01dfffff,0xdfffffb1,0xdfffe981,0x7f4c1fc8, + 0x41fc8dff,0xc8dfffe9,0x7fff4c1f,0x7541fc8d,0x2a01efff,0xc81efffe, + 0x027dc05f,0xfc800ff2,0x09f70003,0xf8827dc0,0x207fe00f,0xc8dfffe9, + 0x0002201f,0x02620008,0x20009880,0x26200098,0x40008800,0x00440008, + 0x06000220,0x40600600,0xeeffeeed,0x7777e40e,0xefc86eee,0xd86eeeee, + 0xeeeffeee,0x7ff776c0,0x0bf50eee,0x02204fd8,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0xffffff80,0x7fe40fff,0xc87fffff, + 0x7fffffff,0xfffffff8,0x7fffc0ff,0xfb0fffff,0x006fa807,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x40f32000,0xca814c29,0x055cc00c,0x203cc800,0x98014c29,0x0bb8802c, + 0x40044002,0x298003c8,0x0310014c,0x8000b260,0x157300cb,0x76c17a20, + 0x00f32000,0x32a0aa62,0x027d400c,0xf882fec0,0x205ff11f,0x3ee00efb, + 0x36001eff,0x47fe205f,0x7d402ff8,0x3fe203ff,0x204eacff,0x203ffffa, + 0x7c4006f8,0x005ff11f,0x3fea01f6,0x3fb0003f,0x4fffff98,0x1fd06f88, + 0x8817f600,0x706ffffb,0x7ff401df,0x80ff6000,0x07fa0ff8,0x5100ef98, + 0xb005ffd7,0x0ff8807f,0xdfa807fa,0x1d303fc8,0x201dffb3,0x2ffdcffa, + 0x8800df10,0x007fa0ff,0x37ea02fc,0xd8003fc8,0x26ffea1f,0x37c44feb, + 0xfd800fe8,0x37ffe603,0x3be602ac,0x400bf700,0x10100098,0x20013100, + 0x26200ffb,0x00202000,0x20019831,0x717ec008,0x01be20bf,0xb7004040, + 0x18807fff,0x7ec000cc,0xff10bfa1,0xfe837c41,0x1004c400,0x310007ff, + 0x00000001,0x20000000,0x000004fd,0x00000000,0x6f983fe0,0x0000df10, + 0xfeffe980,0x000001ff,0x17ea3fb0,0x0df127dc,0x200003fa,0x000003fc, + 0x05e88026,0x82f443d9,0x417a21ec,0x17ee01ec,0x00e77edc,0x80e77edc, + 0x03d905e8,0x8073bf6e,0x413ee2fe,0x7ddb36f8,0x3bfb6e20,0xf13fe81d, + 0x6dc03ffd,0x65401cef,0xf91ffdee,0x44dfd305,0x701fd06f,0x7c0bdddd, + 0x7775c007,0x407f305e,0x45fb06f8,0x45fb06f8,0x05fb06f8,0x3fa61fdc, + 0x303fffef,0x7fffdffd,0x3f60df10,0x7f7ff4c2,0x2df903ff,0xdf100ffa, + 0x0bffdff5,0xfffddff7,0x5f52fdc5,0xffd309f7,0xb107fffd,0x3fffdfff, + 0xfff707f6,0xfe837c4f,0x7ffffc80,0x2aa2bf30,0xffff9009,0x8813ea0f, + 0x445fb06f,0x445fb06f,0x205fb06f,0x27f40ff9,0x3fa07fea,0x220ffd44, + 0xe85fb06f,0x40ffd44f,0x01efeff8,0x4c33ffe2,0x220cc1ff,0xd8bf27fb, + 0x9fd0bf17,0x7e41ffa8,0xfe8ff42d,0xff3dfb10,0x0fe837c4,0xfa83fc40, + 0x2fffffee,0xfa83fc40,0x6c1be204,0x6c1be22f,0x6c1be22f,0x3fffe62f, + 0xfc82fd44,0xfc82fd45,0xfd837c45,0x7e417ea2,0x00bffb05,0x9f709ff1, + 0xfe87fc00,0x547f93e0,0x44bf905f,0x3e3fb07f,0xf0dff98f,0x303fe21f, + 0x7f8803ff,0x537bff70,0x7c403ff9,0x4409f507,0x445fb06f,0x445fb06f, + 0x4c5fb06f,0x05f902ef,0x05f91be2,0x0df11be2,0x02fc8bf6,0xefe88df1, + 0x88ff11ff,0x00bf307f,0x50fe8fec,0x3f23fc5f,0x7dcdf102,0x3fa3fb04, + 0x13fc3ffc,0x7ff445ff,0xb83fc401,0x40bf904f,0x09f507f8,0x2fd837c4, + 0x17ec1be2,0x8bf60df1,0x07fa04f9,0x00ff47f8,0xb06f88ff,0xf00ff45f, + 0xdfb4fd8f,0x6f88df31,0xd930df30,0x323ffffd,0x37c4fb2f,0x27f807fa, + 0x23fb03fc,0x7c41effd,0x337ffe27,0x202efbef,0x09f707f8,0x7f881be6, + 0x7c40bf50,0x7c45fb06,0x7c45fb06,0x7cc5fb06,0xf807fa04,0xff00ff47, + 0x5fb06f88,0x4ff00ff4,0x56ff47f8,0x9837c45f,0x677fdc6f,0x9f51ffcc, + 0x745fa97e,0xfd9fe01f,0x3f23fb02,0x225fa80d,0xb0dffeef,0x83fc409f, + 0x0ff105fa,0x5fb83fc4,0x7ec1be20,0x7ec1be22,0x7ec1be22,0xfd80b222, + 0xfd8df102,0xf88df102,0x7ec5fb06,0x7ccdf102,0x17fffc46,0x2fd41be2, + 0x3fb03ff1,0x44bf3fe2,0x817ec1fe,0x413f26f8,0x20df31fe,0x45be22fd, + 0x07f88000,0x17ea0ff1,0xbf707f88,0x7c40ff80,0x2207fc2f,0x207fc2ff, + 0x64002ff8,0xc8bf704f,0xf0bf704f,0x22ff881f,0x4bf704fc,0xfffa87f9, + 0xfc837c40,0x7f417ea3,0x373ffea1,0x04fc84ff,0x42fdcbf7,0x0ffa1ffb, + 0x06f88ff5,0xb03fc400,0x02fe889f,0x2fdc1fe2,0xfe88bfe0,0xd117fc2f, + 0x22ff85ff,0x3a62ffe8,0x307fe204,0x1ff883ff,0x7fc0ffcc,0x88bffa22, + 0x0ffcc1ff,0xffd50ffe,0xfa86f883,0x36237d46,0x7ffd41ff,0x3ff102ef, + 0x3e21ff98,0x87ffea1f,0xffdcdff9,0x00037c41,0xff981fe2,0x404fecbd, + 0x0bf707f8,0xefcdffb8,0x6ffdc2fd,0x5c2fdefc,0xfdefcdff,0xb803ff62, + 0x3ffdcdff,0xfb9bff70,0x37fee07f,0x5c2fdefc,0x3ffdcdff,0xffceffa8, + 0x3e20efef,0x1ffdccef,0x7ee77fc4,0x5fd41fef,0x9bff7001,0xffb07ffb, + 0x83f99fdb,0x81dfffd8,0xcc8006f8,0x1cccffcc,0x177ffec4,0xcffcccc8, + 0x00df71cc,0xf71bffd5,0x1bffd505,0xffd505f7,0x7dc5f71b,0xfffea806, + 0x7ff5401e,0x7f5401ef,0xa82fb8df,0x201efffe,0xd1dfffea,0xfffdb8bf, + 0xffd300de,0xd83f91bf,0xffea8007,0x3ff201ef,0x0c03f93e,0x20017a20, + 0xffffffff,0x3e00603f,0xffffffff,0x4400bd73,0x00044000,0x00020022, + 0x000c0006,0x00c00044,0x01000040,0x3c800440,0x2000c000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x55530000,0x53035555,0x54c00557, + 0xba9800aa,0x2aaaa60a,0x2a600aaa,0x0032e009,0x32205950,0x020bb883, + 0x3c881654,0x6440736e,0x09999953,0x80357510,0x209aca98,0x20aa00a9, + 0x2e014c29,0x0164c03f,0x1dd127dc,0x64c076c0,0xfffffc82,0x7ffe44ff, + 0x3ee03fff,0x904fffff,0x2bffffff,0xfffffffc,0xfffffb81,0x000fe80d, + 0x320bffd3,0x7fffc41f,0x3fa64eac,0x6c3f905f,0x1fc80ffd,0x40fffff9, + 0xefffffc8,0xfffffc81,0x440bf65f,0x88ffc47f,0x1ffe02ff,0x203fffa8, + 0x3f62fff8,0x3a0df504,0x567e40ff,0x5dc1aaaa,0x81ffdb9a,0xecabcffd, + 0x5e7ff444,0x55535dca,0xfd83fd55,0x0efc989c,0xea8007f4,0x84fa85fa, + 0xeffd98e9,0x217ebaa0,0x83fb04fa,0x266624fa,0x2fbf607f,0x360ffda9, + 0x3baabcef,0x3fc40bf6,0x1fe83fe2,0x7d413f60,0x3e03fc8d,0x41fea1ff, + 0x1ffd03fd,0x40001fc8,0x0f7dc4fe,0x8077ec08,0xf70ff400,0xfd17ea07, + 0x45f88001,0x11000ee8,0x3a22fc40,0x22ffe40e,0xff100ee8,0x3e03fe20, + 0x003ff32f,0x1fe205fb,0x20000404,0x9300cc18,0xf885fd05,0x9035100f, + 0xfb80003f,0x4007fe25,0x20000ffa,0x4cdf11fe,0x743f91bb,0x2fc4000f, + 0x80000bf2,0x417e45f8,0x3f23fda9,0x441fe202,0x2e5fb06f,0x05fb005f, + 0x80001fe2,0x00000098,0x5fa8bf70,0x003f9000,0x3ee2fc80,0x00ff6005, + 0x3ee3fd00,0x22ffff52,0x3603fa4f,0x265f884e,0x2a9d104f,0xbf101cfd, + 0xc99827cc,0x8809f34f,0x10bfa07f,0x007fd4ff,0x7f8817ec,0x02f7775c, + 0xeeb82fb8,0x440005ee,0x70bf60ff,0xf90bdddd,0xf3000335,0x001fe41d, + 0xe80003fd,0xdf11f91f,0x3fa5f823,0x44077ec0,0x4403fa5f,0xffeefcdf, + 0x3fa5f884,0x21dfff00,0x3fc400fe,0xf519ff50,0x177f447f,0x7c40bf60, + 0x3ffffe47,0xfc82fb80,0x80007fff,0x90ff13fd,0xf90fffff,0x205bffff, + 0xd85feee8,0x83fe002f,0x403cccc9,0x3eafb1fe,0x07f4fb03,0x90980bfb, + 0x7ffc405f,0x2603fea3,0x4cc05f90,0x2200bf20,0x7ffcc07f,0xffe981ff, + 0x02fd80be,0x3fc40ff1,0x2017e440,0xa80007f8,0x8809f76f,0xdccca87f, + 0xff982fff,0x3fa0cfff,0xa8ff1002,0x7406ffff,0x0beadd1f,0x361fd3ec, + 0x17e6005f,0xff07ff10,0x002fcc03,0x7c4017e6,0x7ffec407,0x3ffae03f, + 0x8817ec3f,0x81fe207f,0x403fffd9,0x2da807f8,0x07fa7fe0,0x6400ff10, + 0x6fd9807f,0x7c400bf6,0x37d4cc47,0x8bec7fa0,0x7f4dd04f,0x74005fd8, + 0x83fc400f,0x03fa02fd,0x2001fd00,0x3fa607f8,0x405ffc8c,0x3f65ffda, + 0x440ff102,0x273fa07f,0x03fc4009,0xfc80fffc,0x7f8806fd,0x007fe200, + 0x03fc97f4,0x7cc03fe0,0xfc8ff406,0x7c737fd0,0x01bf7fa5,0x33265f70, + 0xfd837c42,0xd915f702,0x997dc05b,0x0ff102cc,0x3fe617fc,0xb2ffa802, + 0x81fe205f,0x0bf307f8,0xe807f880,0xfff103ff,0x00ff1007,0xf9002fe8, + 0xe801bee7,0x80df303f,0x267f51fe,0x47f37ffd,0x002ffafe,0x27ff4bf1, + 0x17ec1be2,0xecfaafc4,0x3a5f881f,0x0ff104ff,0x2fe417e6,0x7f94fc80, + 0xf8817ea0,0x8009f707,0xff9807f8,0x401ff603,0x3e2007f8,0x23fd000f, + 0xf5002ff8,0x40df301f,0x11fa0ff9,0x1fd07ec1,0xfd005ff3,0x113eff21, + 0x20bf60df,0x17dc20fe,0xfbfc87f4,0x2e0ff104,0x00bf704f,0x827dcff2, + 0x1fe204fc,0x220037dc,0x03ff007f,0xf8801fec,0x09fb1007,0xff91bee0, + 0xefe83105,0x20bb7cc0,0x77d46fc8,0x7f43fc80,0x5c03ff50,0x9f39f33f, + 0x5fb06f88,0xfe883fb8,0xcf99fdc0,0x0ff104f9,0x3fa03fea,0x8ffcc013, + 0x7fcc1ff9,0x441fe201,0x3e2003ff,0x206fb807,0xf1000ffa,0xfb999b0f, + 0xb999b0bf,0xfd881fff,0x44feddff,0xecdeffe8,0xffbdfd6f,0x59df703f, + 0x1fd09fd7,0x7c40ffdc,0x3bfbbf66,0x7ec1be23,0x3e61be22,0xfb37c41e, + 0xf107dfdd,0x667ff40f,0x3bf66ffc,0x44ffedcd,0xffecdffc,0x703fc404, + 0x88013bff,0x3bfb207f,0x003ff500,0x7ff43fc4,0xfff02dff,0xea807dff, + 0x702cefff,0x25bffffd,0x00dfffeb,0x0b7fff66,0x3ff207f4,0xdd90fec0, + 0x37c47dfd,0x07f62fd8,0x6c357ff5,0x3fbbb21f,0xff99993e,0x7dc43999, + 0x2e0bffff,0x2dffffff,0x5dfffd70,0x3ff33320,0x7fd41ccc,0x666644ff, + 0x3e1cccff,0xffff983d,0xfcccc803,0x1331cccf,0x00026600,0x00cc0004, + 0x00100011,0x1dfb01fd,0x4f980fea,0x2fd837c4,0xfff707f5,0x980fea9f, + 0x3ffffe4f,0x3103ffff,0x00133001,0xffff8018,0x503fffff,0xffff87b9, + 0x003fffff,0x20019bd3,0xffffffff,0x0000003f,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x02ae6200, + 0xdddfd910,0xdd9501dd,0x0f223b9b,0x00014400,0x22179995,0x07ddb34e, + 0x23deedb8,0x0d4c02a8,0x55440055,0x4c40009a,0x551001ab,0x2aa35555, + 0xaaaaaaaa,0x5555530a,0x5554c555,0xaaaa8009,0x57510009,0x00aaa001, + 0xff5013ee,0xf101bfff,0xddffd9bf,0xfeeffd81,0x00df11ff,0x22001fe0, + 0x12fffffe,0xffdff5bf,0xddffd30b,0x103fe8ff,0x01fe21ff,0xffffffa8, + 0x7ffd401d,0x7e401eff,0xdf4fffff,0xdddddddd,0x3ffff21f,0x3ff67fff, + 0xf00dffff,0x07ffffff,0x1fffffe4,0x80bffe20,0xf702fff8,0x1dfd759f, + 0x27e43fd8,0x3fa06fe4,0x2000df11,0xdfd8007f,0x3fe21312,0x83ff30cf, + 0x26140dfe,0x23fd80ff,0x3ea007f8,0x3ffecbae,0x9339ff30,0xefef805f, + 0x021f1aaa,0x559f90f8,0x67ec5555,0x82ffecba,0xffecabff,0xa9adfd83, + 0x3fea03ff,0x0fffc04f,0x3a20ffc4,0x7c43fc3f,0x6c07fc47,0x000df11f, + 0x3fe001fe,0x213fe201,0x017f24fb,0x37cc4fd8,0x3bffffe2,0xb85fa81d, + 0x83fd80ff,0x2fdfd400,0x85dfd0f8,0xb007f90f,0x81ff705f,0x547fc87f, + 0x206f986f,0x4c07fafd,0x209f902c,0x21fe27fa,0x837dc7f8,0x00df11fd, + 0x3bffbba6,0xf301eeee,0x307f880d,0x000ff4bf,0x17f43ff1,0x3b733fe2, + 0x82fd43ff,0x00fe85fc,0x05f9fe80,0xf27dc41f,0x3600ff21,0xf8bfb02f, + 0x320ff887,0x105fb03f,0x0007faff,0x3fe01ff8,0xbf70bfa1,0x3fb04fc8, + 0x67ed5be2,0x7ffffcc1,0x302fffff,0x06f880bf,0x007fcdf3,0x2fd57ee0, + 0x7fd43fc4,0x7cc17ea1,0x98007f87,0x1f05f8cf,0x643e1f50,0x02fd803f, + 0x887f8ff3,0xb817ec7f,0xf74fa83f,0x03fc0009,0xcffa8bf6,0x7ec0ffda, + 0x3e23fb02,0x4ffeefce,0xf3001fe0,0x306f880b,0x001fe2df,0x407f57f4, + 0x49f907f8,0x03fe05fa,0x3f9000ff,0x203e0bf1,0x3f21f1f9,0x202fd803, + 0x321fe0ff,0xb81fec5f,0xf32fd84f,0x1be6000f,0x6ff47fb0,0xfc80dfff, + 0x3e23fd03,0x03fea4ff,0x7ffc03fc,0x7fffffff,0x27d41be2,0xf50001fd, + 0x1fe207ff,0xffeeb7d4,0xa8ffc1ee,0x2aaaaffa,0xeff8b7c0,0x4cc1f1ee, + 0x3f21f0fd,0x24eeeeee,0x87fe02fd,0xefecbbff,0x64077d40,0x3a3fc45f, + 0x6f98001f,0x4f99fe40,0x709f7002,0x0ffe23ff,0x03fc07fe,0x67fee664, + 0x1be24ccc,0x07f71fe4,0x881bf600,0x3ebf707f,0x742fffff,0xffffff1f, + 0x3ee01fff,0x3dddff13,0x06f7c43e,0x3ffff21f,0x0bf66fff,0x3ffe1fe8, + 0xfd00bfff,0x9fffb99f,0x27e45fa8,0x0ff30150,0x3df52fd8,0xa83fe200, + 0x0ff11fff,0x03fc0bf6,0xf1017e60,0x4c6fb88d,0x74040bff,0xeeeffeee, + 0x7f41fe21,0xff817ea3,0x333ff331,0x887f4033,0x3e21f05f,0x07f90f80, + 0x7fc05fb0,0x3f267fe1,0x3ffb200e,0x7ec3fccf,0xfe83fcc2,0x203fc40f, + 0xfffd11fe,0xfb05bfff,0x3fb9fd9f,0x17ec1be2,0x7cc007f8,0x677fc405, + 0xfc81fffc,0xe87ecdff,0xeeeffeee,0xf931fe21,0x882fd41f,0x003fc0ff, + 0x82fc4bf3,0x43e03a0f,0x2fd803fc,0x3fc1ff10,0x320013f2,0x267fe22f, + 0x441ff999,0x1ff82fff,0x7e41ff10,0x4fffeeed,0xfb3effc8,0x7ec1be23, + 0x9800ff02,0x7ffc405f,0x2e00dfff,0x405ffffe,0x3fe204fb,0x41efffee, + 0x0df705fa,0x7fe400ff,0x1f05ffff,0x7f90f804,0x2e05fb00,0x3e23fc6f, + 0x07f4000f,0xfffffff5,0x1dfb09ff,0x3ee09f90,0x7dc17ee5,0x23fb0207, + 0x05fb06f8,0xf98007fa,0x08b7c405,0x803be200,0x99dfc999,0x77fffc41, + 0x10bf503d,0x00ff07ff,0x3bbbbfe2,0x3ea1f05f,0x07f90f82,0xff105fb0, + 0x4fc87f85,0xfb0ff200,0xfb99999b,0xff88060d,0xfb07fd43,0x003fe205, + 0x06f88fec,0x13f605fb,0x4405f980,0x7f50006f,0xffffff80,0x1fe21fff, + 0x7545fa80,0x200ff06f,0x82fc43fb,0x1f03d30f,0x3f600ff2,0x7c2ffd42, + 0x400ff987,0x7fc46fd9,0x0007fe00,0x3fb3bfee,0xc837ec3f,0x47f6005f, + 0x05fb06f8,0x3733ffe6,0x880bf301,0x3f90006f,0xdfdaaa80,0x1fe20aaa, + 0xfeeffa80,0x7f6c0dff,0x3eeeeeef,0x9ff103fa,0x2003e599,0xddddf90f, + 0x777ecddd,0xff05fffe,0xddb13f60,0xfa819fff,0x0027ec05,0x1dfffea8, + 0xeeefff98,0x36000eff,0x360df11f,0x3ffaa02f,0x0bf301ff,0x30006f88, + 0x04fb8005,0xfa801fe2,0xf01cefff,0xffffffff,0x2217e69f,0xff5fffff, + 0xffffffff,0x3ffff21f,0x3ff67fff,0x3e01ceef,0x741ff307,0xfb01cdef, + 0x006fa807,0xeb880180,0x8002ceee,0x20df11ec,0x013002fd,0x74405f98, + 0x00000005,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0xaaaa8000,0xaaa98099,0x31aaaaaa,0x55555555,0x260aaa00, + 0x2055100a,0x2aa0d42a,0x0aaaaaaa,0x0aa60551,0x40335555,0x455302a9, + 0xaaaaaaa9,0x803551aa,0x02aa22a8,0x03530aa8,0x01551a88,0x0154c550, + 0x2aaaaa55,0x00aaaaaa,0x751002aa,0x80551015,0xfffffff8,0x3ffff20c, + 0xf95fffff,0x0fffffff,0xfb0fff70,0x7c1be205,0xfff0fe65,0x21ffffff, + 0x2ff886f8,0x3fffffe2,0x07fec0bf,0xfff737fc,0x2bffffff,0x2fe406fb, + 0x7fd413fa,0xf9807f50,0xfa809fb4,0x220fff26,0xffffff6f,0x501fffff, + 0x36203ffd,0x4c3fffff,0x57fc406f,0x2a5ffcba,0xdccccccc,0x555bf95f, + 0xff880555,0x102fd87f,0xfa93e0df,0x6fed5542,0x0df10aaa,0xaff887fd, + 0x6c5ffeba,0x3ffd43ff,0x99999993,0x81ffc9ff,0x7fcc0ff8,0xf517f441, + 0xf53f9809,0x323fc80f,0x56f886ff,0x55bfb555,0x7ff4c155,0x7bfd01ff, + 0x7cc3ff95,0x443fc406,0x3fd000ff,0x6c000ff2,0x2fd87fbf,0x9f10df10, + 0x9f700fdc,0x9fb1be20,0xff10ff10,0x3637f747,0xdf7007ee,0xfd80ffa8, + 0xfc8bf904,0x2a027cc5,0xf807fe3f,0x0bfbf21f,0x13ee0df1,0xff9dff98, + 0xbf905501,0x3e2037cc,0x3003fd07,0x001fe4df,0x43fc67d4,0x4df102fd, + 0xdaadfbaa,0x4fb81abf,0x2fdcdf10,0xbf907f88,0xf887e774,0xff8807dc, + 0x7cc4fe81,0x25ff100f,0x2fcc0ff9,0x4fd8bea0,0xbfc8df30,0xb837c46f, + 0xff0e404f,0x26f98003,0x3fc406f9,0x5fb007f8,0x22001fe4,0xd87f88ff, + 0x74df102f,0xffffffff,0x04fb85ff,0x03be6df1,0x6fa83fc4,0x7dcfe7ba, + 0x7ec00fd9,0x6c1ff304,0x47fd403f,0x45f883fe,0xfa8bee09,0xfc87f906, + 0x1be22fda,0x3e0027dc,0x37cc001f,0x7f880df3,0xf9804fc8,0x2001fe46, + 0xb0ff12fd,0x21be205f,0x701f61fb,0x23be209f,0x1fe201ff,0x3adf2fec, + 0x803f6dd6,0xa7ec06fa,0xdfb006f9,0xa9be20df,0xff07ee3f,0xfc81fd03, + 0x1be26faa,0x3e0027dc,0x2fdc001f,0xff880df3,0x002ffeee,0xcefc85fb, + 0xfa82cccc,0x3f61fe25,0xfeeeeeee,0x1ba0fc86,0x3e209f70,0x7c402fef, + 0x3e2ff887,0x367f5f95,0x03ff100f,0x2fd8ff88,0x03fff100,0x64df937c, + 0x2627ec1f,0xfd2fc86f,0x7dc1be23,0x00ffc004,0x7cc5fd10,0x7fffc406, + 0x4c02efff,0xffffc86f,0x0fe85fff,0x3ff61fe2,0x6fffffff,0x202fc7c8, + 0xfff104fb,0x9ff8805f,0x7c5ffdb9,0x321fff35,0x009fb01f,0x001bfbf2, + 0x37c01ffd,0x03f23fff,0x83fc8df5,0x22bf52fc,0x009f706f,0x36001ff8, + 0x2037cc5f,0x7fe447f8,0x320bf601,0x099999cf,0x1fe217e4,0x37c40bf6, + 0x7013e3ec,0x2bbe209f,0x3fe200ff,0x443fffff,0xfc97fa5f,0x2006fa81, + 0x2001fff8,0x3a05fffb,0x329f9f57,0x3a1ff80f,0x3e2fc80f,0xf706f89f, + 0x01ff8009,0xf981df90,0xc83fc406,0x20df305f,0xef9803fc,0x9ff99999, + 0x2205fb09,0xdffdd56f,0x20ddffdd,0x2df104fb,0xff100efb,0xf1013599, + 0x3f917dcb,0x4001ff88,0x3e6005fb,0xfd02ff9f,0x3edbe3f2,0x0df33fd8, + 0x8cfb8bf2,0x009f706f,0xfc801ff8,0x406f980e,0x0df507f8,0x1fe40ff6, + 0x7ffffdc0,0xb4ffffff,0x4dbe205f,0xfdccefcc,0x09f704cd,0x05fd9be2, + 0x3e600ff1,0x3617e405,0x4fb8004f,0x7dcffa00,0x5f8fd80f,0x2a0fb3f9, + 0x3207f76f,0x3e7fe22f,0x8009f706,0x77e401ff,0x880df300,0x309fb07f, + 0x01fe40ff,0x6666664c,0xfb2ccffc,0xf11be205,0x2e017d49,0x44df104f, + 0x07f883ff,0xfb809f30,0x0003bea2,0x7dc013ee,0x7e427f46,0xdd9f32fb, + 0x07f47fc0,0x67e42fc8,0x009f706f,0x3f201ff8,0x01be600e,0xffa88ff1, + 0x3203fd82,0x7c40003f,0xf102fd87,0x3ee4f88d,0x8827dc01,0x20ffcc6f, + 0x9f3007f8,0xff13fb80,0x13ee0003,0xf30bfe20,0x47efc83f,0x3f606eff, + 0x0bf206fc,0x2e0dfff1,0x0ffc004f,0x4c00efc8,0x77fc406f,0x983fffee, + 0x0ff200ff,0xb0ff1000,0x31be205f,0x6c07e47f,0xeeeffeee,0xff70df10, + 0xa803fc41,0xc9fdc04f,0xffffffff,0x013ee06f,0x37e417f6,0xff917fee, + 0x1fffd40b,0xff905f90,0xb013ee0d,0xdddffddd,0x3ffffe67,0xff36ffff, + 0x15dddddd,0x19dfffff,0xf900ff60,0x7f880007,0xdf102fd8,0x03f22fa8, + 0x3ffffffe,0x20df10ff,0x01fe26fd,0x3ee027d4,0xffffffb3,0x7dc0dfff, + 0x807fdc04,0x3fee4ff8,0x202ffcc2,0x3f200fff,0x706ff882,0xffff809f, + 0xf34fffff,0xffffffff,0x3ffffe6d,0x00003fff,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x80322000, + 0x8026200b,0x6c40001c,0xdb880000,0x2e01defe,0xe881cefd,0x6d43d905, + 0xdfd98cef,0x00054400,0x207bddb7,0x700cefdb,0xc83ddfdb,0x21bd505e, + 0xd52ed8bd,0xeeeed81b,0xaa986eee,0x2017540a,0x2e1d74e9,0x77441dfd, + 0x6c03b600,0x40df504f,0x7ff304fa,0x0ffe6000,0x7dc04fa8,0x42fffeef, + 0xfffeffe9,0xfd837c43,0x3bff7be2,0x7406fdef,0xffe9807f,0xefd87fee, + 0x7f42ffed,0x442feeef,0x17fc43ff,0xf3ffdb9f,0xfffe8bfd,0x7dc7ffff, + 0x3ea1ffff,0xfca7d404,0x1fffefc9,0x6fa81fec,0x32ebfe20,0x2a01ff9b, + 0x13fe604f,0x805ff700,0x20cc04fa,0x27f47fb8,0x6f887fea,0x36145fb0, + 0x405f90ff,0xdfe807fe,0x513f2140,0x417ee1ff,0x361ff980,0x5c77fc4f, + 0x200fd4ef,0xf70cc3fe,0x2e02fccb,0x45fdf93f,0x837d45fc,0x7fd403fd, + 0x403fffff,0x7f4404fa,0x1efc800d,0x0004fa80,0x82fd43fe,0x41be25fc, + 0x97ee02fd,0x072204fa,0xf100bf90,0x7e4ff20d,0xab7e4003,0xf52ff86f, + 0x32007ecf,0x37cc405f,0x9174cdf1,0x307ff23f,0x883ff0df,0x7fc400ff, + 0x402ffc9c,0xdfb004fa,0x03bf6201,0x00027d40,0x40bf23fb,0x41be26f8, + 0x8fea02fd,0xe80004f9,0x04fa801f,0x0bfee9f5,0x1ff9fd00,0xb27d4ff0, + 0x077d401f,0x37fff644,0x365fc9fe,0xd107f90f,0xfb89f90b,0x645fb804, + 0x7777645f,0x205eeeff,0x7f441ffb,0x5ccccc04,0x981999df,0x1ffffeec, + 0x13fc03fd,0x88bf60df,0xeeefeedb,0x266665fe,0x41999999,0xefb800ff, + 0x5feeeeee,0x0077fff6,0x7c0bffe2,0x0fd8fea7,0x3203ff30,0x746f99af, + 0x3f43ffa7,0xf88005f9,0x6c00ff47,0x363fcc2f,0xffffffff,0x8ffdc07f, + 0xff805ff8,0xffffffff,0x33bfee1f,0x3fd1ffcc,0x0df13fc0,0xcffe8bf6, + 0x2ccccefd,0x3ffffffe,0xff11ffff,0x3bbbf200,0x4c4eeeee,0x200efffd, + 0xff00ffe8,0x01fb1fd4,0x37c05fd1,0x98fd8df5,0x64df3fcf,0x2fd8002f, + 0x3f600df3,0x2a03fc42,0x3fe6004f,0x201ffd43,0xcefdcccc,0x3ff10ccc, + 0x0bf63fb0,0x0df137c4,0x52fd4bf6,0xcccc809f,0x0ccccccc,0x3ee003fe, + 0xfd510005,0x77f7ec0d,0x8fea7f80,0x04fd80fd,0x37ff6fec,0x3e3f27ee, + 0x017e4bf6,0x3fcafd40,0xf989fb00,0x8027d406,0xfd302ffb,0x027d4009, + 0x47fa0bf5,0x8bf704fc,0x97fc40ff,0x01bea2fc,0x01ff4000,0x00007fd4, + 0xdf701ff1,0xa9fe17f6,0xf703f63f,0x17b7100d,0x5ebfa877,0x7e49f5f9, + 0xd1ff0002,0x3bea001f,0xf500ff60,0x03df9009,0x800dfe88,0x1bea04fa, + 0x3e23ffb1,0x20ffcc1f,0x3ffa22ff,0x3fa27f72,0x0054001f,0x8102ffea, + 0x30000cfe,0x23ff30ff,0x53fc3ff8,0xf307ec7f,0x4c00001f,0xfbf32fdf, + 0x80017e47,0x2005fdfc,0xfffdfff8,0x1027d401,0x6c001dfb,0x27d400ef, + 0xfb9dff10,0x7fdc3fdf,0xb83ffdcd,0xfdefcdff,0x7dd9df12,0x403b99ff, + 0xffd806fd,0x7cc7ecdf,0x0eccbdff,0xffb999dd,0x4c3ff889,0xfa9fe1ff, + 0xfff83f63,0x32eeeeee,0x7ddddddd,0xff07ffc4,0x0017e45f,0x002fff98, + 0x37ffbbf6,0x8164c06f,0x70005fe8,0x27d403ff,0x37fffa60,0x7f541fc8, + 0x3aa01eff,0x22fb8dff,0xff90efeb,0x3ff403ff,0xffffea80,0xffffd885, + 0xffffb0ef,0x0bfb05df,0x53fc3ff2,0xff07ec7f,0x5fffffff,0x3bbbbba6, + 0x322ffc3e,0x00bf20ff,0x2006fe80,0x09fb06fb,0x001f4400,0x98807ea0, + 0x00011000,0x00088003,0x26002601,0x0088002c,0x4cc01310,0x00000009, + 0x00000000,0x00000000,0x4407ee00,0x3333264f,0x002ccccc,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x40000000, + 0x3fee0400,0x4fffffff,0x74400000,0x4039fb54,0x64400aa9,0xb9800001, + 0x000001bc,0x03372a00,0x4017bb93,0x16dc04c9,0x200e65c4,0x333100a8, + 0x81333333,0x4cc40bb9,0x09999999,0x26057700,0x257714c2,0x00000bb9, + 0x40000000,0xfeefcdf8,0x7fff444f,0x80be202f,0xc81d705c,0x40dfdcdf, + 0x3203645c,0xfd83320d,0x3f21ffff,0x6cc0ffff,0x3fe207ff,0x3fffea0f, + 0x41bf604f,0xfffffffa,0x0efb84ff,0x3ffffff2,0xfd802fff,0x11ff880d, + 0x54ffa3ff,0x000000ff,0x44000000,0x3fea3fff,0x3ee6ff60,0x8fc46a0f, + 0x717fa238,0x557641df,0x7ec5d88a,0x7d40ff23,0x1731be65,0x32049fb1, + 0x3f7fe23f,0x897ffc07,0x05fd10ff,0x5107fbf5,0x55555555,0x543be603, + 0xebbbbbbb,0x01fec02f,0xd1fe83fa,0x001fe67f,0x00000000,0x3e0ffe20, + 0xfc8bf31f,0x5cfd3fa3,0x57fa20ff,0x27e60efb,0x3f8afcfa,0x0fe83fa2, + 0x07fa0fe8,0x7ec0bf70,0x03fc45c2,0x1fd4bfea,0x75ba13ea,0x8800000f, + 0x05f90009,0x808004c4,0x3fccbf60,0x00000000,0x83fc4000,0xa87f52fd, + 0x77f7544f,0xefe880bf,0x6ab5c0ef,0xbf317299,0x8ff22fcc,0x7f4403fc, + 0x027ff542,0xff880ff1,0x4f987f70,0x44f98fdc,0x99999998,0x20000099, + 0x000002fc,0x37c4bf60,0x00000000,0x837c4000,0xb8bf32fd,0x1ffe883f, + 0x407ff440,0x21ddf54d,0x362fc86b,0x7ccdf12f,0x42ff4406,0x103ffdc9, + 0x25fc80ff,0x117e45f9,0x2a1fd8bf,0xffffffff,0x3200004f,0x0000002f, + 0x037c47f2,0x00000000,0xd837c400,0x223ff12f,0x37f220fe,0xf701dfdf, + 0x2ab90bff,0x88b90fae,0xd8df10ff,0x5407f62f,0x7f9804ff,0xd910ff10, + 0xbdfe81df,0x207e46fd,0x2eee66f8,0x02bbbbbb,0x00000000,0x00000000, + 0x00000000,0x17ec1be2,0x87ffdff7,0xfd33f2fe,0xfe8efb81,0xdb547d45, + 0x22fd89d4,0x137c42fd,0xbffb81df,0xff700999,0x3a61fe20,0xfffb102d, + 0xb827cc19,0x6d40003f,0x2ca8103d,0xffb80dcc,0x55534fff,0x00000555, + 0x00000000,0x7ec1be20,0x40e6e4c2,0x20c3f109,0xbfd10efb,0x99339dd8, + 0xf527dc1f,0xfb93ee0b,0x3ffffe25,0xffddb2ff,0xffffe85f,0x010001ff, + 0x00130062,0x2ffffdc0,0x7ffccbee,0x503fff11,0x3a799999,0x007fffff, + 0x00000000,0x0df10000,0x10000bf6,0x2077405f,0x3ba20fe8,0x741fda9b, + 0xfd007f46,0x999076c1,0x3ae39999,0xccb80bde,0x0000cccc,0x80000000, + 0x8dfd89fe,0xfff50fd8,0x00fffe65,0x333332e0,0x00000004,0x10000000, + 0x4cbf60df,0x3eeeeeee,0x04401510,0xdfb70088,0x00202019,0x00000101, + 0x00000000,0x7c400000,0x2ffffec5,0x1ffd1bfa,0x00000000,0x00000000, + 0x20df1000,0xdddd32fd,0x00007ddd,0x00000000,0x00000000,0x00000000, + 0x06a00000,0x80413bae,0x00000009,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +}; + +static signed short stb__consolas_24_latin1_x[224]={ 0,5,3,0,1,0,0,5,3,3,1,0,2,3, +4,1,1,1,1,1,0,2,1,1,1,1,4,2,1,1,2,3,0,0,1,1,1,2,2,0,1,2,2,1, +2,0,1,0,1,0,1,1,1,1,0,0,0,0,1,4,1,3,1,0,0,1,1,1,1,1,0,1,1,2, +1,2,2,1,1,1,1,1,2,2,0,1,0,0,0,0,1,1,5,2,0,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,5,1,1,1,0, +5,1,0,0,2,1,1,3,1,0,2,1,2,3,0,1,1,4,5,2,2,1,0,0,0,2,0,0,0,0, +0,0,-1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0, +0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, + }; +static signed short stb__consolas_24_latin1_y[224]={ 17,0,0,1,-1,0,0,0,-1,-1,0,4,13,9, +13,0,1,1,1,1,1,1,1,1,1,1,5,5,4,7,4,0,0,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,20,0,5,0,5,0,5,0,5,0,0, +0,0,0,5,5,5,5,5,5,5,1,5,5,5,5,5,5,0,-3,0,8,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,17,5,-1,1,2,1, +-3,0,0,1,1,5,9,9,0,1,0,2,0,0,0,5,0,8,17,0,1,5,0,0,0,5,-3,-3,-3,-3, +-3,-4,1,1,-3,-3,-3,-3,-3,-3,-3,-3,1,-3,-3,-3,-3,-3,-3,5,-1,-3,-3,-3,-3,-3,1,0,0,0, +0,0,0,-1,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,0,0,0,0,0,0,0, + }; +static unsigned short stb__consolas_24_latin1_w[224]={ 0,4,8,13,11,13,14,3,8,7,11,13,7,8, +5,11,12,11,11,11,13,10,11,11,11,11,5,7,10,11,10,8,14,14,11,11,12,10,10,12,11,10,9,12, +10,13,11,13,11,14,12,11,12,11,14,13,13,14,11,6,11,7,11,14,8,11,11,11,11,11,13,12,11,10, +10,11,10,12,11,12,11,11,11,10,12,11,13,13,13,13,11,10,3,10,13,12,12,12,12,12,12,12,12,12, +12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,4,10,11,12,13, +3,11,11,14,9,11,11,8,11,10,9,11,9,8,12,12,11,5,3,9,9,11,13,13,13,8,14,14,14,14, +14,14,14,11,12,12,12,12,12,12,12,12,13,12,13,13,13,13,13,11,13,12,12,12,12,14,11,11,12,12, +12,12,12,12,13,11,12,12,12,12,12,12,12,12,11,12,13,13,13,13,13,13,12,12,12,12,12,13,11,13, + }; +static unsigned short stb__consolas_24_latin1_h[224]={ 0,18,6,16,21,18,18,6,23,23,11,13,9,3, +5,20,17,16,16,17,16,17,17,16,17,16,13,17,14,7,14,18,22,16,16,17,16,16,16,17,16,16,17,16, +16,16,16,17,16,21,16,17,16,17,16,16,16,16,16,22,20,22,9,2,6,13,18,13,18,13,17,17,17,17, +22,17,17,12,12,13,17,17,12,13,17,13,12,12,12,17,12,22,25,22,5,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,17,21,16,15,16, +25,20,6,17,12,11,6,3,11,5,9,15,10,10,6,17,20,5,4,10,12,11,17,17,17,17,20,20,20,20, +20,21,16,20,20,20,20,20,20,20,20,20,16,20,21,21,21,21,21,11,21,21,21,21,21,20,16,18,18,18, +18,18,18,19,13,16,18,18,18,18,17,17,17,17,18,17,18,18,18,18,18,13,18,18,18,18,18,22,22,22, + }; +static unsigned short stb__consolas_24_latin1_s[224]={ 252,250,247,62,40,106,104,252,17,9,70, +48,159,238,215,91,183,221,233,12,36,1,222,13,152,220,247,223,37,189,26, +40,100,232,1,24,194,183,25,36,50,76,49,87,245,112,196,1,100,129,207, +164,208,176,181,167,153,138,126,34,146,26,177,26,201,62,119,127,171,139,65, +15,40,245,89,74,141,176,48,74,79,28,225,151,52,87,237,211,162,231,189, +41,1,64,201,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,252,247,157, +143,1,103,5,186,235,59,201,118,210,238,94,227,167,14,130,140,222,196,79, +221,252,149,60,106,86,113,127,201,198,213,66,118,103,52,155,67,133,173,14, +27,241,1,40,53,129,228,168,182,196,210,224,82,238,1,14,27,144,158,117, +94,172,185,198,211,131,81,99,91,133,159,146,120,234,209,210,188,224,100,236, +49,157,90,63,113,144,27,1,77,14,75,52,115, }; +static unsigned short stb__consolas_24_latin1_t[224]={ 13,49,156,125,27,49,70,1,1,1,156, +142,156,163,163,27,70,125,125,89,125,89,70,125,89,107,107,89,142,156,142, +70,1,107,125,89,107,107,125,89,125,125,89,125,125,125,125,107,125,1,107, +89,125,89,125,125,125,125,125,1,27,1,156,24,156,142,70,142,70,142,107, +107,107,89,1,89,89,142,156,142,107,107,142,142,107,142,142,142,142,89,142, +1,1,1,163,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,13,70,1, +107,142,107,1,27,156,89,142,156,156,163,156,163,156,142,156,156,156,70,27, +163,8,156,156,156,89,89,89,89,27,27,49,27,27,27,107,27,27,27,49, +49,27,49,49,49,107,27,1,1,1,1,1,156,1,27,27,27,1,27,107, +49,49,49,49,49,70,49,142,107,49,49,49,49,70,70,89,89,49,89,49, +70,70,70,70,142,70,70,70,70,70,1,1,1, }; +static unsigned short stb__consolas_24_latin1_a[224]={ 211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211, }; + +// Call this function with +// font: NULL or array length +// data: NULL or specified size +// height: STB_FONT_consolas_24_latin1_BITMAP_HEIGHT or STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 +// return value: spacing between lines +static void stb_font_consolas_24_latin1(stb_fontchar font[STB_FONT_consolas_24_latin1_NUM_CHARS], + unsigned char data[STB_FONT_consolas_24_latin1_BITMAP_HEIGHT][STB_FONT_consolas_24_latin1_BITMAP_WIDTH], + int height) +{ + int i,j; + if (data != 0) { + unsigned int *bits = stb__consolas_24_latin1_pixels; + unsigned int bitpack = *bits++, numbits = 32; + for (i=0; i < STB_FONT_consolas_24_latin1_BITMAP_WIDTH*height; ++i) + data[0][i] = 0; // zero entire bitmap + for (j=1; j < STB_FONT_consolas_24_latin1_BITMAP_HEIGHT-1; ++j) { + for (i=1; i < STB_FONT_consolas_24_latin1_BITMAP_WIDTH-1; ++i) { + unsigned int value; + if (numbits==0) bitpack = *bits++, numbits=32; + value = bitpack & 1; + bitpack >>= 1, --numbits; + if (value) { + if (numbits < 3) bitpack = *bits++, numbits = 32; + data[j][i] = (bitpack & 7) * 0x20 + 0x1f; + bitpack >>= 3, numbits -= 3; + } else { + data[j][i] = 0; + } + } + } + } + + // build font description + if (font != 0) { + float recip_width = 1.0f / STB_FONT_consolas_24_latin1_BITMAP_WIDTH; + float recip_height = 1.0f / height; + for (i=0; i < STB_FONT_consolas_24_latin1_NUM_CHARS; ++i) { + // pad characters so they bilerp from empty space around each character + font[i].s0 = (stb__consolas_24_latin1_s[i]) * recip_width; + font[i].t0 = (stb__consolas_24_latin1_t[i]) * recip_height; + font[i].s1 = (stb__consolas_24_latin1_s[i] + stb__consolas_24_latin1_w[i]) * recip_width; + font[i].t1 = (stb__consolas_24_latin1_t[i] + stb__consolas_24_latin1_h[i]) * recip_height; + font[i].x0 = stb__consolas_24_latin1_x[i]; + font[i].y0 = stb__consolas_24_latin1_y[i]; + font[i].x1 = stb__consolas_24_latin1_x[i] + stb__consolas_24_latin1_w[i]; + font[i].y1 = stb__consolas_24_latin1_y[i] + stb__consolas_24_latin1_h[i]; + font[i].advance_int = (stb__consolas_24_latin1_a[i]+8)>>4; + font[i].s0f = (stb__consolas_24_latin1_s[i] - 0.5f) * recip_width; + font[i].t0f = (stb__consolas_24_latin1_t[i] - 0.5f) * recip_height; + font[i].s1f = (stb__consolas_24_latin1_s[i] + stb__consolas_24_latin1_w[i] + 0.5f) * recip_width; + font[i].t1f = (stb__consolas_24_latin1_t[i] + stb__consolas_24_latin1_h[i] + 0.5f) * recip_height; + font[i].x0f = stb__consolas_24_latin1_x[i] - 0.5f; + font[i].y0f = stb__consolas_24_latin1_y[i] - 0.5f; + font[i].x1f = stb__consolas_24_latin1_x[i] + stb__consolas_24_latin1_w[i] + 0.5f; + font[i].y1f = stb__consolas_24_latin1_y[i] + stb__consolas_24_latin1_h[i] + 0.5f; + font[i].advance = stb__consolas_24_latin1_a[i]/16.0f; + } + } +} + +#ifndef STB_SOMEFONT_CREATE +#define STB_SOMEFONT_CREATE stb_font_consolas_24_latin1 +#define STB_SOMEFONT_BITMAP_WIDTH STB_FONT_consolas_24_latin1_BITMAP_WIDTH +#define STB_SOMEFONT_BITMAP_HEIGHT STB_FONT_consolas_24_latin1_BITMAP_HEIGHT +#define STB_SOMEFONT_BITMAP_HEIGHT_POW2 STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 +#define STB_SOMEFONT_FIRST_CHAR STB_FONT_consolas_24_latin1_FIRST_CHAR +#define STB_SOMEFONT_NUM_CHARS STB_FONT_consolas_24_latin1_NUM_CHARS +#define STB_SOMEFONT_LINE_SPACING STB_FONT_consolas_24_latin1_LINE_SPACING +#endif + diff --git a/textoverlay/textoverlay.cpp b/textoverlay/textoverlay.cpp new file mode 100644 index 00000000..2ec3cd2f --- /dev/null +++ b/textoverlay/textoverlay.cpp @@ -0,0 +1,1098 @@ +/* +* Vulkan Example - Text overlay rendering on-top of an existing scene using a separate render pass +* +* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de +* +* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#include +#include +#include + +#include +#include "vulkanexamplebase.h" +#include "../external/stb/stb_font_consolas_24_latin1.inl" + +#define VERTEX_BUFFER_BIND_ID 0 +#define ENABLE_VALIDATION false + +// Vertex layout for this example +std::vector vertexLayout = +{ + vkMeshLoader::VERTEX_LAYOUT_POSITION, + vkMeshLoader::VERTEX_LAYOUT_NORMAL, + vkMeshLoader::VERTEX_LAYOUT_UV, + vkMeshLoader::VERTEX_LAYOUT_COLOR, +}; + + +// Defines for the STB font used +// STB font files can be found at http://nothings.org/stb/font/ +#define STB_FONT_NAME stb_font_consolas_24_latin1 +#define STB_FONT_WIDTH STB_FONT_consolas_24_latin1_BITMAP_WIDTH +#define STB_FONT_HEIGHT STB_FONT_consolas_24_latin1_BITMAP_HEIGHT +#define STB_FIRST_CHAR STB_FONT_consolas_24_latin1_FIRST_CHAR +#define STB_NUM_CHARS STB_FONT_consolas_24_latin1_NUM_CHARS + +// Max. number of chars the text overlay buffer can hold +#define MAX_CHAR_COUNT 1024 + +// Mostly self-contained text overlay class +// todo : comment +class VulkanTextOverlay +{ +private: + VkPhysicalDevice physicalDevice; + VkDevice device; + VkPhysicalDeviceMemoryProperties deviceMemoryProperties; + VkFormat colorFormat; + VkFormat depthFormat; + VkExtent2D windowSize; + + VkSampler sampler; + VkImage image; + VkImageView view; + VkBuffer buffer; + // VkDeviceMemory memory; + VkDeviceMemory imageMemory; + VkDescriptorPool descriptorPool; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + VkPipelineLayout pipelineLayout; + VkPipelineCache pipelineCache; + VkPipeline pipeline; + VkCommandPool commandPool; + std::vector cmdBuffers; + std::vector frameBuffers; + + VkRenderPass renderPass; + + // Try to find appropriate memory type for a memory allocation + VkBool32 getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t *typeIndex) + { + for (int i = 0; i < 32; i++) { + if ((typeBits & 1) == 1) { + if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + { + *typeIndex = i; + return true; + } + } + typeBits >>= 1; + } + return false; + } + + // todo : duplicate code, android + VkPipelineShaderStageCreateInfo loadShader(std::string fileName, VkShaderStageFlagBits stage) + { + VkPipelineShaderStageCreateInfo shaderStage = {}; + shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaderStage.stage = stage; +#if defined(__ANDROID__) + shaderStage.module = vkTools::loadShader(androidApp->activity->assetManager, fileName.c_str(), device, stage); +#else + shaderStage.module = vkTools::loadShader(fileName.c_str(), device, stage); +#endif + shaderStage.pName = "main"; + assert(shaderStage.module != NULL); + //shaderModules.push_back(shaderStage.module); + return shaderStage; + } + +public: + + // todo : move to private! + stb_fontchar stbFontData[STB_NUM_CHARS]; + uint32_t numLetters; + VkDeviceMemory memory; + + // Pointer to mapped vertex buffer + glm::vec4 *mapped = nullptr; + + VulkanTextOverlay::VulkanTextOverlay( + VkPhysicalDevice physicalDevice, + VkDevice device, + std::vector framebuffers, + VkFormat colorformat, + VkFormat depthformat, + VkExtent2D windowsize) + { + this->physicalDevice = physicalDevice; + this->device = device; + this->colorFormat = colorformat; + this->depthFormat = depthformat; + this->windowSize = windowsize; + this->frameBuffers = framebuffers; + + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); + cmdBuffers.resize(framebuffers.size()); + prepareResources(); + prepareRenderPass(); + preparePipeline(); + } + + // Prepare all vulkan resources required to render the font + // The text overlay uses separate resources for descriptors (pool, sets, layouts), pipelines and command buffers + void prepareResources() + { + static unsigned char font24pixels[STB_FONT_HEIGHT][STB_FONT_WIDTH]; + STB_FONT_NAME(stbFontData, font24pixels, STB_FONT_HEIGHT); + + // Vertex buffer + + VkDeviceSize bufferSize = MAX_CHAR_COUNT * sizeof(glm::vec4); + + VkBufferCreateInfo bufferInfo = vkTools::initializers::bufferCreateInfo(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, bufferSize); + vkTools::checkResult(vkCreateBuffer(device, &bufferInfo, nullptr, &buffer)); + + VkMemoryRequirements memReqs; + VkMemoryAllocateInfo allocInfo = vkTools::initializers::memoryAllocateInfo(); + + vkGetBufferMemoryRequirements(device, buffer, &memReqs); + allocInfo.allocationSize = memReqs.size; + getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &allocInfo.memoryTypeIndex); + + vkTools::checkResult(vkAllocateMemory(device, &allocInfo, nullptr, &memory)); + vkTools::checkResult(vkBindBufferMemory(device, buffer, memory, 0)); + + VkImageCreateInfo imageInfo = vkTools::initializers::imageCreateInfo(); + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.format = VK_FORMAT_R8_UNORM; + imageInfo.extent.width = STB_FONT_WIDTH; + imageInfo.extent.height = STB_FONT_HEIGHT; + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + + vkTools::checkResult(vkCreateImage(device, &imageInfo, nullptr, &image)); + + allocInfo.allocationSize = STB_FONT_WIDTH * STB_NUM_CHARS; + + vkTools::checkResult(vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory)); + vkTools::checkResult(vkBindImageMemory(device, image, imageMemory, 0)); + + // todo : staging + + VkImageViewCreateInfo imageViewInfo = vkTools::initializers::imageViewCreateInfo(); + imageViewInfo.image = image; + imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewInfo.format = imageInfo.format; + imageViewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + imageViewInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + + vkTools::checkResult(vkCreateImageView(device, &imageViewInfo, nullptr, &view)); + + uint8_t *data; + vkTools::checkResult(vkMapMemory(device, imageMemory, 0, allocInfo.allocationSize, 0, (void **)&data)); + memcpy(data, &font24pixels[0][0], STB_FONT_WIDTH * STB_FONT_HEIGHT); + vkUnmapMemory(device, imageMemory); + + // Sampler + VkSamplerCreateInfo samplerInfo = vkTools::initializers::samplerCreateInfo(); + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.compareOp = VK_COMPARE_OP_NEVER; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + vkTools::checkResult(vkCreateSampler(device, &samplerInfo, nullptr, &sampler)); + + // Descriptor + // Font uses a separate descriptor pool + std::array poolSizes; + poolSizes[0] = vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1); + + VkDescriptorPoolCreateInfo descriptorPoolInfo = + vkTools::initializers::descriptorPoolCreateInfo( + poolSizes.size(), + poolSizes.data(), + 1); + + vkTools::checkResult(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Descriptor set layout + std::array setLayoutBindings; + setLayoutBindings[0] = vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = + vkTools::initializers::descriptorSetLayoutCreateInfo( + setLayoutBindings.data(), + setLayoutBindings.size()); + + vkTools::checkResult(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout)); + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutInfo = + vkTools::initializers::pipelineLayoutCreateInfo( + &descriptorSetLayout, + 1); + + vkTools::checkResult(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout)); + + // Descriptor set + VkDescriptorSetAllocateInfo descriptorSetAllocInfo = + vkTools::initializers::descriptorSetAllocateInfo( + descriptorPool, + &descriptorSetLayout, + 1); + + vkTools::checkResult(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSet)); + + VkDescriptorImageInfo texDescriptor = + vkTools::initializers::descriptorImageInfo( + sampler, + view, + VK_IMAGE_LAYOUT_GENERAL); + + std::array writeDescriptorSets; + writeDescriptorSets[0] = vkTools::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &texDescriptor); + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); + + // Command buffer + + // Pool + VkCommandPoolCreateInfo cmdPoolInfo = {}; + cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + cmdPoolInfo.queueFamilyIndex = 0; // todo : pass from example base / swap chain + cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + vkTools::checkResult(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &commandPool)); + + VkCommandBufferAllocateInfo cmdBufAllocateInfo = + vkTools::initializers::commandBufferAllocateInfo( + commandPool, + VK_COMMAND_BUFFER_LEVEL_PRIMARY, + (uint32_t)cmdBuffers.size()); + + vkTools::checkResult(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, cmdBuffers.data())); + + // Pipeline cache + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; + pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + vkTools::checkResult(vkCreatePipelineCache(device, &pipelineCacheCreateInfo, nullptr, &pipelineCache)); + } + + // Prepare a separate pipeline for the font rendering decoupled from the main application + void preparePipeline() + { + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = + vkTools::initializers::pipelineInputAssemblyStateCreateInfo( + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + 0, + VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterizationState = + vkTools::initializers::pipelineRasterizationStateCreateInfo( + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_CLOCKWISE, + 0); + + // Enable blending + VkPipelineColorBlendAttachmentState blendAttachmentState = + vkTools::initializers::pipelineColorBlendAttachmentState(0xf, VK_TRUE); + + blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo colorBlendState = + vkTools::initializers::pipelineColorBlendStateCreateInfo( + 1, + &blendAttachmentState); + + VkPipelineDepthStencilStateCreateInfo depthStencilState = + vkTools::initializers::pipelineDepthStencilStateCreateInfo( + VK_TRUE, + VK_TRUE, + VK_COMPARE_OP_LESS_OR_EQUAL); + + VkPipelineViewportStateCreateInfo viewportState = + vkTools::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + + VkPipelineMultisampleStateCreateInfo multisampleState = + vkTools::initializers::pipelineMultisampleStateCreateInfo( + VK_SAMPLE_COUNT_1_BIT, + 0); + + std::vector dynamicStateEnables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dynamicState = + vkTools::initializers::pipelineDynamicStateCreateInfo( + dynamicStateEnables.data(), + dynamicStateEnables.size(), + 0); + + std::array vertexBindings = {}; + vertexBindings[0] = vkTools::initializers::vertexInputBindingDescription(0, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX); + vertexBindings[1] = vkTools::initializers::vertexInputBindingDescription(1, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX); + + std::array vertexAttribs = {}; + vertexAttribs[0] = vkTools::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32_SFLOAT, 0); + vertexAttribs[1] = vkTools::initializers::vertexInputAttributeDescription(1, 1, VK_FORMAT_R32G32_SFLOAT, sizeof(glm::vec2)); + + VkPipelineVertexInputStateCreateInfo inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo(); + inputState.vertexBindingDescriptionCount = vertexBindings.size(); + inputState.pVertexBindingDescriptions = vertexBindings.data(); + inputState.vertexAttributeDescriptionCount = vertexAttribs.size(); + inputState.pVertexAttributeDescriptions = vertexAttribs.data(); + + std::array shaderStages; + + //shaderStages[0] = loadShader(getAssetPath() + "shaders/base/font.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + //shaderStages[1] = loadShader(getAssetPath() + "shaders/base/font.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + // todo : pass asset path + shaderStages[0] = loadShader("../data/shaders/base/font.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader("../data/shaders/base/font.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkGraphicsPipelineCreateInfo pipelineCreateInfo = + vkTools::initializers::pipelineCreateInfo( + pipelineLayout, + renderPass, + 0); + + pipelineCreateInfo.pVertexInputState = &inputState; + pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; + pipelineCreateInfo.pRasterizationState = &rasterizationState; + pipelineCreateInfo.pColorBlendState = &colorBlendState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDepthStencilState = &depthStencilState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.stageCount = shaderStages.size(); + pipelineCreateInfo.pStages = shaderStages.data(); + + vkTools::checkResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); + } + + // Prepare a separate render pass for rendering the text as an overlay + void prepareRenderPass() + { + VkAttachmentDescription attachments[2] = {}; + + // Color attachment + attachments[0].format = colorFormat; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + // Don't clear the framebuffer (like the renderpass from the example does) + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + // Depth attachment + attachments[1].format = depthFormat; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorReference = {}; + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference = {}; + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = NULL; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = NULL; + subpass.pDepthStencilAttachment = &depthReference; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = NULL; + + VkRenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.pNext = NULL; + renderPassInfo.attachmentCount = 2; + renderPassInfo.pAttachments = attachments; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 0; + renderPassInfo.pDependencies = NULL; + + vkTools::checkResult(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); + } + + // Map buffer + void beginTextUpdate() + { + vkTools::checkResult(vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, (void **)&mapped)); + numLetters = 0; + } + + // Add text to the current buffer + // todo : drop shadow? color attribute? + void addText(std::string text, float x, float y) + { + assert(mapped != nullptr); + +#define CHAR_WIDTH 2.0f * 0.75f / (float)windowSize.width - 1.0f +#define CHAR_HEIGHT 2.0f * 0.75f / (float)windowSize.height - 1.0f + + // Generate a uv mapped quad per char in the new text + for (auto letter : text) + { + stb_fontchar *charData = &stbFontData[(uint32_t)letter - STB_FIRST_CHAR]; + + mapped->x = (x + charData->x0) * CHAR_WIDTH; + mapped->y = (y + charData->y0) * CHAR_HEIGHT; + mapped->z = charData->s0; + mapped->w = charData->t0; + mapped++; + + mapped->x = (x + charData->x1) * CHAR_WIDTH; + mapped->y = (y + charData->y0) * CHAR_HEIGHT; + mapped->z = charData->s1; + mapped->w = charData->t0; + mapped++; + + mapped->x = (x + charData->x0) * CHAR_WIDTH; + mapped->y = (y + charData->y1) * CHAR_HEIGHT; + mapped->z = charData->s0; + mapped->w = charData->t1; + mapped++; + + mapped->x = (x + charData->x1) * CHAR_WIDTH; + mapped->y = (y + charData->y1) * CHAR_HEIGHT; + mapped->z = charData->s1; + mapped->w = charData->t1; + mapped++; + + x += charData->advance_int; + + numLetters++; + } + } + + // Unmap buffer and update command buffers + void endTextUpdate() + { + vkUnmapMemory(device, memory); + mapped = nullptr; + updateCommandBuffers(); + } + + // Needs to be called by the application + void updateCommandBuffers() + { + VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); + + VkClearValue clearValues[1]; + clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; + + VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderArea.extent = windowSize; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = clearValues; + + for (int32_t i = 0; i < cmdBuffers.size(); ++i) + { + renderPassBeginInfo.framebuffer = frameBuffers[i]; + + vkTools::checkResult(vkBeginCommandBuffer(cmdBuffers[i], &cmdBufInfo)); + + vkCmdBeginRenderPass(cmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vkTools::initializers::viewport((float)windowSize.width, (float)windowSize.height, 0.0f, 1.0f); + vkCmdSetViewport(cmdBuffers[i], 0, 1, &viewport); + + VkRect2D scissor = vkTools::initializers::rect2D(windowSize.width, windowSize.height, 0, 0); + vkCmdSetScissor(cmdBuffers[i], 0, 1, &scissor); + + vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindDescriptorSets(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); + + VkDeviceSize offsets = 0; + vkCmdBindVertexBuffers(cmdBuffers[i], 0, 1, &buffer, &offsets); + vkCmdBindVertexBuffers(cmdBuffers[i], 1, 1, &buffer, &offsets); + for (uint32_t j = 0; j < numLetters; j++) + { + vkCmdDraw(cmdBuffers[i], 4, 1, j * 4, 0); + } + + vkCmdEndRenderPass(cmdBuffers[i]); + + vkTools::checkResult(vkEndCommandBuffer(cmdBuffers[i])); + } + } + + // Submit the text command buffers to a queue + // Does a queue wait idle + void submit(VkQueue queue, uint32_t bufferindex) + { + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cmdBuffers[bufferindex]; + + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + vkTools::checkResult(vkQueueWaitIdle(queue)); + } + +}; + +class VulkanExample : public VulkanExampleBase +{ +public: + VulkanTextOverlay *textOverlay = nullptr; + + struct { + vkTools::VulkanTexture colorMap; + } textures; + + struct { + VkPipelineVertexInputStateCreateInfo inputState; + std::vector bindingDescriptions; + std::vector attributeDescriptions; + } vertices; + + struct { + vkMeshLoader::MeshBuffer example; + } meshes; + + struct { + vkTools::UniformData vsScene; + } uniformData; + + struct { + glm::mat4 projection; + glm::mat4 model; + glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); + } uboVS; + + struct { + VkPipeline solid; + } pipelines; + + VkPipelineLayout pipelineLayout; + VkDescriptorSet descriptorSet; + VkDescriptorSetLayout descriptorSetLayout; + + VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) + { + zoom = -7.5f; + zoomSpeed = 2.5f; + rotation = { -5.0f, -35.0f, 0.0f }; + //cameraPos = glm::vec3(4.5f, 0.33f, 0.0f); + title = "Vulkan Example - Text overlay"; + } + + ~VulkanExample() + { + // Clean up used Vulkan resources + // Note : Inherited destructor cleans up resources stored in base class + vkDestroyPipeline(device, pipelines.solid, nullptr); + + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + vkMeshLoader::freeMeshBufferResources(device, &meshes.example); + + textureLoader->destroyTexture(textures.colorMap); + + vkTools::destroyUniformData(device, &uniformData.vsScene); + + delete(textOverlay); + } + + void buildCommandBuffers() + { + VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); + + VkClearValue clearValues[3]; + + // Clear to a white background for higher contrast + clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } }; + clearValues[1].depthStencil = { 1.0f, 0 }; + + VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 3; + renderPassBeginInfo.pClearValues = clearValues; + + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { + // Set target frame buffer + renderPassBeginInfo.framebuffer = frameBuffers[i]; + + vkTools::checkResult(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + + VkRect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid); + + VkDeviceSize offsets[1] = { 0 }; + vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.example.vertices.buf, offsets); + vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.example.indices.buf, 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(drawCmdBuffers[i], meshes.example.indexCount, 1, 0, 0, 0); + + vkCmdEndRenderPass(drawCmdBuffers[i]); + + vkTools::checkResult(vkEndCommandBuffer(drawCmdBuffers[i])); + } + } + + // Update the text buffer displayed by the text overlay + void updateTextOverlay(void) + { + textOverlay->beginTextUpdate(); + + textOverlay->addText(title, 5.0f, 5.0f); + + std::stringstream ss; + ss << std::fixed << std::setprecision(2) << (frameTimer * 1000.0f) << "ms (" << lastFPS << " fps)"; + + textOverlay->addText(ss.str(), 5.0f, 30.0f); + + textOverlay->addText(deviceProperties.deviceName, 5.0f, 55.0f); + + // Put some text on top of object + // Project object position into screen space + glm::vec3 projected = glm::project(cameraPos, uboVS.model, uboVS.projection, glm::vec4(0, 0, (float)width, (float)height)); + textOverlay->addText("Look ma I'm a teapot!", projected.x, projected.y); + + textOverlay->endTextUpdate(); + } + + void draw() + { + // Get next image in the swap chain (back/front buffer) + vkTools::checkResult(swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer)); + + submitPostPresentBarrier(swapChain.buffers[currentBuffer].image); + + // Command buffer to be sumitted to the queue + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + + // Submit to queue + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + + // Submit text overlay to queue + textOverlay->submit(queue, currentBuffer); + + submitPrePresentBarrier(swapChain.buffers[currentBuffer].image); + + vkTools::checkResult(swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete)); + + vkTools::checkResult(vkQueueWaitIdle(queue)); + } + + void loadTextures() + { + textureLoader->loadTexture( + getAssetPath() + "models/voyager/voyager.ktx", + VK_FORMAT_BC3_UNORM_BLOCK, + &textures.colorMap); + } + + void loadMeshes() + { +// loadMesh(getAssetPath() + "models/lunarlander/lunarlander.dae", &meshes.example, vertexLayout, 5.0f); + loadMesh(getAssetPath() + "models/teapot.3ds", &meshes.example, vertexLayout, 0.15f); + } + + void setupVertexDescriptions() + { + // Binding description + vertices.bindingDescriptions.resize(1); + vertices.bindingDescriptions[0] = + vkTools::initializers::vertexInputBindingDescription( + VERTEX_BUFFER_BIND_ID, + vkMeshLoader::vertexSize(vertexLayout), + VK_VERTEX_INPUT_RATE_VERTEX); + + // Attribute descriptions + vertices.attributeDescriptions.resize(4); + // Location 0 : Position + vertices.attributeDescriptions[0] = + vkTools::initializers::vertexInputAttributeDescription( + VERTEX_BUFFER_BIND_ID, + 0, + VK_FORMAT_R32G32B32_SFLOAT, + 0); + // Location 1 : Normal + vertices.attributeDescriptions[1] = + vkTools::initializers::vertexInputAttributeDescription( + VERTEX_BUFFER_BIND_ID, + 1, + VK_FORMAT_R32G32B32_SFLOAT, + sizeof(float) * 3); + // Location 2 : Texture coordinates + vertices.attributeDescriptions[2] = + vkTools::initializers::vertexInputAttributeDescription( + VERTEX_BUFFER_BIND_ID, + 2, + VK_FORMAT_R32G32_SFLOAT, + sizeof(float) * 6); + // Location 3 : Color + vertices.attributeDescriptions[3] = + vkTools::initializers::vertexInputAttributeDescription( + VERTEX_BUFFER_BIND_ID, + 3, + VK_FORMAT_R32G32B32_SFLOAT, + sizeof(float) * 8); + + vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo(); + vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size(); + vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data(); + vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size(); + vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data(); + } + + void setupDescriptorPool() + { + // Example uses one ubo and one combined image sampler + std::vector poolSizes = + { + vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), + vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1), + }; + + VkDescriptorPoolCreateInfo descriptorPoolInfo = + vkTools::initializers::descriptorPoolCreateInfo( + poolSizes.size(), + poolSizes.data(), + 2); + + vkTools::checkResult(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + } + + void setupDescriptorSetLayout() + { + std::vector setLayoutBindings = + { + // Binding 0 : Vertex shader uniform buffer + vkTools::initializers::descriptorSetLayoutBinding( + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + VK_SHADER_STAGE_VERTEX_BIT, + 0), + // Binding 1 : Fragment shader combined sampler + vkTools::initializers::descriptorSetLayoutBinding( + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + VK_SHADER_STAGE_FRAGMENT_BIT, + 1), + }; + + VkDescriptorSetLayoutCreateInfo descriptorLayout = + vkTools::initializers::descriptorSetLayoutCreateInfo( + setLayoutBindings.data(), + setLayoutBindings.size()); + + vkTools::checkResult(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + + VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = + vkTools::initializers::pipelineLayoutCreateInfo( + &descriptorSetLayout, + 1); + + vkTools::checkResult(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + } + + void setupDescriptorSet() + { + VkDescriptorSetAllocateInfo allocInfo = + vkTools::initializers::descriptorSetAllocateInfo( + descriptorPool, + &descriptorSetLayout, + 1); + + vkTools::checkResult(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + + VkDescriptorImageInfo texDescriptor = + vkTools::initializers::descriptorImageInfo( + textures.colorMap.sampler, + textures.colorMap.view, + VK_IMAGE_LAYOUT_GENERAL); + + std::vector writeDescriptorSets = + { + // Binding 0 : Vertex shader uniform buffer + vkTools::initializers::writeDescriptorSet( + descriptorSet, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, + &uniformData.vsScene.descriptor), + // Binding 1 : Color map + vkTools::initializers::writeDescriptorSet( + descriptorSet, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 1, + &texDescriptor) + }; + + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); + } + + void preparePipelines() + { + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = + vkTools::initializers::pipelineInputAssemblyStateCreateInfo( + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + 0, + VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterizationState = + vkTools::initializers::pipelineRasterizationStateCreateInfo( + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_CLOCKWISE, + 0); + + VkPipelineColorBlendAttachmentState blendAttachmentState = + vkTools::initializers::pipelineColorBlendAttachmentState( + 0xf, + VK_FALSE); + + VkPipelineColorBlendStateCreateInfo colorBlendState = + vkTools::initializers::pipelineColorBlendStateCreateInfo( + 1, + &blendAttachmentState); + + VkPipelineDepthStencilStateCreateInfo depthStencilState = + vkTools::initializers::pipelineDepthStencilStateCreateInfo( + VK_TRUE, + VK_TRUE, + VK_COMPARE_OP_LESS_OR_EQUAL); + + VkPipelineViewportStateCreateInfo viewportState = + vkTools::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + + VkPipelineMultisampleStateCreateInfo multisampleState = + vkTools::initializers::pipelineMultisampleStateCreateInfo( + VK_SAMPLE_COUNT_1_BIT, + 0); + + std::vector dynamicStateEnables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + VkPipelineDynamicStateCreateInfo dynamicState = + vkTools::initializers::pipelineDynamicStateCreateInfo( + dynamicStateEnables.data(), + dynamicStateEnables.size(), + 0); + + // Solid rendering pipeline + // Load shaders + std::array shaderStages; + + shaderStages[0] = loadShader(getAssetPath() + "shaders/textoverlay/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/textoverlay/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkGraphicsPipelineCreateInfo pipelineCreateInfo = + vkTools::initializers::pipelineCreateInfo( + pipelineLayout, + renderPass, + 0); + + pipelineCreateInfo.pVertexInputState = &vertices.inputState; + pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; + pipelineCreateInfo.pRasterizationState = &rasterizationState; + pipelineCreateInfo.pColorBlendState = &colorBlendState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDepthStencilState = &depthStencilState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.stageCount = shaderStages.size(); + pipelineCreateInfo.pStages = shaderStages.data(); + + vkTools::checkResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid)); + } + + // Prepare and initialize uniform buffer containing shader uniforms + void prepareUniformBuffers() + { + // Vertex shader uniform buffer block + createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + sizeof(uboVS), + &uboVS, + &uniformData.vsScene.buffer, + &uniformData.vsScene.memory, + &uniformData.vsScene.descriptor); + + updateUniformBuffers(); + } + + void updateUniformBuffers() + { + // Vertex shader + glm::mat4 viewMatrix = glm::mat4(); + uboVS.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 256.0f); + viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, zoom)); + + float offset = 0.5f; + int uboIndex = 1; + uboVS.model = glm::mat4(); + uboVS.model = viewMatrix * glm::translate(uboVS.model, cameraPos); + uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + + uint8_t *pData; + vkTools::checkResult(vkMapMemory(device, uniformData.vsScene.memory, 0, sizeof(uboVS), 0, (void **)&pData)); + memcpy(pData, &uboVS, sizeof(uboVS)); + vkUnmapMemory(device, uniformData.vsScene.memory); + } + + void prepareTextOverlay() + { + VkExtent2D windowSize = { width, height }; + textOverlay = new VulkanTextOverlay( + physicalDevice, + device, + frameBuffers, + colorformat, + depthFormat, + windowSize + ); + updateTextOverlay(); + } + + void prepare() + { + VulkanExampleBase::prepare(); + loadTextures(); + loadMeshes(); + setupVertexDescriptions(); + prepareUniformBuffers(); + setupDescriptorSetLayout(); + preparePipelines(); + setupDescriptorPool(); + setupDescriptorSet(); + buildCommandBuffers(); + prepareTextOverlay(); + prepared = true; + } + + virtual void render() + { + if (!prepared) + return; + draw(); + // todo + if (frameCounter == 0) + { + updateTextOverlay(); + } + } + + virtual void viewChanged() + { + vkDeviceWaitIdle(device); + updateUniformBuffers(); + updateTextOverlay(); + } +}; + +VulkanExample *vulkanExample; + +#if defined(_WIN32) +LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (vulkanExample != NULL) + { + vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam); + } + return (DefWindowProc(hWnd, uMsg, wParam, lParam)); +} +#elif defined(__linux__) && !defined(__ANDROID__) +static void handleEvent(const xcb_generic_event_t *event) +{ + if (vulkanExample != NULL) + { + vulkanExample->handleEvent(event); + } +} +#endif + +// Main entry point +#if defined(_WIN32) +// Windows entry point +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow) +#elif defined(__ANDROID__) +// Android entry point +void android_main(android_app* state) +#elif defined(__linux__) +// Linux entry point +int main(const int argc, const char *argv[]) +#endif +{ +#if defined(__ANDROID__) + // Removing this may cause the compiler to omit the main entry point + // which would make the application crash at start + app_dummy(); +#endif + vulkanExample = new VulkanExample(); +#if defined(_WIN32) + vulkanExample->setupWindow(hInstance, WndProc); +#elif defined(__ANDROID__) + // Attach vulkan example to global android application state + state->userData = vulkanExample; + state->onAppCmd = VulkanExample::handleAppCommand; + state->onInputEvent = VulkanExample::handleAppInput; + vulkanExample->androidApp = state; +#elif defined(__linux__) + vulkanExample->setupWindow(); +#endif +#if !defined(__ANDROID__) + vulkanExample->initSwapchain(); + vulkanExample->prepare(); +#endif + vulkanExample->renderLoop(); + delete(vulkanExample); +#if !defined(__ANDROID__) + return 0; +#endif +} \ No newline at end of file diff --git a/textoverlay/textoverlay.vcxproj b/textoverlay/textoverlay.vcxproj new file mode 100644 index 00000000..31aae5c5 --- /dev/null +++ b/textoverlay/textoverlay.vcxproj @@ -0,0 +1,77 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + {9462DD15-5A1D-460A-B502-C9250D98D7A3} + textoverlay + 8.1 + + + + v140 + + + v140 + + + + + + + true + $(SolutionDir)\bin\ + $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName) + + + $(SolutionDir)\bin\ + $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName) + + + + ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_DEBUG;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX + MultiThreadedDebugDLL + Disabled + true + /FS %(AdditionalOptions) + + + ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies) + true + %(AdditionalLibraryDirectories) + Console + + + + + WIN32;NDEBUG;_WINDOWS;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories) + + + ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/textoverlay/textoverlay.vcxproj.filters b/textoverlay/textoverlay.vcxproj.filters new file mode 100644 index 00000000..08f37acd --- /dev/null +++ b/textoverlay/textoverlay.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/vulkanExamples.sln b/vulkanExamples.sln index d81c17ec..e85bbbe0 100644 --- a/vulkanExamples.sln +++ b/vulkanExamples.sln @@ -63,6 +63,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raytracing", "raytracing\ra EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multisampling", "multisampling\multisampling.vcxproj", "{34265930-5C09-447C-9C21-45FD933902FC}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textoverlay", "textoverlay\textoverlay.vcxproj", "{9462DD15-5A1D-460A-B502-C9250D98D7A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -189,6 +191,10 @@ Global {34265930-5C09-447C-9C21-45FD933902FC}.Debug|x64.Build.0 = Debug|x64 {34265930-5C09-447C-9C21-45FD933902FC}.Release|x64.ActiveCfg = Release|x64 {34265930-5C09-447C-9C21-45FD933902FC}.Release|x64.Build.0 = Release|x64 + {9462DD15-5A1D-460A-B502-C9250D98D7A3}.Debug|x64.ActiveCfg = Debug|x64 + {9462DD15-5A1D-460A-B502-C9250D98D7A3}.Debug|x64.Build.0 = Debug|x64 + {9462DD15-5A1D-460A-B502-C9250D98D7A3}.Release|x64.ActiveCfg = Release|x64 + {9462DD15-5A1D-460A-B502-C9250D98D7A3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE