/// <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 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 specifies 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 specifies the number of layers defining the texture array. /// </param> /// <param name="level"> /// A <see cref="UInt32"/> that specifies the mipmap level affected. /// </param> public EmptyTechnique(TextureArray2D texture, TextureTarget target, PixelLayout pixelFormat, uint width, uint height, uint layers, uint level) : base(texture) { _TextureArray2d = texture; _Target = target; _PixelFormat = pixelFormat; _Width = width; _Height = height; _Layers = layers; _Level = level; }
/// <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); } }
/// <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)) { }
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> /// 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 = (ArrayBufferInterleaved <GlyphInstance>)ctx.GetSharedResource(instanceArrayId); if (_GlyphInstances == null) { _GlyphInstances = new ArrayBufferInterleaved <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 }