uint8_t hyd_text_render(struct hyd_text *t, struct hyd_font *font) { t->uvs = calloc(strlen(t->text), sizeof(*t->uvs)); t->pos = calloc(strlen(t->text), sizeof(*t->pos)); t->font = font; char const *str = t->text; float x = 0, y = 0; uint32_t i = 0; while (*str) { if (*str >= 32 && *str < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *str-32, &x, &y, &q, 1); t->pos[i].x1 = q.x0; t->pos[i].y1 = q.y0; t->pos[i].x2 = q.x1; t->pos[i].y2 = q.y1; t->uvs[i].x1 = q.s0; t->uvs[i].y1 = q.t0; t->uvs[i].x2 = q.s1; t->uvs[i].y2 = q.t1; t->w += q.x1 - q.x0; if (t->h < (q.y1 - q.y0)) t->h = (q.y1 - q.y0); } ++i; ++str; } t->ready = 1; return 0; }
Console::Position Console::print(float x, float y, const char *text, bool measure) { unsigned passes; float xstart = x; Position ret = std::make_pair(-100.0f, 100.0f); if(!measure) { effect->SetTexture(textTex2DHandle, fontTex); effect->Begin(&passes, 0); effect->BeginPass(1); } while(*text) { if(*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, BMPSIZE, BMPSIZE, *text - 32, &x, &y, &q, 1); // 1=opengl, 0=old d3d if(!measure) { quad(q); } ret.first = max(ret.first, q.x0/width - 1.0f); ret.second = min(ret.second, -q.y0/height + 1.0f); } if(*text == '\n') { y += 38.0f; x = xstart; } ++text; } if(!measure) { effect->EndPass(); effect->End(); } return ret; }
int Font::write(unsigned int dx, const std::string& text, float r, float g, float b, float a) { FontEntry& e = entries[dx]; if(e.num_vertices) { vertices.erase(vertices.begin()+e.start_dx, vertices.begin()+(e.start_dx+e.num_vertices)); } e.col[0] = r, e.col[1] = g, e.col[2] = b, e.col[3] = a; // Create vertices e.w = 0; e.start_dx = vertices.size(); float x = 0; float y = 0; for(int i = 0; i < text.size(); ++i) { char c = text[i]; stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, w, h, c-32, &x, &y, &q, 1); CharVertex va(q.x0, q.y1, q.s0, q.t1, e.col); CharVertex vb(q.x1, q.y1, q.s1, q.t1, e.col); CharVertex vc(q.x1, q.y0, q.s1, q.t0, e.col); CharVertex vd(q.x0, q.y0, q.s0, q.t0, e.col); CHAR_TRI(va, vb, vc); CHAR_TRI(va, vc, vd); if(q.x1 > e.w) { e.w = q.x1; } } e.needs_update = true; e.num_vertices = vertices.size() - e.start_dx; flagChanged(); return e.num_vertices; }
void FontAsset::GetGlyphData (char c, float* x, float* y, BBox* verts, BBox* texCoords) const { stbtt_aligned_quad q; stbtt_GetBakedQuad((stbtt_bakedchar*)m_fontCData, m_textureWidth, m_textureHeight, c - 32, // Character index. x, y, // Pointer to x and y position in screen pixel space. &q, // Output quad to draw. 1 // OpenGL Mode ); if (verts != NULL) { verts->min.x = q.x0; verts->min.y = q.y0; verts->max.x = q.x1; verts->max.y = q.y1; } if (texCoords != NULL) { texCoords->min.x = q.s0; texCoords->min.y = q.t0; texCoords->max.x = q.s1; texCoords->max.y = q.t1; } }
Font * FontLoader::loadFont(const char * path, float fontSize, int textureWidth, int textureHeight) { Font * font = 0; unsigned char * data; int length; if (fileContent(path, &data, length)) { font = new Font(); font->size = fontSize; unsigned char * alpha = new unsigned char[textureWidth * textureHeight]; stbtt_bakedchar charDef[96]; stbtt_BakeFontBitmap(data, 0, fontSize, alpha, textureWidth, textureHeight, 32, 96, charDef); delete[] data; // Construct an luminance-alpha texture unsigned char * image = new unsigned char[textureWidth * textureHeight * 2]; for (int i = 0, len = textureWidth * textureHeight; i < len; ++i) { image[i * 2 + 0] = 255; image[i * 2 + 1] = alpha[i]; } // Create the texture Texture * texture = new Texture(); texture->images[0] = image; texture->width = textureWidth; texture->height = textureHeight; texture->format = LuminanceAlphaFormat; texture->imageDataType = UnsignedByteType; texture->type = Texture2D; font->texture = texture; // Copy glyph info for (int i = 0; i < 96; ++i) { float x = 0.0f, y = 0.0f; Font::Glyph & glyph = font->glyphs[i]; stbtt_aligned_quad quad; stbtt_GetBakedQuad(charDef, textureWidth, textureHeight, i, &x, &y, &quad, 1); float offsetX = quad.x0 < 0.0f ? -quad.x0 : 0.0f; glyph.topLeft = Vector2(quad.x0 + offsetX, quad.y0); glyph.bottomRight = Vector2(quad.x1 + offsetX, quad.y1); glyph.uvTopLeft = Vector2(quad.s0, quad.t0); glyph.uvBottomRight = Vector2(quad.s1, quad.t1); glyph.advance = x; } } return font; }
float Font::getStringWidth(const std::string& str, unsigned int start, unsigned int end) { float x = 0.0f; float y = 0.0f; float txt_w = 0.0f; stbtt_aligned_quad q; for(unsigned int i = start; i < end; ++i) { char c = str[i]; stbtt_GetBakedQuad(cdata, w, h, c-32, &x, &y, &q, 1); txt_w += (q.x1 - q.x0); } return txt_w; }
float width(const char * text) { float x=0, y=0; for(; *text; ++text) { if (*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1); } } return x; }
void typo_get_char(int codepoint, float *x, float *y, float verts[2*3*2*2]) { int i = 0; stbtt_aligned_quad q; stbtt_bakedchar* bc = chardata+(codepoint-32); float fixup = -(bc->yoff*2 + (bc->y1 - bc->y0)); stbtt_GetBakedQuad(chardata, typo_width,typo_height, codepoint-32, x,y,&q,1); if(codepoint < 32 || codepoint > 32+96) { codepoint = '.'; } // We have bottom-left origin, stbtt assumes top-left, fixup. verts[i++] = q.x0; verts[i++] = q.y0 + fixup; verts[i++] = q.s0; verts[i++] = q.t1; verts[i++] = q.x1; verts[i++] = q.y0 + fixup; verts[i++] = q.s1; verts[i++] = q.t1; verts[i++] = q.x1; verts[i++] = q.y1 + fixup; verts[i++] = q.s1; verts[i++] = q.t0; verts[i++] = q.x0; verts[i++] = q.y0 + fixup; verts[i++] = q.s0; verts[i++] = q.t1; verts[i++] = q.x1; verts[i++] = q.y1 + fixup; verts[i++] = q.s1; verts[i++] = q.t0; verts[i++] = q.x0; verts[i++] = q.y1 + fixup; verts[i++] = q.s0; verts[i++] = q.t0; }
void TTFFontAsset::GetGlyphData(char c, float* x, float* y, Rect& verts, Rect& texCoords) const { stbtt_aligned_quad q; stbtt_GetBakedQuad((stbtt_bakedchar *)fontCData, textureWidth, textureHeight, c-32, x, y, &q, 1);//1=opengl,0=old d3d verts.topLeft.x = q.x0; verts.topLeft.y = q.y0; verts.bottomRight.x = q.x1; verts.bottomRight.y = q.y1; texCoords.topLeft.x = q.s0; texCoords.topLeft.y = q.t0; texCoords.bottomRight.x = q.s1; texCoords.bottomRight.y = q.t1; }
static int fill_vertex_buffer(layer_data *data, vertex *vertices, int index) { char str[1024]; sprintf(str, "Vulkan Overlay Example\nWSI Image Index: %d\nFrame: " "%d\nCmdBuffers: %d", index, data->frame++, data->cmdBuffersThisFrame); float x = 0; float y = 16; vertex *v = vertices; for (char const *p = str; *p; p++) { if (*p == '\n') { y += 16; x = 0; } else { stbtt_aligned_quad q; stbtt_GetBakedQuad(data->glyphs, FONT_ATLAS_SIZE, FONT_ATLAS_SIZE, *p - 32, &x, &y, &q, 1); v[0].x = q.x0; v[0].y = q.y0; v[0].u = q.s0; v[0].v = q.t0; v[1].x = q.x1; v[1].y = q.y0; v[1].u = q.s1; v[1].v = q.t0; v[2].x = q.x0; v[2].y = q.y1; v[2].u = q.s0; v[2].v = q.t1; v[3] = v[1]; v[4].x = q.x1; v[4].y = q.y1; v[4].u = q.s1; v[4].v = q.t1; v[5] = v[2]; v += 6; } } return (int)(v - vertices); }
void draw_string_goth(float x, float y, const std::string str) { // assume orthographic projection with units = screen pixels, origin at top left glBindTexture(GL_TEXTURE_2D, goth_tex); glBegin(GL_QUADS); const char *text = str.c_str(); while (*text) { if (*text >= 32 && (unsigned char)(*text) < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata_goth, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } ++text; } glEnd(); }
void Font_p::GetTextExtent(const std::string& _text, float & _x, float &_y) { float maxX = 0; float maxY = 0; _x = 0; _y = this->fontHeight; float xStart = 0; int textLen = (int)_text.size(); for (int i = 0; i < textLen; i++) { unsigned char ch = _text[i]; if (ch == '\n') { _x = xStart; _y += this->fontHeight; continue; } if (ch < 32 || ch > 128) ch = '?'; stbtt_aligned_quad q; stbtt_GetBakedQuad(this->cdata, 512, 512, ch - 32, // position of character in font &_x, // current position &_y, &q, // resulted quad 1); // '1' for tex coords for opengl ('0' for d3d) if (_x > maxX) maxX = _x; if (_y > maxY) maxY = _y ; } _x = maxX; _y = maxY; }
uint32_t font_bake_string(font_t font, const char* string, float xstart, float ystart, vector_t* outVertices) { FOUNDATION_ASSERT((uint32_t)font <= array_size(s_fontCtx.fonts)); FOUNDATION_ASSERT(string != nullptr && outVertices != nullptr); font_data_t& fontData = s_fontCtx.fonts[font]; const uint32_t entryLen = string_length(string); float x = 0; float y = 0; for(uint32_t c=0; c < entryLen; ++c) { const char character = string[c]; const uint32_t charStart = c*4; if(character < 32 && character >= 128) continue; stbtt_aligned_quad q; stbtt_GetBakedQuad( fontData.cdata, MINT_FONT_BITMAPSIZE, MINT_FONT_BITMAPSIZE, (int)character - 32, &x, &y, &q, 1 ); outVertices[charStart+0] = vector(xstart + q.x0, ystart - q.y0, q.s0, q.t0); outVertices[charStart+1] = vector(xstart + q.x1, ystart - q.y0, q.s1, q.t0); outVertices[charStart+2] = vector(xstart + q.x1, ystart - q.y1, q.s1, q.t1); outVertices[charStart+3] = vector(xstart + q.x0, ystart - q.y1, q.s0, q.t1); /*for(uint32_t d=0; d < 4; ++d) log_infof("Vert %d Pos: %f,%f UV: %f,%f", charStart+d, vector_x(outVertices[charStart+d]), vector_y(outVertices[charStart+d]), vector_z(outVertices[charStart+d]), vector_w(outVertices[c+d]));*/ } return entryLen; }
void Font::RenderAsMesh(const char *s, Mesh *m) { m->SetVertexAttributes(VertexFormat::AttributeFlag_TexCoord); m->SetIndexAttributes(3, 2); m->SetMeshFlag(Mesh::MeshFlag_HasTranslucency); float penX = 0.0f; float penY = 0.0f; struct V { float pos[3]; float uv[2]; }; stbtt_aligned_quad q; const uint32 len = strlen(s); for(uint32 i = 0; i < len; i++) { if(s[i] < MIN_CHAR_CODE || s[i] > MAX_CHAR_CODE) { continue; } stbtt_GetBakedQuad(bakedChars, textureWidth, textureHeight, s[i] - MIN_CHAR_CODE, &penX, &penY, &q, 1); V v[4] = { {q.x0, q.y0, 0, q.s0, q.t0}, {q.x0, q.y1, 0, q.s0, q.t1}, {q.x1, q.y1, 0, q.s1, q.t1}, {q.x1, q.y0, 0, q.s1, q.t0}, }; m->PushVertexData(sizeof(v), (char *)v); uint16 base = i*4; uint16 f[6] = {base, (uint16)(base+1), (uint16)(base+2), base, (uint16)(base+2), (uint16)(base+3)}; m->PushIndexData(sizeof(f), (char *)f); } m->Upload(); }
void print(float x, float y, const char * text) { glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_QUADS); for(; *text; ++text) { if (*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1); glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } } glEnd(); glPopAttrib(); }
void D3D9DebugManager::RenderTextInternal(float x, float y, const char *text) { if(char *t = strchr((char *)text, '\n')) { *t = 0; RenderTextInternal(x, y, text); RenderTextInternal(x, y + 1.0f, t + 1); *t = '\n'; return; } if(strlen(text) == 0) return; RDCASSERT(strlen(text) < FONT_MAX_CHARS); // transforms float width = (float)m_width; float height = (float)m_height; float nearPlane = 0.001f; float farPlane = 1.f; D3DMATRIX identity = {1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f}; D3DMATRIX ortho = {2.f / width, 0.f, 0.f, 0.f, 0.f, -(2.f / height), 0.f, 0.f, 0.f, 0.f, 1.f / (farPlane - nearPlane), 0.f, 0.f, 0.f, nearPlane / (nearPlane - farPlane), 1.f}; HRESULT res = S_OK; res |= m_WrappedDevice->SetTransform(D3DTS_PROJECTION, &ortho); res |= m_WrappedDevice->SetTransform(D3DTS_WORLD, &identity); res |= m_WrappedDevice->SetTransform(D3DTS_VIEW, &identity); // enable fixed function pipeline res |= m_WrappedDevice->SetVertexShader(NULL); res |= m_WrappedDevice->SetPixelShader(NULL); // default render states res |= m_WrappedDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_LIGHTING, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_CLIPPING, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F); res |= m_WrappedDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); res |= m_WrappedDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); res |= m_WrappedDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); res |= m_WrappedDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); res |= m_WrappedDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); // sampler states res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR /*D3DTEXF_POINT*/); res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR /*D3DTEXF_POINT*/); res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR /*D3DTEXF_POINT*/); res |= m_WrappedDevice->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, 0); // texture stage states res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_COLORARG0, D3DTA_CURRENT); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_ALPHAARG0, D3DTA_CURRENT); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_RESULTARG, D3DTA_CURRENT); res |= m_WrappedDevice->SetTextureStageState(0, D3DTSS_CONSTANT, 0xffffffff); res |= m_WrappedDevice->SetFVF(m_fvf); res |= m_WrappedDevice->SetTexture(0, m_Font.Tex); for(uint32_t stage = 1; stage < 8; stage++) { res |= m_WrappedDevice->SetTexture(stage, NULL); } struct Vertex { float pos[3]; float uv[2]; Vertex() {} Vertex(float posx, float posy, float posz, float texu, float texv) { pos[0] = posx; pos[1] = posy; pos[2] = posz; uv[0] = texu; uv[1] = texv; } }; struct Quad { Vertex vertices[6]; Quad() {} Quad(float x0, float y0, float z, float s0, float t0, float x1, float y1, float s1, float t1) { vertices[0] = Vertex(x0, y0, z, s0, t0); vertices[1] = Vertex(x1, y0, z, s1, t0); vertices[2] = Vertex(x0, y1, z, s0, t1); vertices[3] = Vertex(x1, y0, z, s1, t0); vertices[4] = Vertex(x1, y1, z, s1, t1); vertices[5] = Vertex(x0, y1, z, s0, t1); } }; Quad *quads = NULL; Quad background; UINT triangleCount = 0; { UINT quadCount = (UINT)strlen(text); // calculate string length triangleCount = quadCount * 2; // create text VB quads = new Quad[quadCount]; float textStartingPositionX = (-width / 2.f) + (x * m_Font.charData->xadvance); float textStartingPositionY = (-height / 2.f) + ((y + 1.f) * m_Font.maxHeight); float textPositionX = textStartingPositionX; float textPositionY = textStartingPositionY; for(UINT i = 0; i < quadCount; ++i) { char glyphIndex = text[i] - (' ' + 1); if(glyphIndex < 0) { float currentX = textPositionX; textPositionX += m_Font.charData->xadvance; quads[i] = Quad(currentX, textPositionY - m_Font.maxHeight, 0.5f, 0.f, 0.f, textPositionX, textPositionY, 0.f, 0.f); } else { stbtt_aligned_quad quad; stbtt_GetBakedQuad(m_Font.charData, 256, 128, glyphIndex, &textPositionX, &textPositionY, &quad, 0); quads[i] = Quad(quad.x0, quad.y0, 0.5f, quad.s0, quad.t0, quad.x1, quad.y1, quad.s1, quad.t1); } } background = Quad(textStartingPositionX, textStartingPositionY - m_Font.maxHeight, 0.6f, 0.f, 0.f, textPositionX, textPositionY + 3.f, 0.f, 0.f); } if(quads != NULL) { // overlay render states res |= m_WrappedDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); res |= m_WrappedDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, &background, sizeof(Vertex)); //// overlay render states res |= m_WrappedDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); res |= m_WrappedDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); res |= m_WrappedDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); res |= m_WrappedDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, triangleCount, &quads[0], sizeof(Vertex)); delete[] quads; } }
void Ibex::TextRenderer::precompileText(float x, float y, const std::vector<std::string> &lines, const std::vector<bool> &highlighted, int maxChars) { if(!initialized) { initialized = true; loadProgram(); initializeFont(); } checkForErrors(); vertices.clear(); indices.clear(); minX = minY = INT_MAX; maxX = maxY = INT_MIN; // assume orthographic projection with units = screen pixels, origin at top left int index = 0; int lineNum = (int)lines.size()-1; //for(std::string line : lines) { for(int i = 0; i < lines.size(); ++i) { std::string line = lines[i]; if(maxChars > 0 && line.length() > maxChars) { line.resize(maxChars); } const GLfloat *color = (highlighted.size() > i && highlighted[i]) ? highlightedTextColor : textColor; x = 0; y = -lineNum * (ascent-descent+lineGap)*scale; unsigned char *text = (unsigned char *)line.data(); while (*text) { if (*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 1024,256, *text-32, &x,&y,&q,1); // bottom right triangle vertices.push_back(q.x0); vertices.push_back((baseline-q.y0)); vertices.push_back(0); vertices.push_back(q.s0); vertices.push_back(q.t0); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); vertices.push_back(q.x1); vertices.push_back((baseline-q.y0)); vertices.push_back(0); vertices.push_back(q.s1); vertices.push_back(q.t0); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); vertices.push_back(q.x1); vertices.push_back((baseline-q.y1)); vertices.push_back(0); vertices.push_back(q.s1); vertices.push_back(q.t1); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); // top left triangle vertices.push_back(q.x0); vertices.push_back((baseline-q.y0)); vertices.push_back(0); vertices.push_back(q.s0); vertices.push_back(q.t0); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); vertices.push_back(q.x1); vertices.push_back((baseline-q.y1)); vertices.push_back(0); vertices.push_back(q.s1); vertices.push_back(q.t1); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); vertices.push_back(q.x0); vertices.push_back((baseline-q.y1)); vertices.push_back(0); vertices.push_back(q.s0); vertices.push_back(q.t1); vertices.push_back(color[0]); vertices.push_back(color[1]); vertices.push_back(color[2]); vertices.push_back(color[3]); minX = std::min(minX,std::min(q.x0,q.x1)); maxX = std::max(maxX,std::max(q.x0,q.x1)); minY = std::min(minY,std::min(baseline-q.y0,baseline-q.y1)+y); maxY = std::max(maxY,std::max(baseline-q.y0,baseline-q.y1)); for(int i = 0; i < 6; ++i) { indices.push_back(index++); } } ++text; } --lineNum; if(minX > maxX) std::swap(minX,maxX); if(minY > maxY) std::swap(minY,maxY); } if(vaoTextRenderer == 0) glGenVertexArrays(1,&vaoTextRenderer); if(!checkForErrors()) { exit(1); } glBindVertexArray(vaoTextRenderer); if(vboTextVertices == 0) glGenBuffers(1, &vboTextVertices); glBindBuffer(GL_ARRAY_BUFFER, vboTextVertices); glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW); if(!checkForErrors()) { exit(1); } glEnableVertexAttribArray(IbexTextAttribLocations[0]); glVertexAttribPointer(IbexTextAttribLocations[0], 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*9, 0); glEnableVertexAttribArray(IbexTextAttribLocations[1]); glVertexAttribPointer(IbexTextAttribLocations[1], 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*9, (GLvoid*) (sizeof(GLfloat)*3)); glEnableVertexAttribArray(IbexTextAttribLocations[2]); glVertexAttribPointer(IbexTextAttribLocations[2], 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*9, (GLvoid*) (sizeof(GLfloat)*5)); if(!checkForErrors()) { exit(1); } if(vboTextIndices == 0) glGenBuffers(1, &vboTextIndices); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboTextIndices); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLuint), indices.data(), GL_STATIC_DRAW); if(!checkForErrors()) { exit(1); } glBindVertexArray(0); ////////////////////////////////////////////////////////////////////////////// static GLfloat IbexDisplayFlatVertices[] = { -1.0, -1.0, 0.0, 0, 1, 1.0, -1.0, 0.0, 1, 1, 1.0, 1.0, 0.0, 1, 0, -1.0, 1.0, 0.0, 0, 0 }; static GLushort IbexDisplayFlatIndices[] = { 0, 2, 1, 0, 3, 2 }; if(vaoTextTextureRenderer == 0) { if(vaoTextTextureRenderer == 0) glGenVertexArrays(1,&vaoTextTextureRenderer); if(!checkForErrors()) { exit(1); } glBindVertexArray(vaoTextTextureRenderer); if(vboTextTextureVertices == 0) glGenBuffers(1, &vboTextTextureVertices); glBindBuffer(GL_ARRAY_BUFFER, vboTextTextureVertices); glBufferData(GL_ARRAY_BUFFER, sizeof(IbexDisplayFlatVertices), IbexDisplayFlatVertices, GL_STATIC_DRAW); if(!checkForErrors()) { exit(1); } glEnableVertexAttribArray(IbexDisplayFlatAttribLocations[0]); glVertexAttribPointer(IbexDisplayFlatAttribLocations[0], 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*5, 0); glEnableVertexAttribArray(IbexDisplayFlatAttribLocations[2]); glVertexAttribPointer(IbexDisplayFlatAttribLocations[2], 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*5, (GLvoid*) (sizeof(GLfloat) * 3)); if(!checkForErrors()) { exit(1); } if(vboTextTextureIndices == 0) glGenBuffers(1, &vboTextTextureIndices); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboTextTextureIndices); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IbexDisplayFlatIndices), IbexDisplayFlatIndices, GL_STATIC_DRAW); if(!checkForErrors()) { exit(1); } glBindVertexArray(0); } }