я пытаюсь написать wpf как пользовательский интерфейс. Я использую Sharpfont, FreeImage c# привязки и OpenGL. Моя проблема заключается в обработке шрифтов и создании текстур для моих шрифтов. Это то, что я получаю ...
Это мой код шрифта
int IGlyphAtlas.Width => SIZE;
int IGlyphAtlas.Height => SIZE;
public int ID { get; } = id++;
public float Size { get; }
public string Family => fontface.Family;
public bool IsLoaded => fontface != null;
public FontWeight Weight => fontface.Weight;
public FontStyle Style => fontface.Style;
public FontStretch Stretch => fontface.Stretch;
public Texture Texture => internaltexture;
private bool isdisposed;
private readonly FontFace fontface;
private readonly TextAnalyzer analyzer;
private readonly Texture2D internaltexture;
private readonly List<PixelData> pixeldata = new List<PixelData>();
public Font(FontFace face, float size)
{
TextureAttributes attributes = new TextureAttributes()
{
filter = OpenGL.GlFilter.LINEAR,
format = OpenGL.GLPixelFormat.RED,
type = OpenGL.GLPixelDataType.UNSIGNED_BYTE,
wrap = OpenGL.GLTextureWrapMode.CLAMP_TO_BORDER,
internalformat = OpenGL.GLInternalFormat.R8,
};
Size = size;
fontface = face;
analyzer = new TextAnalyzer(this);
internaltexture = new Texture2D(attributes, SIZE, SIZE);
}
public TextLayout Layout(string text, TextFormat format, Rect rect, bool direct)
{
TextLayout layout = new TextLayout();
format.Font = fontface;
format.Size = Size;
analyzer.Clear();
analyzer.AppendText(text, format);
analyzer.PerformLayout((float)rect.x, (float)rect.y, (float)rect.width, (float)rect.height, layout);
return layout;
}
public Texture CopyInternalTexture()
{
TextureAttributes attributes = new TextureAttributes()
{
filter = OpenGL.GlFilter.LINEAR,
format = OpenGL.GLPixelFormat.RED,
type = OpenGL.GLPixelDataType.UNSIGNED_BYTE,
wrap = OpenGL.GLTextureWrapMode.CLAMP_TO_BORDER,
internalformat = OpenGL.GLInternalFormat.R8,
};
return new Texture2D(attributes, SIZE, SIZE, internaltexture.Read());
}
public void Dispose() => Dispose(true);
private void Dispose(bool dispose)
{
if (isdisposed) return;
if (dispose)
{
isdisposed = true;
}
}
void IGlyphAtlas.Insert(char glyph, int page, int x, int y, int width, int height, IntPtr data)
{
if (isdisposed) throw new ObjectDisposedException(nameof(Font));
if (page > 0) throw new InvalidOperationException("the texture of the font is to small for more glyphs");
//byte[] pixels = new byte[width * height];
//Marshal.Copy(data, pixels, 0, pixels.Length);
internaltexture.Write(0, x, y, width, height, data);
//pixeldata.Add(new PixelData(glyph, x, y, width, height, pixels));
}
это мой код текстуры
public int Width { get; }
public int Height { get; }
public GLTextureTarget Target { get; }
public GLPixelDataType Type => textureattributes.type;
public GLPixelFormat Format => textureattributes.format;
public GLInternalFormat InternalFormat => textureattributes.internalformat;
public GLTextureWrapMode Wrap => textureattributes.wrap;
public GlFilter Filter => textureattributes.filter;
private bool isdisposed;
private readonly uint textureindex;
private readonly TextureAttributes textureattributes;
public Texture(GLTextureTarget target, TextureAttributes attributes, int width, int height)
{
Target = target;
Width = width;
Height = height;
textureattributes = attributes;
textureindex = GL.GenTexture();
GL.BindTexture(Target, textureindex);
Initialize(IntPtr.Zero);
GL.BindTexture(Target, 0);
}
public Texture(GLTextureTarget target, TextureAttributes attributes, int width, int height, IntPtr dataptr)
{
Target = target;
Width = width;
Height = height;
textureattributes = attributes;
textureindex = GL.GenTexture();
GL.BindTexture(Target, textureindex);
Initialize(dataptr);
GL.BindTexture(Target, 0);
}
public Texture(GLTextureTarget target, TextureAttributes attributes, int width, int height, byte[] dataarray)
{
Target = target;
Width = width;
Height = height;
textureattributes = attributes;
textureindex = GL.GenTexture();
GCHandle pinnedArray = GCHandle.Alloc(dataarray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
GL.BindTexture(Target, textureindex);
Initialize(pointer);
GL.BindTexture(Target, 0);
pinnedArray.Free();
}
internal void Bind()
{
if (isdisposed) throw new ObjectDisposedException(nameof(Texture));
GL.BindTexture(Target, textureindex);
}
internal void Release() => GL.BindTexture(Target, 0);
public void Write(int level, int xoffset, int yoffset, int width, int height, IntPtr data)
{
if (isdisposed) throw new ObjectDisposedException(nameof(Texture));
GL.BindTexture(Target, textureindex);
WriteOverride(level, xoffset, yoffset, width, height, data);
GL.BindTexture(Target, 0);
}
public void Write(int level, int xoffset, int yoffset, int width, int height, byte[] data)
{
if (isdisposed) throw new ObjectDisposedException(nameof(Texture));
GL.BindTexture(Target, textureindex);
WriteOverride(level, xoffset, yoffset, width, height, data);
GL.BindTexture(Target, 0);
}
public byte[] Read()
{
if (isdisposed) throw new ObjectDisposedException(nameof(Texture));
int size = Width * Height * GetBPP();
GL.BindTexture(Target, textureindex);
byte[] dataarray = new byte[size];
GL.GetTextureImage(textureindex, 0, Format, Type, size, dataarray);
GL.BindTexture(Target, 0);
return dataarray;
}
public byte[] Read(int level, int xoffset, int yoffset, int width, int height)
{
if (isdisposed) throw new ObjectDisposedException(nameof(Texture));
int size = width * height * GetBPP();
byte[] dataarray = new byte[size];
GL.BindTexture(Target, textureindex);
GL.GetTextureSubImage(textureindex, 0, xoffset, yoffset, 0, width, height, 0, Format, Type, size, dataarray);
GL.BindTexture(Target, 0);
return dataarray;
}
public void Dispose() => Dispose(true);
protected abstract void Initialize(IntPtr dataptr);
protected abstract void WriteOverride(int level, int x, int y, int width, int height, byte[] data);
protected abstract void WriteOverride(int level, int x, int y, int width, int height, IntPtr data);
private void Dispose(bool dispose)
{
if (isdisposed) return;
if (dispose)
{
isdisposed = true;
GL.DeleteTextures(1, new[] { textureindex });
}
}
private int GetBPP()
{
switch (Format)
{
case GLPixelFormat.STENCIL_INDEX:
case GLPixelFormat.DEPTH_COMPONENT:
case GLPixelFormat.RED:
case GLPixelFormat.GREEN:
case GLPixelFormat.BLUE: return 1;
case GLPixelFormat.RG: return 2;
case GLPixelFormat.BGR:
case GLPixelFormat.RGB: return 3;
case GLPixelFormat.BGRA:
case GLPixelFormat.RGBA: return 4;
case GLPixelFormat.RED_INTEGER:
case GLPixelFormat.GREEN_INTEGER:
case GLPixelFormat.BLUE_INTEGER: return 4;
case GLPixelFormat.RG_INTEGER: return 8;
case GLPixelFormat.BGR_INTEGER:
case GLPixelFormat.RGB_INTEGER: return 12;
case GLPixelFormat.BGRA_INTEGER:
case GLPixelFormat.RGBA_INTEGER: return 16;
case GLPixelFormat.NONE:
default: return 0;
}
}
и texture2D
public Texture2D(TextureAttributes attributes, int width, int height) :
base(GLTextureTarget.TEXTURE_2D, attributes, width, height)
{
}
public Texture2D(TextureAttributes attributes, int width, int height, IntPtr dataptr) :
base(GLTextureTarget.TEXTURE_2D, attributes, width, height, dataptr)
{
}
public Texture2D(TextureAttributes attributes, int width, int height, byte[] dataarray) :
base(GLTextureTarget.TEXTURE_2D, attributes, width, height, dataarray)
{
}
protected override void Initialize(IntPtr dataptr)
{
GL.TexParameteri(Target, GLTextureParameter.TEXTURE_MIN_FILTER, Filter);
GL.TexParameteri(Target, GLTextureParameter.TEXTURE_MAG_FILTER, Filter);
GL.TexParameteri(Target, GLTextureParameter.TEXTURE_WRAP_S, Wrap);
GL.TexParameteri(Target, GLTextureParameter.TEXTURE_WRAP_T, Wrap);
GL.GenerateMipmap(Target);
GL.TexImage2D(GLTexture2DProxyTarget.TEXTURE_2D, 0, InternalFormat, Width, Height, 0, Format, Type, dataptr);
}
protected override void WriteOverride(int level, int x, int y, int width, int height, byte[] data)
=> GL.TexSubImage2D(GLTexture2DTarget.TEXTURE_2D, level, x, y, width, height, Format, Type, data);
protected override void WriteOverride(int level, int x, int y, int width, int height, IntPtr data)
=> GL.TexSubImage2D(GLTexture2DTarget.TEXTURE_2D, level, x, y, width, height, Format, Type, data);
im с использованием одного канала (красный) для данных текстуры. sharpfont работает правильно (подтверждено). я что-то пропустил, написав текстуру?