public void DrawString(float x, float y, string text) { GL.ActiveTexture(TextureUnit.Texture0); shader.Activate(); GL.PushAttrib(AttribMask.AllAttribBits); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.AlphaTest); GL.AlphaFunc(AlphaFunction.Always, 0.0f); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Uniform1(scaleXLoc, scaleX); GL.Uniform1(scaleYLoc, scaleY); for (int i = textColors.Length - 1; i >= 0; i--) { float mx = x + (i * 2.0f); float my = y + (i * 2.0f); GL.Uniform4(textColorLoc, textColors[i]); GL.Uniform1(textPosYLoc, my); float cx = mx; for (int j = 0; j < text.Length; j++) { char c = text[j]; if (c == '\n' || (c == '\r' && text[j + 1] == '\n')) { cx = mx; my += charHeight; GL.Uniform1(textPosYLoc, my); if (c == '\r' && text[j + 1] == '\n') { j++; } continue; } GL.Uniform1(textPosXLoc, cx); if (!characters.ContainsKey(c)) { continue; } FontCharacter fontChar = characters[c]; if (c != ' ') { if (!vaoWidthMap.ContainsKey(fontChar.Width)) { continue; } int vaoHandle = vaoWidthMap[fontChar.Width]; GL.BindTexture(TextureTarget.Texture2D, fontChar.TextureHandle); GL.BindVertexArray(vaoHandle); GL.DrawArrays(PrimitiveType.Triangles, 0, 6); GL.BindVertexArray(0); } cx += fontChar.Width; } } GL.PopAttrib(); GL.UseProgram(0); }
private void Load(FontFamily family) { SetScreenSize(640, 480); System.Drawing.Font font = new System.Drawing.Font(family, size, FontStyle.Bold, GraphicsUnit.Pixel); charHeight = (float)NextPowerOfTwo((double)font.Size); for (char c = startChar; c < endChar; c++) { SizeF charSize; using (Graphics g = Graphics.FromImage(new Bitmap(1, 1))) { g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; charSize = g.MeasureString(c.ToString(), font, 256, StringFormat.GenericTypographic); if (charSize.Width == 0) { charSize = g.MeasureString(c.ToString(), font); } } int charTextureWidth = (int)NextPowerOfTwo(charSize.Width); Bitmap charTextureImage = new Bitmap(charTextureWidth, (int)charHeight); using (Graphics g = Graphics.FromImage(charTextureImage)) { g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; g.DrawString(c.ToString(), font, Brushes.White, PointF.Empty, StringFormat.GenericTypographic); } //charTextureImage.Save(@"C:\Temp\glsl\" + ((int)c).ToString() + ".png"); FontCharacter fontChar = new FontCharacter((float)Math.Round(charSize.Width, 1), charTextureImage); if (!vaoWidthMap.ContainsKey(fontChar.Width)) { float u1 = (float)fontChar.Width * (1.0f / (float)charTextureWidth); float v1 = (float)font.Height * (1.0f / charHeight); CharacterVertex[] vertices = new CharacterVertex[6] { new CharacterVertex(0.0f, charHeight, 0.0f, v1), new CharacterVertex(fontChar.Width, 0.0f, u1, 0.0f), new CharacterVertex(0.0f, 0.0f, 0.0f, 0.0f), new CharacterVertex(fontChar.Width, charHeight, u1, v1), new CharacterVertex(fontChar.Width, 0.0f, u1, 0.0f), new CharacterVertex(0.0f, charHeight, 0.0f, v1), }; int vaoHandle = GL.GenVertexArray(); GL.BindVertexArray(vaoHandle); int bufferHandle = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, bufferHandle); GL.BufferData <CharacterVertex>(BufferTarget.ArrayBuffer, new IntPtr(CharacterVertex.StructSize * vertices.Length), vertices, BufferUsageHint.StaticDraw); GL.EnableVertexAttribArray(0); GL.EnableVertexAttribArray(1); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, CharacterVertex.StructSize, 0); GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, CharacterVertex.StructSize, Marshal.OffsetOf(typeof(CharacterVertex), "U")); GL.BindVertexArray(0); usedArrayBuffers.Add(bufferHandle); vaoWidthMap.Add(fontChar.Width, vaoHandle); } characters.Add(c, fontChar); } }