internal void LoadFromBitmap(Bitmap bitmap) { try { ImageGDI.LoadFromBitmap(ref bitmap, out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture from bitmap..."); RLog.Error(e); } if (Id == 0 || textureTarget == 0) { RLog.Error("Error generating OpenGL texture from bitmap"); } // load succeeded, Texture can be used. /*Bind(); * GL.TexParameter( textureTarget, TextureParameterName.TextureMagFilter, (int) RTextureMagFilter.Linear ); * REngine.CheckGLError(); * * GL.TexParameter( textureTarget, TextureParameterName.TextureMinFilter, (int) RTextureMinFilter.Linear ); * * REngine.CheckGLError(); * GL.TexParameter(textureTarget, TextureParameterName.TextureMaxLod, 0); * REngine.CheckGLError(); * GL.TexParameter(textureTarget, TextureParameterName.TextureMinLod, 0); * REngine.CheckGLError(); */ Bounds = new Reactor.Math.Rectangle(0, 0, bitmap.Width, bitmap.Height); }
public void RenderTexture(RTexture texture, Math.Rectangle bounds, RColor color, Matrix matrix, bool font) { RViewport viewport = REngine.Instance._viewport; UpdateQuad(bounds); blendState.PlatformApplyState(); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); defaultShader.Bind(); defaultShader.SetSamplerValue(RTextureLayer.DIFFUSE, texture); vertexQuad2D.Bind(); vertexQuad2D.BindVertexArray(); indexQuad2D.Bind(); defaultShader.SetUniformValue("projection", camera2d.Projection); defaultShader.SetUniformValue("view", camera2d.View); defaultShader.SetUniformValue("diffuse_color", color.ToVector4()); defaultShader.SetUniformValue("model", matrix); defaultShader.SetUniformValue("font", font); vertexQuad2D.VertexDeclaration.Apply(defaultShader, IntPtr.Zero); GL.DrawElements(PrimitiveType.Triangles, indexQuad2D.IndexCount, DrawElementsType.UnsignedShort, IntPtr.Zero); REngine.CheckGLError(); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.DstAlpha); GL.Disable(EnableCap.Blend); indexQuad2D.Unbind(); vertexQuad2D.UnbindVertexArray(); vertexQuad2D.Unbind(); defaultShader.Unbind(); }
internal void LoadFromDisk(string filename) { if (Path.GetExtension(filename).ToLower() == ".dds") { try { ImageDDS.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture from: " + filename); RLog.Error(e); } } else { try { ImageGDI.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture from: " + filename); RLog.Error(e); return; } } if (Id == 0 || textureTarget == 0) { RLog.Error("Error generating OpenGL texture from: " + filename); return; } // load succeeded, Texture can be used. Bind(); int max_level = 0; int min_level = 0; REngine.CheckGLError(); GL.TexParameterI(textureTarget, TextureParameterName.TextureBaseLevel, ref min_level); REngine.CheckGLError(); GL.TexParameterI(textureTarget, TextureParameterName.TextureMaxLevel, ref max_level); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMagFilter, (int)RTextureMagFilter.Linear); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)RTextureMinFilter.Linear); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMaxLod, 0); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMinLod, 0); REngine.CheckGLError(); int height, width; GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureHeight, out height); REngine.CheckGLError(); GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureWidth, out width); REngine.CheckGLError(); Bounds = new Reactor.Math.Rectangle(0, 0, width, height); RLog.Info("Texture loaded from: " + filename); }
void UpdateQuad(Math.Rectangle placement) { quadVerts[0].Position = new Vector2(placement.X, placement.Y); quadVerts[0].TexCoord = new Vector2(0, 0); quadVerts[1].Position = new Vector2(placement.X + placement.Width, placement.Y); quadVerts[1].TexCoord = new Vector2(1, 0); quadVerts[2].Position = new Vector2(placement.X + placement.Width, placement.Y + placement.Height); quadVerts[2].TexCoord = new Vector2(1, 1); quadVerts[3].Position = new Vector2(placement.X, placement.Y + placement.Height); quadVerts[3].TexCoord = new Vector2(0, 1); vertexQuad2D.SetData <RVertexData2D>(quadVerts); }
RVertexData2D[] AddQuads(Reactor.Math.Rectangle placement, Vector4 UVs) { quadVerts[0].Position = new Vector2(placement.X, placement.Y); quadVerts[0].TexCoord = new Vector2(UVs.X, UVs.Y); quadVerts[1].Position = new Vector2(placement.X + placement.Width, placement.Y); quadVerts[1].TexCoord = new Vector2(UVs.X + UVs.Z, UVs.Y); quadVerts[2].Position = new Vector2(placement.X + placement.Width, placement.Y + placement.Height); quadVerts[2].TexCoord = new Vector2(UVs.X + UVs.Z, UVs.Y + UVs.W); quadVerts[3].Position = new Vector2(placement.X, placement.Y + placement.Height); quadVerts[3].TexCoord = new Vector2(UVs.X, UVs.Y + UVs.W); //vertexBuffer.SetData<RVertexData2D>(quadVerts); return(quadVerts); }
internal void LoadFromData(byte[] data, string name, bool isCompressed) { if (isCompressed) { try { ImageDDS.LoadFromData(data, name, out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture for: " + name); RLog.Error(e.Message); RLog.Error(e); } } else { try { ImageGDI.LoadFromData(data, out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture for: " + name); RLog.Error(e.Message); RLog.Error(e); } } if (Id == 0 || textureTarget == 0) { RLog.Error("Error generating OpenGL texture for: " + name); } // load succeeded, Texture can be used. Bind(); GL.TexParameter(textureTarget, TextureParameterName.TextureMagFilter, (int)RTextureMagFilter.Linear); int MipMapCount; GL.GetTexParameter(textureTarget, GetTextureParameter.TextureMaxLevel, out MipMapCount); if (MipMapCount == 0) // if no MipMaps are present, use linear Filter { GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)RTextureMinFilter.Linear); } else // MipMaps are present, use trilinear Filter { GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)RTextureMinFilter.LinearMipmapLinear); } int height, width; GL.GetTexParameter(textureTarget, GetTextureParameter.TextureHeight, out height); GL.GetTexParameter(textureTarget, GetTextureParameter.TextureWidth, out width); Bounds = new Reactor.Math.Rectangle(0, 0, width, height); RLog.Info("Texture loaded for: " + name); }
internal void Render(ref RShader shader, ref RVertexBuffer vertexBuffer, ref RIndexBuffer indexBuffer, string text, Vector2 location, RColor color, Matrix matrix) { Vector2 pen = location; pen.Y += MeasureString(text).Height; float x = pen.X; List <RVertexData2D> quads = new List <RVertexData2D>(); foreach (char c in text) { if (c == '\r') { continue; } if (c == '\n') { pen.X = x; pen.Y += LineHeight; continue; } if (c == ' ') { pen.X += SpaceWidth; continue; } if (c == '\t') { pen.X += (SpaceWidth * 3); continue; } RFontGlyph glyph = GetGlyphForChar(c); var dest = new Reactor.Math.Rectangle(); dest.X = (int)(pen.X + glyph.Offset.X); dest.Y = (int)pen.Y - ((int)glyph.Offset.Y); dest.Width = glyph.Bounds.Width; dest.Height = glyph.Bounds.Height; vertexBuffer.SetData <RVertexData2D>(AddQuads(dest, glyph.UVBounds)); vertexBuffer.Bind(); vertexBuffer.BindVertexArray(); indexBuffer.Bind(); vertexBuffer.VertexDeclaration.Apply(shader, IntPtr.Zero); GL.DrawElements(PrimitiveType.Triangles, indexBuffer.IndexCount, DrawElementsType.UnsignedShort, IntPtr.Zero); REngine.CheckGLError(); indexBuffer.Unbind(); vertexBuffer.Unbind(); vertexBuffer.UnbindVertexArray(); pen.X += glyph.Advance; } }
public Reactor.Math.Rectangle MeasureString(string text) { Reactor.Math.Rectangle r = new Reactor.Math.Rectangle(); foreach (char c in text) { if (c == ' ') { r.Width += SpaceWidth; continue; } if (c == '\t') { r.Width += (SpaceWidth * 3); continue; } FontGlyph glyph = GetGlyphForChar(c); r.Height = Math.Max(r.Height, glyph.Bounds.Height); r.Width += (int)glyph.Offset.X; } return(r); }
public void RenderTexture(RTexture texture, Math.Rectangle bounds, RColor color) { RenderTexture(texture, bounds, color, Matrix.Identity, false); }
public void RenderTexture(RTexture texture, Math.Rectangle bounds) { RenderTexture(texture, bounds, RColor.White); }
internal void Generate(Face face, int size, int dpi) { face.SetCharSize(0, new Fixed26Dot6(size), 0, (uint)dpi); Name = face.FamilyName; face.LoadChar((uint)32, (LoadFlags.Render | LoadFlags.Monochrome | LoadFlags.Pedantic), LoadTarget.Normal); SpaceWidth = face.Glyph.Metrics.HorizontalAdvance.ToInt32(); LineHeight = face.Height >> 6; Kerning = face.HasKerning; Size = size; Ascent = face.Ascender >> 6; Descent = face.Descender >> 6; Glyphs = new List <RFontGlyph>(); for (int i = 33; i < 126; i++) { uint charIndex = face.GetCharIndex((uint)i); face.LoadGlyph(charIndex, (LoadFlags.Render | LoadFlags.Color | LoadFlags.Pedantic | LoadFlags.CropBitmap), LoadTarget.Normal); if (face.Glyph.Bitmap.PixelMode == PixelMode.None) { continue; } RFontGlyph glyph = new RFontGlyph(); glyph.bitmap = face.Glyph.Bitmap.ToGdipBitmap(Color.White); glyph.Bounds = new Reactor.Math.Rectangle(0, 0, glyph.bitmap.Width, glyph.bitmap.Height); glyph.CharIndex = i; glyph.Offset = new Vector2(face.Glyph.Metrics.HorizontalBearingX.ToInt32(), face.Glyph.Metrics.HorizontalBearingY.ToInt32()); glyph.Advance = face.Glyph.Advance.X.ToInt32(); Glyphs.Add(glyph); } Glyphs.Sort(new FontGlyphSizeSorter()); var missed = -1; var width = 16; Bitmap b = new Bitmap(1, 1); while (missed != 0) { missed = 0; AtlasNode root = new AtlasNode(); root.bounds = new Reactor.Math.Rectangle(0, 0, width, width); b.Dispose(); b = new Bitmap(width, width); Graphics g = Graphics.FromImage(b); g.Clear(Color.Transparent); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; for (var i = 0; i < Glyphs.Count; i++) { RFontGlyph glyph = Glyphs[i]; AtlasNode result = root.Insert(glyph.Bounds); if (result != null) { Reactor.Math.Rectangle bounds = result.bounds; //g.DrawImageUnscaledAndClipped(glyph.bitmap, bounds); g.DrawImage(glyph.bitmap, bounds); glyph.Bounds = bounds; glyph.UVBounds = new Vector4((float)bounds.X, (float)bounds.Y, (float)bounds.Width, (float)bounds.Height); glyph.UVBounds /= (float)width; Glyphs[i] = glyph; } else { missed += 1; break; } } width += 16; } Texture = new RTexture2D(); Texture.LoadFromBitmap(b); Texture.SetTextureMagFilter(RTextureMagFilter.Linear); Texture.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear); Texture.SetTextureWrapMode(RTextureWrapMode.ClampToBorder, RTextureWrapMode.ClampToBorder); REngine.CheckGLError(); }
public Font Build(string filename, int size, int dpi) { Face face = new Face(FreeTypeLibrary, filename); face.SetCharSize(0, new Fixed26Dot6(size), 0, (uint)dpi); Font font = new Font(); font.Name = face.FamilyName; face.LoadChar((uint)32, (LoadFlags.Render | LoadFlags.Monochrome | LoadFlags.Pedantic), LoadTarget.Normal); font.SpaceWidth = face.Glyph.Metrics.HorizontalAdvance.ToInt32(); font.LineHeight = face.Height; font.Kerning = face.HasKerning; font.Size = size; font.Ascent = face.Ascender >> 6; font.Descent = face.Descender >> 6; font.Glyphs = new List <FontGlyph>(); for (int i = 33; i < 126; i++) { uint charIndex = face.GetCharIndex((uint)i); face.LoadGlyph(charIndex, (LoadFlags.Render | LoadFlags.Color | LoadFlags.Pedantic), LoadTarget.Normal); if (face.Glyph.Bitmap.Width == 0) { continue; } FontGlyph glyph = new FontGlyph(); glyph.bitmap = face.Glyph.Bitmap.ToGdipBitmap(Color.White); glyph.Bounds = new Reactor.Math.Rectangle(0, 0, glyph.bitmap.Width, glyph.bitmap.Height); glyph.CharIndex = i; glyph.Offset = new Vector2(face.Glyph.Metrics.HorizontalBearingX.ToInt32(), face.Glyph.Metrics.HorizontalBearingY.ToInt32()); glyph.Advance = face.Glyph.Advance.X.ToInt32(); font.Glyphs.Add(glyph); } font.Glyphs.Sort(new FontGlyphSizeSorter()); font.Glyphs.Reverse(); var missed = -1; var width = 16; Bitmap b = new Bitmap(1, 1); while (missed != 0) { Application.DoEvents(); missed = 0; AtlasNode root = new AtlasNode(); root.bounds = new Reactor.Math.Rectangle(0, 0, width, width); b.Dispose(); b = new Bitmap(width, width); Graphics g = Graphics.FromImage(b); g.Clear(Color.Transparent); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; for (var i = 0; i < font.Glyphs.Count; i++) { FontGlyph glyph = font.Glyphs[i]; AtlasNode result = root.Insert(glyph.Bounds); if (result != null) { Reactor.Math.Rectangle bounds = result.bounds; //g.DrawImageUnscaledAndClipped(glyph.bitmap, bounds); g.DrawImage(glyph.bitmap, bounds); glyph.Bounds = bounds; glyph.UVBounds = new Vector4((float)bounds.X / (float)width, (float)bounds.Y / (float)width, (float)bounds.Width / (float)width, (float)bounds.Height / (float)width); font.Glyphs[i] = glyph; } else { missed += 1; break; } } width += 1; } if (missed > 0) { MessageBox.Show("Oops, looks like there wasn't enough room!\r\nMissed: " + missed, "Missed Glyphs", MessageBoxButtons.OK); } font.Bitmap = b; return(font); }