private static GlyphServer Create(List <ChunkBase> chunkList, int maxTextureWidth, int maxTextureHeight, int maxTextureCount) { var context = new PagesContext(maxTextureWidth, maxTextureHeight, maxTextureCount); foreach (var item in chunkList) { item.Put(context); } Bitmap[] bitmaps = GenerateBitmaps(chunkList, context.PageList.Count); PrintChunks(chunkList, context, bitmaps); Dictionary <string, GlyphInfo> dictionary = GetDictionary(chunkList, bitmaps[0].Width, bitmaps[0].Height); Texture texture = GenerateTexture(bitmaps); var server = new GlyphServer(); server.dictionary = dictionary; server.GlyphTexture = texture; server.TextureWidth = bitmaps[0].Width; server.TextureHeight = bitmaps[0].Height; //// test: save bitmaps to disk. //Test(server.dictionary, bitmaps); foreach (var item in bitmaps) { item.Dispose(); } return(server); }
private TextBillboardNode(int width, int height, GlyphsModel model, RenderMethodBuilder renderUnitBuilder, GlyphServer glyphServer = null) : base(model, renderUnitBuilder) { if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } this._width = width; this._height = height; this.widthByHeight = (float)width / (float)height; this.heightByWidth = (float)height / (float)width; this.textModel = model; if (glyphServer == null) { this.glyphServer = GlyphServer.DefaultServer; } else { this.glyphServer = glyphServer; } }
/// <summary> /// start from (0, 0) to the right. /// </summary> /// <param name="text"></param> /// <param name="server"></param> /// <param name="totalWidth"></param> /// <param name="totalHeight"></param> unsafe private void PositionPass(string text, GlyphServer server, out float totalWidth, out float totalHeight) { int textureWidth = server.TextureWidth; int textureHeight = server.TextureHeight; VertexBuffer buffer = this.positionBuffer; var positionArray = (QuadStruct *)buffer.MapBuffer(MapBufferAccess.ReadWrite); const float height = 2.0f; // let's say height is 2.0f. totalWidth = 0; totalHeight = height; int index = 0; foreach (var c in text) { GlyphInfo glyphInfo; float wByH = 0; if (server.GetGlyphInfo(c, out glyphInfo)) { float w = (glyphInfo.quad.rightBottom.x - glyphInfo.quad.leftBottom.x) * textureWidth; float h = (glyphInfo.quad.rightBottom.y - glyphInfo.quad.rightTop.y) * textureHeight; wByH = height * w / h; } else { // put an empty glyph(square) here. wByH = height * 1.0f / 1.0f; } var leftTop = new vec2(totalWidth, 1f); var leftBottom = new vec2(totalWidth, -1f); var rightBottom = new vec2(totalWidth + wByH, -1f); var rightTop = new vec2(totalWidth + wByH, 1f); positionArray[index++] = new QuadStruct(leftTop, leftBottom, rightBottom, rightTop); totalWidth += wByH; } // move to center. const float scale = 1f; for (int i = 0; i < text.Length; i++) { QuadStruct quad = positionArray[i]; var newPos = new QuadStruct( // y is already in [-1, 1], so just shrink x to [-1, 1] new vec2(quad.leftTop.x / totalWidth * 2.0f - 1f, quad.leftTop.y) * scale, new vec2(quad.leftBottom.x / totalWidth * 2.0f - 1f, quad.leftBottom.y) * scale, new vec2(quad.rightBottom.x / totalWidth * 2.0f - 1f, quad.rightBottom.y) * scale, new vec2(quad.rightTop.x / totalWidth * 2.0f - 1f, quad.rightTop.y) * scale ); positionArray[i] = newPos; } buffer.UnmapBuffer(); }
unsafe private void ArrangeCharaters(string text, GlyphServer server) { float totalWidth, totalHeight; PositionPass(text, server, out totalWidth, out totalHeight); UVPass(text, server); this.drawCmd.VertexCount = text.Length * 4; // each alphabet needs 4 vertexes. this.Width = (int)(totalWidth * this.Height / totalHeight); // auto size means auto width. }
unsafe private void ArrangeCharaters(string text, GlyphServer server) { float totalWidth, totalHeight; PositionPass(text, server, out totalWidth, out totalHeight); UVPass(text, server); this.indexBuffer.RenderingVertexCount = text.Length * 4; // each alphabet needs 4 vertexes. this.widthByHeight = totalWidth / totalHeight; this.heightByWidth = totalHeight / totalWidth; this.Width = (int)(this.Height * this.widthByHeight);// auto size means auto width. }
/// <summary> /// /// </summary> protected override void DoInitialize() { this.RenderUnit.Initialize(); this.positionBuffer = this.labelModel.GetVertexAttributeBuffer(GlyphsModel.position); this.strBuffer = this.labelModel.GetVertexAttributeBuffer(GlyphsModel.STR); this.indexBuffer = this.labelModel.GetIndexBuffer() as ZeroIndexBuffer; GlyphServer server = GlyphServer.DefaultServer; Texture texture = server.GlyphTexture; string name = glyphTexture; this.RenderUnit.Methods[0].Program.SetUniform(name, texture); }
static GlyphServer() { var builder = new StringBuilder(); for (char c = (char)20; c < (char)127; c++) { builder.Append(c); } string charSet = builder.ToString(); var font = new Font("Arial", 32, GraphicsUnit.Pixel); defaultServer = GlyphServer.Create(font, charSet); font.Dispose(); }
/// <summary> /// Creates a billboard in 3D world. Its size is described by Width\Height(in pixels). /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="capacity">Maximum characters count.</param> /// <param name="glyphServer"></param> /// <returns></returns> public static TextBillboardNode Create(int width, int height, int capacity, GlyphServer glyphServer = null) { var vs = new VertexShader(vertexCode);// this vertex shader has no vertex attributes. var fs = new FragmentShader(fragmentCode); var provider = new ShaderArray(vs, fs); var map = new AttributeMap(); map.Add(inPosition, GlyphsModel.position); map.Add(inSTR, GlyphsModel.STR); var blendState = new BlendFuncSwitch(BlendSrcFactor.SrcAlpha, BlendDestFactor.OneMinusSrcAlpha); var builder = new RenderMethodBuilder(provider, map, blendState); var node = new TextBillboardNode(width, height, new GlyphsModel(capacity), builder, glyphServer); node.Initialize(); node.blend = blendState; return node; }
/// <summary> /// start from (0, 0) to the right. /// </summary> /// <param name="text"></param> /// <param name="server"></param> /// <param name="totalWidth"></param> /// <param name="totalHeight"></param> unsafe private void PositionPass(string text, GlyphServer server, out float totalWidth, out float totalHeight) { int textureWidth = server.TextureWidth; int textureHeight = server.TextureHeight; VertexBuffer buffer = this.positionBuffer; var positionArray = (QuadPositionStruct *)buffer.MapBuffer(MapBufferAccess.ReadWrite); const float height = 2; // 2 is the height value in clip space. totalWidth = 0; totalHeight = height; int index = 0; foreach (var c in text) { if (index >= this.textModel.Capacity) { break; } GlyphInfo glyphInfo; float wByH = 0; if (server.GetGlyphInfo(c, out glyphInfo)) { float w = (glyphInfo.quad.rightBottom.x - glyphInfo.quad.leftBottom.x) * textureWidth; float h = (glyphInfo.quad.rightBottom.y - glyphInfo.quad.rightTop.y) * textureHeight; wByH = height * w / h; } else { // put an empty glyph(square) here. wByH = height * 1.0f / 1.0f; } var leftTop = new vec2(totalWidth, height); var leftBottom = new vec2(totalWidth, 0); var rightBottom = new vec2(totalWidth + wByH, 0); var rightTop = new vec2(totalWidth + wByH, height); positionArray[index++] = new QuadPositionStruct(leftTop, leftBottom, rightBottom, rightTop); totalWidth += wByH; } buffer.UnmapBuffer(); }
/// <summary> /// /// </summary> protected override void DoInitialize() { base.DoInitialize(); // make sure textModel only returns once. this.positionBuffer = (from item in this.textModel.GetVertexAttribute(GlyphsModel.position) select item).First(); this.strBuffer = (from item in this.textModel.GetVertexAttribute(GlyphsModel.STR) select item).First(); this.drawCmd = (from item in this.textModel.GetDrawCommand() select item).First() as DrawArraysCmd; GlyphServer server = this.glyphServer; Texture texture = server.GlyphTexture; RenderMethod method = this.RenderUnit.Methods[0]; // the only render unit in this node. ShaderProgram program = method.Program; program.SetUniform(glyphTexture, texture); program.SetUniform(width, this._width); program.SetUniform(height, this._height); program.SetUniform(textColor, this._color); }
/// <summary> /// /// </summary> protected override void DoInitialize() { base.DoInitialize(); this.positionBuffer = this.textModel.GetVertexAttributeBuffer(GlyphsModel.position); this.strBuffer = this.textModel.GetVertexAttributeBuffer(GlyphsModel.STR); this.indexBuffer = this.textModel.GetIndexBuffer() as ZeroIndexBuffer; GlyphServer server = this.glyphServer; Texture texture = server.GlyphTexture; RenderMethod method = this.RenderUnit.Methods[0]; // the only render unit in this node. ShaderProgram program = method.Program; program.SetUniform(glyphTexture, texture); program.SetUniform(width, this._width); program.SetUniform(height, this._height); program.SetUniform(textColor, this._color); }
/// <summary> /// start from (0, 0) to the right. /// </summary> /// <param name="text"></param> /// <param name="server"></param> unsafe private void UVPass(string text, GlyphServer server) { VertexBuffer buffer = this.uvBuffer; var uvArray = (QuadStruct *)buffer.MapBuffer(MapBufferAccess.WriteOnly); int index = 0; foreach (var c in text) { GlyphInfo glyphInfo; if (server.GetGlyphInfo(c, out glyphInfo)) { uvArray[index] = glyphInfo.quad; } index++; } buffer.UnmapBuffer(); }
/// <summary> /// start from (0, 0) to the right. /// </summary> /// <param name="text"></param> /// <param name="server"></param> unsafe private void TextureIndexPass(string text, GlyphServer server) { VertexBuffer buffer = this.textureIndexBuffer; var textureIndexArray = (float *)buffer.MapBuffer(MapBufferAccess.WriteOnly); int index = 0; foreach (var c in text) { GlyphInfo glyphInfo; if (server.GetGlyphInfo(c, out glyphInfo)) { textureIndexArray[index] = glyphInfo.textureIndex; } index++; } buffer.UnmapBuffer(); }
unsafe private void ArrangeCharaters(string text, GlyphServer server) { float totalWidth, totalHeight; PositionPass(text, server, out totalWidth, out totalHeight); UVPass(text, server); this.drawCmd.VertexCount = text.Length * 4; // each alphabet needs 4 vertexes. if (totalWidth != 0.0f && totalHeight != 0.0f) { this.widthByHeight = totalWidth / totalHeight; this.heightByWidth = totalHeight / totalWidth; this.Width = (int)(this.Height * this.widthByHeight);// auto size means auto width. } else { this.Width = 0; } }
/// <summary> /// start from (0, 0) to the right. /// </summary> /// <param name="text"></param> /// <param name="server"></param> unsafe private void UVPass(string text, GlyphServer server) { VertexBuffer buffer = this.stringBuffer; var textureIndexArray = (QuadSTRStruct *)buffer.MapBuffer(MapBufferAccess.WriteOnly); int index = 0; foreach (var c in text) { if (index >= this.labelModel.Capacity) { break; } GlyphInfo glyphInfo; if (server.GetGlyphInfo(c, out glyphInfo)) { textureIndexArray[index] = glyphInfo.quad; } index++; } buffer.UnmapBuffer(); }
private static void Create(int maxTextureWidth, int maxTextureHeight, int maxTextureCount, GlyphServer server, List <ChunkBase> chunkList) { var context = new PagesContext(maxTextureWidth, maxTextureHeight, maxTextureCount); foreach (var item in chunkList) { item.Put(context); } Bitmap[] bitmaps = GenerateBitmaps(chunkList, context); PrintChunks(chunkList, context, bitmaps); FillDictionary(chunkList, context, server.dictionary, bitmaps[0].Width, bitmaps[0].Height); Texture texture = GenerateTexture(bitmaps); server.GlyphTexture = texture; server.TextureWidth = bitmaps[0].Width; server.TextureHeight = bitmaps[0].Height; //// test: save bitmaps to disk. //Test(server.dictionary, bitmaps); foreach (var item in bitmaps) { item.Dispose(); } }
/// <summary> /// Create a <see cref="GlyphServer"/> instance that provides glyph information according to specified characters. /// </summary> /// <param name="font"></param> /// <param name="charset"></param> /// <returns></returns> public static GlyphServer CreateGlyphServer(this Font font, IEnumerable <string> charset) { return(GlyphServer.Create(font, charset)); }
private static void Create(int textureWidth, int textureHeight, int maxTextureCount, GlyphServer server, List <ChunkBase> chunkList) { var context = new PagesContext(textureWidth, textureHeight, maxTextureCount); foreach (var item in chunkList) { item.Put(context); } Bitmap[] bitmaps = GenerateBitmaps(chunkList, context); PrintChunks(chunkList, context, bitmaps); //for (int i = 0; i < bitmaps.Length; i++) //{ // bitmaps[i].Save(string.Format("{0}.png", i)); //} Texture texture = GenerateTexture(bitmaps); server.GlyphTexture = texture; server.TextureWidth = bitmaps[0].Width; server.TextureHeight = bitmaps[0].Height; FillDictionary(chunkList, context, server.dictionary, bitmaps[0].Width, bitmaps[0].Height); }