C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字
2015-08-26 18:00
399 查看
[b]C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字 [/b]
上一篇实现了把文字绘制到OpenGL窗口,但实质上只是把含有文字的贴图贴到矩形模型上。本篇我们介绍用PointSprite绘制文字,这可以只用1个点绘制文字,并确保文字始终面相窗口。用PointSprite绘制的文字,其大小范围有限,本篇提供的Demo中,Max Row Width最大只有256。现在能够绘制少量的文字,为其指定的位置的过程与为一个点指定位置的过程是相同的,所以此方式的应用范围还是比较广的。
计算字符串贴图
.png]
上一篇实现了把文字绘制到OpenGL窗口,但实质上只是把含有文字的贴图贴到矩形模型上。本篇我们介绍用PointSprite绘制文字,这可以只用1个点绘制文字,并确保文字始终面相窗口。用PointSprite绘制的文字,其大小范围有限,本篇提供的Demo中,Max Row Width最大只有256。现在能够绘制少量的文字,为其指定的位置的过程与为一个点指定位置的过程是相同的,所以此方式的应用范围还是比较广的。
基本流程
与前文相同的是仍然用GLSL+VBO+贴图来绘制。PointSprite只是Enable了一些OpenGL开关,然后把贴图贴到一个Point图元上。/// <summary> /// 为指定的字符串生成贴图。 /// </summary> /// <param name="fontResource"></param> /// <param name="content"></param> /// <param name="fontSize"></param> /// <param name="maxRowWidth"></param> /// <returns></returns> public static System.Drawing.Bitmap GenerateBitmapForString(this FontResource fontResource, string content, int fontSize, int maxRowWidth) { // step 1: get totalLength int totalLength = 0; { int glyphsLength = 0; for (int i = 0; i < content.Length; i++) { char c = content[i]; CharacterInfo cInfo; if (fontResource.CharInfoDict.TryGetValue(c, out cInfo)) { int glyphWidth = cInfo.width; glyphsLength += glyphWidth; } //else //{ throw new Exception(string.Format("Not support for display the char [{0}]", c)); } } //glyphsLength = (glyphsLength * this.fontSize / FontResource.Instance.FontHeight); int interval = fontResource.FontHeight / 10; if (interval < 1) { interval = 1; } totalLength = glyphsLength + interval * (content.Length - 1); } // step 2: setup contentBitmap System.Drawing.Bitmap contentBitmap = null; { int interval = fontResource.FontHeight / 10; if (interval < 1) { interval = 1; } //int totalLength = glyphsLength + interval * (content.Length - 1); int currentTextureWidth = 0; int currentWidthPos = 0; int currentHeightPos = 0; if (totalLength * fontSize > maxRowWidth * fontResource.FontHeight)// 超过1行能显示的内容 { currentTextureWidth = maxRowWidth * fontResource.FontHeight / fontSize; int lineCount = (totalLength - 1) / currentTextureWidth + 1; // 确保整篇文字的高度在贴图中间。 currentHeightPos = (currentTextureWidth - fontResource.FontHeight * lineCount) / 2; //- FontResource.Instance.FontHeight / 2; } else//只在一行内即可显示所有字符 { if (totalLength >= fontResource.FontHeight) { currentTextureWidth = totalLength; // 确保整篇文字的高度在贴图中间。 currentHeightPos = (currentTextureWidth - fontResource.FontHeight) / 2; //- FontResource.Instance.FontHeight / 2; } else { currentTextureWidth = fontResource.FontHeight; currentWidthPos = (currentTextureWidth - totalLength) / 2; //glyphsLength = fontResource.FontHeight; } } //this.textureWidth = textureWidth * this.fontSize / FontResource.Instance.FontHeight; //currentWidthPosition = currentWidthPosition * this.fontSize / FontResource.Instance.FontHeight; //currentHeightPosition = currentHeightPosition * this.fontSize / FontResource.Instance.FontHeight; contentBitmap = new Bitmap(currentTextureWidth, currentTextureWidth); Graphics gContentBitmap = Graphics.FromImage(contentBitmap); Bitmap bigBitmap = fontResource.FontBitmap; for (int i = 0; i < content.Length; i++) { char c = content[i]; CharacterInfo cInfo; if (fontResource.CharInfoDict.TryGetValue(c, out cInfo)) { if (currentWidthPos + cInfo.width > contentBitmap.Width) { currentWidthPos = 0; currentHeightPos += fontResource.FontHeight; } gContentBitmap.DrawImage(bigBitmap, new Rectangle(currentWidthPos, currentHeightPos, cInfo.width, fontResource.FontHeight), new Rectangle(cInfo.xoffset, cInfo.yoffset, cInfo.width, fontResource.FontHeight), GraphicsUnit.Pixel); currentWidthPos += cInfo.width + interval; } } gContentBitmap.Dispose(); //contentBitmap.Save("PointSpriteStringElement-contentBitmap.png"); System.Drawing.Bitmap bmp = null; if (totalLength * fontSize > maxRowWidth * fontResource.FontHeight)// 超过1行能显示的内容 { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( maxRowWidth, maxRowWidth, null, IntPtr.Zero); } else//只在一行内即可显示所有字符 { if (totalLength >= fontResource.FontHeight) { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( totalLength * fontSize / fontResource.FontHeight, totalLength * fontSize / fontResource.FontHeight, null, IntPtr.Zero); } else { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( fontSize, fontSize, null, IntPtr.Zero); } } contentBitmap.Dispose(); contentBitmap = bmp; //contentBitmap.Save("PointSpriteStringElement-contentBitmap-scaled.png"); } return contentBitmap; }
计算字符串贴图
缺陷
用PointSprite绘制的文字,其大小范围有限,本篇提供的Demo中,Max Row Width最大只有256。总结
现在能够绘制少量的文字,为其指定的位置的过程与为一个点指定位置的过程是相同的,所以此方式的应用范围还是比较广的。.png]
相关文章推荐
- c#获取listview当前选中行的数据
- C#中的协变OUT和逆变
- C# select的联动效果
- 如何:创建和终止线程(C# 编程指南)
- C# 线程Thread的Join()方法
- C# XML文件操作
- C#读取Excel文件
- c#中日期的处理
- c# 分页
- c#委托、事件
- C#中virtual 方法和abstract方法的区别 .
- C#用QQ邮箱发送邮件代码
- C#WinForm制作异形窗体/控件
- C# WinForm窗体中制作滚动的字幕
- C#实现无标题栏窗体的拖动
- C#中的反射
- Rust初步(六):在C#中使用Rust组件
- C# DataTable抽取Distinct数据(不重复数据)
- Missing Number
- C# 水印透明度图片