public static void RenderText(string message, float x, float y, float scale, float rotation, Color color) { // Apply the 2D orthographic matrix transformation SetOrthographicMatrix(); rotation = rotation * 180f / Constants.pi_float; // Set the text shader program and pass in the color as a parameter GL.UseProgram(ShaderManager.TextShader.GpuHandle); int uniformLocation = GL.GetUniformLocation(ShaderManager.TextShader.GpuHandle, "color"); GL.Uniform4(uniformLocation, new Color4(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f)); // Apply the model view matrix transformations GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.Translate((x * _screenWidth - _screenWidth / 2f), (y * _screenHeight - _screenHeight / 2f), 0f); if (rotation != 0) { GL.Rotate(rotation, 0, 0, 1); } // Set up the verteces (hardware instanced for all character sprites) GL.BindBuffer(BufferTarget.ArrayBuffer, CharacterSprite.GpuVertexBufferHandle); GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero); GL.EnableClientState(ArrayCap.VertexArray); // this standardizes the size (not depedent on sprite sheet size) float sizeRatio = scale / (float)_font.LineHeight; for (int i = 0; i < message.Length; i++) { CharacterSprite sprite = _font.Get(message[i]); // Calculate the per-character transformational values float ySize = sizeRatio * (float)sprite.OriginalHeight; float yOffset = sizeRatio * (float)sprite.YOffset; float xSize = sizeRatio * (float)sprite.OriginalWidth; float xRatio = xSize / (float)(sprite.OriginalWidth); float xOffset = xRatio * (float)sprite.XOffset; float xAdvance = xRatio * (float)sprite.XAdvance; // Kearning (extra adjustments between specific charasters) if (i + 1 < message.Length) { xAdvance += xRatio * (float)sprite.CheckKearning(message[i + 1]); } // Apply the character offsets and scaling GL.Translate(xOffset, -yOffset, 0f); GL.Scale(xSize, ySize, 0f); // Bind the texture and set up the texture coordinates GL.BindTexture(TextureTarget.Texture2D, sprite.Texture.GpuHandle); GL.BindBuffer(BufferTarget.ArrayBuffer, sprite.GPUTextureCoordinateBufferHandle); GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero); GL.EnableClientState(ArrayCap.TextureCoordArray); // Perform the render //GL.DrawArrays(PrimitiveType.Triangles, 0, sprite.VertexCount); GL.DrawArrays(BeginMode.Triangles, 0, sprite.VertexCount); // Remove the per character transforms and advance to the next charachers position GL.Scale(1 / xSize, 1 / ySize, 0f); GL.Translate(-xOffset + xAdvance, yOffset, 0f); } }