/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="modelview"> /// The <see cref="Matrix4x4"/> the model-view-projection matrix for the first character of <paramref name="s"/>. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore_Instanced(GraphicsContext ctx, TextureArray2d texture, ColorRGBAF color, List <GlyphModelType> glyphsInstances) { ctx.Bind(_FontProgram); // Set uniforms _FontProgram.SetUniform(ctx, "glo_UniformColor", color); _FontProgram.SetUniform(ctx, "glo_FontGlyph", texture); // Set instances if (_GlyphUniformBuffer == null) { // Set instances for (int i = 0; i < glyphsInstances.Count; i++) { string structName = "glo_Glyphs[" + i + "]"; _FontProgram.SetUniform(ctx, structName + ".ModelViewProjection", glyphsInstances[i].ModelViewProjection); _FontProgram.SetUniform(ctx, structName + ".VertexParams", glyphsInstances[i].VertexParams); _FontProgram.SetUniform(ctx, structName + ".TexParams", glyphsInstances[i].TexParams); } } else { // Bind uniform block // Note: already updated by DrawString _FontProgram.SetUniformBlock(ctx, "Glyphs", _GlyphUniformBuffer); } // Rasterize it State.BlendState.AlphaBlending.Apply(ctx, _FontProgram); _VertexArrays.DrawInstanced(ctx, _FontProgram, (uint)glyphsInstances.Count); }
/// <summary> /// Construct a ImageTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> /// <param name="pixelFormat"> /// The <see cref="PixelLayout"/> that specify texture pixel format. /// </param> /// <param name="images"> /// A <see cref="Image[]"/> that specify the texture array layers. /// </param> /// <param name="resetLayers"> /// /// </param> public ImageTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, Image[] images, bool resetLayers) : base(texture) { if (images == null) { throw new ArgumentNullException("images"); } if (images.Length == 0) { throw new ArgumentException("no image layers", "images"); } _TextureArray2d = texture; _Target = target; _PixelFormat = pixelFormat; _Images = images; foreach (Image image in images) { if (image != null) { image.IncRef(); } } _ResetLayers = resetLayers; }
/// <summary> /// Construct a ImageTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> /// <param name="pixelFormat"> /// The <see cref="PixelLayout"/> that specify texture pixel format. /// </param> /// <param name="images"> /// A <see cref="Image[]"/> that specify the texture array layers. /// </param> /// <param name="resetLayers"> /// /// </param> public ImageTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, Image[] images, bool resetLayers) : base(texture) { if (images == null) { throw new ArgumentNullException("images"); } if (images.Length == 0) { throw new ArgumentException("no image layers", "images"); } //if (Array.TrueForAll(images, delegate (Image item) { return ((item == null) || (item.Width == images[0].Width && item.Height == images[0].Height)); }) == false) // throw new ArgumentException("non-uniform image layers extents", "images"); _TextureArray2d = texture; _Target = target; _PixelFormat = pixelFormat; _Images = images; foreach (Image image in images) { if (image != null) { image.IncRef(); } } _ResetLayers = resetLayers; }
/// <summary> /// Construct a ImmutableEmptyTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> /// <param name="pixelFormat"> /// The texture pixel format. /// </param> /// <param name="width"> /// The width of the texture. /// </param> /// <param name="height"> /// The height of the texture. /// </param> /// <param name="layers"> /// A <see cref="UInt32"/> that specify the number of layers defining the texture array. /// </param> /// <param name="levels"> /// A <see cref="UInt32"/> that specify the number of levels defining the texture array. /// </param> public ImmutableEmptyTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, uint width, uint height, uint layers, uint levels) : base(texture, target, pixelFormat, width, height, layers, 0) { if (levels == 0) { throw new ArgumentException("invalid value", "levels"); } _MipmapLevels = levels; }
/// <summary> /// Construct a EmptyTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> /// <param name="pixelFormat"> /// The texture pixel format. /// </param> /// <param name="width"> /// The width of the texture. /// </param> /// <param name="height"> /// The height of the texture. /// </param> /// <param name="layers"> /// A <see cref="UInt32"/> that specify the number of layers defining the texture array. /// </param> public EmptyTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, uint width, uint height, uint layers) : base(texture) { _TextureArray2d = texture; _Target = target; _PixelFormat = pixelFormat; _Width = width; _Height = height; _Layers = layers; }
/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore_InstancedArrays(GraphicsContext ctx, TextureArray2d texture, ColorRGBAF color, List <GlyphModelType> glyphInstances) { ctx.Bind(_FontProgram); // Set uniforms _FontProgram.SetUniform(ctx, "glo_UniformColor", color); _FontProgram.SetUniform(ctx, "glo_FontGlyph", texture); // Rasterize it State.BlendState.AlphaBlending.Apply(ctx, _FontProgram); _VertexArrays.DrawInstanced(ctx, _FontProgram, (uint)glyphInstances.Count); }
/// <summary> /// Construct a ImageTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specifies the texture target. /// </param> /// <param name="pixelFormat"> /// The <see cref="PixelLayout"/> that specifies texture pixel format. /// </param> /// <param name="images"> /// A <see cref="Image"/> that specifies the texture array image for the specified layer. /// </param> public ImageTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, Image image, uint layer) : base(texture) { if (image == null) { throw new ArgumentNullException("images"); } _TextureArray2d = texture; _Target = target; _PixelFormat = pixelFormat; _Image = image; _Image.IncRef(); _ImageLayer = layer; }
/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore(GraphicsContext ctx, TextureArray2d texture, ColorRGBAF color, List <GlyphModelType> glyphInstances) { if (ctx.Extensions.InstancedArrays) { DrawStringCore_InstancedArrays(ctx, texture, color, glyphInstances); } else if (ctx.Extensions.DrawInstanced_ARB) { DrawStringCore_Instanced(ctx, texture, color, glyphInstances); } else { DrawStringCore_Compatibility(ctx, texture, color, glyphInstances); } }
/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore_Compatibility(GraphicsContext ctx, TextureArray2d texture, ColorRGBAF color, List <GlyphModelType> glyphsInstances) { ctx.Bind(_FontProgram); // Set uniforms _FontProgram.SetUniform(ctx, "glo_UniformColor", color); _FontProgram.SetUniform(ctx, "glo_FontGlyph", texture); // Rasterize it State.BlendState.AlphaBlending.Apply(ctx, _FontProgram); for (int i = 0; i < glyphsInstances.Count; i++) { _FontProgram.SetUniform(ctx, "glo_ModelViewProjection", glyphsInstances[i].ModelViewProjection); _FontProgram.SetUniform(ctx, "glo_VertexParams", glyphsInstances[i].VertexParams); _FontProgram.SetUniform(ctx, "glo_TexParams", glyphsInstances[i].TexParams); _VertexArrays.Draw(ctx, _FontProgram); } }
public void AttachColor(uint attachmentIndex, TextureArray2d texture, uint layer, uint level) { AttachColor(attachmentIndex, new TextureArrayAttachment(texture, layer, level)); }
/// <summary> /// Construct a Texture3dAttachment specifing the texture. /// </summary> /// <param name="texture"> /// The <see cref="TextureCube"/> to be attached to a Framebuffer. /// </param> /// <param name="layer"> /// A <see cref="UInt32"/> the specify the layer of <paramref name="texture"/> to attach. /// </param> /// <param name="textureLevel"> /// A <see cref="UInt32"/> that specify the level of <paramref name="texture"/> to be attached. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="texture"/> is null. /// </exception> public TextureArrayAttachment(TextureArray2d texture, uint layer, uint textureLevel) : base(texture, textureLevel) { Depth = layer; }
/// <summary> /// Construct a Texture3dAttachment specifing the texture. /// </summary> /// <param name="texture"> /// The <see cref="TextureCube"/> to be attached to a Framebuffer. /// </param> /// <param name="layer"> /// A <see cref="UInt32"/> the specify the layer of <paramref name="texture"/> to attach. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="texture"/> is null. /// </exception> public TextureArrayAttachment(TextureArray2d texture, uint layer) : this(texture, layer, 0) { }
/// <summary> /// Construct a ImmutableEmptyTechnique. /// </summary> /// <param name="texture"> /// The <see cref="TextureArray2d"/> affected by this Technique. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> /// <param name="pixelFormat"> /// The texture pixel format. /// </param> /// <param name="width"> /// The width of the texture. /// </param> /// <param name="height"> /// The height of the texture. /// </param> /// <param name="layers"> /// A <see cref="UInt32"/> that specify the number of layers defining the texture array. /// </param> public ImmutableEmptyTechnique(TextureArray2d texture, TextureTarget target, PixelLayout pixelFormat, uint width, uint height, uint layers) : this(texture, target, pixelFormat, width, height, layers, GetMipmapCompleteLevels(width, height, 1, 0)) { }
/// <summary> /// Create resources for rendering glyphs. /// </summary> /// <param name="ctx"></param> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); StringFormat stringFormat = StringFormat.GenericTypographic; // Font-wide resources string resourceClassId = "OpenGL.Objects.FontTextureArray2d"; string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); #region Instanced Arrays if (ctx.Extensions.InstancedArrays) { string instanceArrayId = resourceClassId + ".InstanceArray"; _GlyphInstances = (ArrayBufferObjectInterleaved <GlyphInstance>)ctx.GetSharedResource(instanceArrayId); if (_GlyphInstances == null) { _GlyphInstances = new ArrayBufferObjectInterleaved <GlyphInstance>(MapBufferUsageMask.MapWriteBit); _GlyphInstances.Create(256); // Share ctx.SetSharedResource(instanceArrayId, _GlyphInstances); } LinkResource(_GlyphInstances); } else { _GlyphInstances = null; } #endregion #region Vertex Array string vertexArrayId = resourceClassId + ".VertexArray"; _VertexArrays = (VertexArrays)ctx.GetSharedResource(vertexArrayId); if (_VertexArrays == null) { _VertexArrays = new VertexArrays(); ArrayBuffer <Vertex2f> arrayPosition = new ArrayBuffer <Vertex2f>(); arrayPosition.Create(new Vertex2f[] { new Vertex2f(0.0f, 1.0f), new Vertex2f(0.0f, 0.0f), new Vertex2f(1.0f, 1.0f), new Vertex2f(1.0f, 0.0f), }); _VertexArrays.SetArray(arrayPosition, VertexArraySemantic.Position); if (ctx.Extensions.InstancedArrays) { _VertexArrays.SetInstancedArray(_GlyphInstances, 0, 1, "glo_GlyphModelViewProjection"); _VertexArrays.SetInstancedArray(_GlyphInstances, 1, 1, "glo_GlyphVertexParams"); _VertexArrays.SetInstancedArray(_GlyphInstances, 2, 1, "glo_GlyphTexParams"); } _VertexArrays.SetElementArray(PrimitiveType.TriangleStrip); // Share ctx.SetSharedResource(vertexArrayId, _VertexArrays); } LinkResource(_VertexArrays); #endregion #region Glyphs Metadata string glyphDbId = resourceBaseId + ".GlyphDb"; _GlyphMetadata = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (_GlyphMetadata == null) { _GlyphMetadata = new Dictionary <char, Glyph>(); char[] fontChars = GetFontCharacters().ToCharArray(); uint layer = 0; using (Bitmap bitmap = new Bitmap(1, 1)) using (Graphics g = Graphics.FromImage(bitmap)) using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style)) { // Avoid grid fitting g.TextRenderingHint = TextRenderingHint.AntiAlias; float glyphHeight = font.GetHeight(); foreach (char c in fontChars) { SizeF glyphSize; switch (c) { case ' ': glyphSize = g.MeasureString(c.ToString(), font, 0, StringFormat.GenericDefault); break; default: glyphSize = g.MeasureString(c.ToString(), font, 0, stringFormat); break; } Glyph glyph = new Glyph(c, glyphSize, layer++, new SizeF(1.0f, 1.0f)); _GlyphMetadata.Add(c, glyph); } } // Share ctx.SetSharedResource(glyphDbId, _GlyphMetadata); } #endregion #region Glyph Sampler string samplerId = resourceBaseId + ".Sampler"; Sampler sampler = (Sampler)ctx.GetSharedResource(samplerId); if (sampler == null) { sampler = new Sampler(); sampler.Parameters.MinFilter = TextureMinFilter.Linear; } #endregion #region Glyph Texture string textureId = resourceBaseId + ".Texture"; _FontTexture = (TextureArray2d)ctx.GetSharedResource(textureId); if (_FontTexture == null) { // Get the size required for all glyphs float w = 0.0f, h = 0.0f; uint z = 0; foreach (Glyph glyph in _GlyphMetadata.Values) { w = Math.Max(w, glyph.GlyphSize.Width); h = Math.Max(h, glyph.GlyphSize.Height); z = Math.Max(z, glyph.Layer); } // Create texture _FontTexture = new TextureArray2d(); _FontTexture.Sampler = sampler; _FontTexture.Create(ctx, (uint)Math.Ceiling(w), (uint)Math.Ceiling(h), z + 1, PixelLayout.R8, 1); using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style)) using (Brush brush = new SolidBrush(Color.White)) { foreach (Glyph glyph in _GlyphMetadata.Values) { using (Bitmap bitmap = new Bitmap((int)_FontTexture.Width, (int)_FontTexture.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)) using (Graphics g = Graphics.FromImage(bitmap)) { // Recompute texture scaling glyph.TexScale = new SizeF( glyph.GlyphSize.Width / bitmap.Width, glyph.GlyphSize.Height / bitmap.Height ); // Avoid grid fitting g.TextRenderingHint = TextRenderingHint.AntiAlias; g.Clear(Color.Black); g.DrawString(glyph.GlyphChar.ToString(), font, brush, 0.0f, 0.0f, stringFormat); _FontTexture.Create(ctx, PixelLayout.R8, bitmap, glyph.Layer); } } } // Share ctx.SetSharedResource(textureId, _FontTexture); } LinkResource(_FontTexture); #endregion }
/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="modelview"> /// The <see cref="Matrix4x4"/> the model-view-projection matrix for the first character of <paramref name="s"/>. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore(GraphicsContext ctx, Matrix4x4 modelview, TextureArray2d texture, ColorRGBAF color, string s) { ModelMatrix charModel = new ModelMatrix(modelview); ctx.Bind(_FontProgram); // Set uniforms _FontProgram.SetUniform(ctx, "glo_UniformColor", color); _FontProgram.SetUniform(ctx, "glo_FontGlyph", texture); // Set instances char[] fontChars = s.ToCharArray(); uint instances = 0; _GlyphInstances.Map(ctx, BufferAccessARB.WriteOnly); try { for (int i = 0; i < fontChars.Length; i++) { Glyph glyph; if (_GlyphMetadata.TryGetValue(fontChars[i], out glyph) == false) { continue; } // Set instance information Matrix4x4f modelViewProjection = new Matrix4x4f( new Vertex4f(charModel.GetColumn(0)), new Vertex4f(charModel.GetColumn(1)), new Vertex4f(charModel.GetColumn(2)), new Vertex4f(charModel.GetColumn(3)) ); Vertex3f glyphVertexParams = new Vertex3f( glyph.GlyphSize.Width, glyph.GlyphSize.Height, glyph.Layer ); Vertex2f glyphTexParams = new Vertex2f( glyph.TexScale.Width, glyph.TexScale.Height ); _GlyphInstances.SetElement(modelViewProjection, instances, 0); _GlyphInstances.SetElement(glyphVertexParams, instances, 1); _GlyphInstances.SetElement(glyphTexParams, instances, 2); // Count the instance instances++; // Move next charModel.Translate(glyph.GlyphSize.Width, 0.0f); } } finally { _GlyphInstances.Unmap(ctx); } // Rasterize it using (State.BlendState stateBlend = State.BlendState.AlphaBlending) { stateBlend.ApplyState(ctx, _FontProgram); _VertexArrays.DrawInstanced(ctx, _FontProgram, instances); } }