Showing posts with label font. Show all posts
Showing posts with label font. Show all posts

Sunday, July 18, 2010

Performance and Shapes

The functionality is really starting to come together on Sgine, but the performance has been a bit lower than I had hoped for large scenes. For simple games and business applications Sgine is performing quite well, but it's definitely not yet ready to write a first-person shooter on yet.

I've spent a bit of time doing performance tweaking and optimizations with YourKit and the performance is getting better, but still not where I'd like to see it. Right now I've got 400 cubes (which is made up of four independent Images for greater complexity) rotating and animating back and forth across the screen via easing effect at 38fps:



Not terrible, but over the next few weeks I'm hopeful I can get 4,000 cubes rendering at over 60fps.

Another quick note is that I've created a little Shape system in Sgine that will hopefully eventually be the core of all rendering as it auto-detects and uses additional capabilities of the video card for better performance. Additionally, I've added support for java.awt.Shape to ShapeData to draw nifty things like vector-text directly from a java.awt.Font to the screen. This is not the Shape-to-Texture cheating that most of the other engines do, this is direct to screen via tesselation. I've turned off any anti-aliasing so you can see it for yourself:



I've still got more work before I'm finished with the new Shape system, but once it is done I think this should help me get to the framerates I'm looking for.

Saturday, May 22, 2010

ResolutionNode

I'm back from a week long cruise to the Caribbean without cell phones, computers, or internet access. It was a great break from technology, but now I'm back, refreshed, and ready to crank out more functionality into Sgine.

What I have today is called ResolutionNode. If you look back at all the blogged examples below you'll notice all the 'z' translation stuff on the components. The reason for that is because Sgine (and OpenGL generally) is configured to have 'z' at 0.0 have a distance of -1.0 to 1.0 both vertically and horizontally. Further, anything between 0.0 and -1.0 (negative to back further into the screen) is clipped for mathematical precision reasons. So by pushing the the components to something like -1000.0 for 'z' causes it to appear much smaller because its depth is so far back into the projection.

This is fine for games and general 3D applications, but can be a pain in the neck when you want to have a normal graphics-based UI and you're expecting a specific resolution (e.g. 1024x768) to design graphics and layout for. To this end I have created a trait called ResolutionNode. It gives the ability to specify a resolution (e.g. 1024x768) and modifies the world matrix for that Node to properly display that resolution to fit to the screen. Not only does this give you the benefit of managing the resolution for the screen, but it also keeps you from having to worry about the *actual* resolution as this will scale-to-fit so even if you are running 1920x1200 resolution if you specify 1024x768 internally you'll end up with everything being stretched to fit.

This is actually part of a larger UI design concept I've been developing that I'll go into more on as the functionality is finalized in Sgine, but for now I give you my example.

The following code takes a 1024x768 image and a 640x480 image and displays them overlayed on top of each other. The cool thing here though is that you can see that using a ResolutionNode container for each I am able to see both of them at the exact same size.

package org.sgine.ui

import org.sgine.core.Color
import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestResolution {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Resolution")
  r.verticalSync := false
  
  val scene = new GeneralNodeContainer()
  
  val r1024 = new GeneralNodeContainer() with ResolutionNode
  r1024.setResolution(1024.0, 768.0)
  scene += r1024
  
  val c1024 = new Image()
  c1024.source := Resource("1024.jpg")
  c1024.alpha := 0.5
  r1024 += c1024
  
  val r640 = new GeneralNodeContainer() with ResolutionNode
  r640.setResolution(640.0, 480.0)
  scene += r640
  
  val c640 = new Image()
  c640.source := Resource("640.jpg")
  c640.alpha := 0.5
  r640 += c640
  
  r.renderable := RenderableScene(scene)
 }
}

The two images I'm using are:



and:



The resulting screenshot is as follows:

Saturday, April 24, 2010

Label, Scale9, FontManager, and Resource

Yes, this is my third post today, but it's Saturday and I'm cranking through code now that I've gotten over the mouse-picking hurdle!

I have created a new component "Label" that is moderately self-explanatory, but represents a single-line of text. With this Resource comes to fruition as a simple lookup call "Resource(resourceName)" that will find a resource in the defined resource paths (defaults to look in "resource" path). Additionally I have created a FontManager that simplifies the management of fonts in the system. I have plans in the long-run to create a bitmap-font generator from AWT fonts, but for now getting a font is as easy as "FontManager("Arial")" presuming there's an AngelCode font definition in the Resource lookup path by the name of "Arial.fnt".

See the following test of Label:

package org.sgine.ui

import scala.io.Source

import org.sgine.input.event.MousePressEvent

import org.sgine.render.Renderer
import org.sgine.render.font.FontManager
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestLabel {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer()
  val component = new Label()
  component.location.z := -500.0
  component.font := FontManager("Franklin")
  component.text := "Hello World!"
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Even more exciting is Scale-9 (a.k.a nine-slice) support that opens up more advanced skinning functionality and in the short-run allows creation of pretty buttons; bet you can guess what's up next. ;)

Anyway, here's a quick test using the new Scale9 component:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestScale9 {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Scale-9")
  
  val scene = new GeneralNodeContainer()
  
  val component = new Scale9()
  component(Resource("scale9/windows/button/hover.png"), 3.0, 3.0, 4.0, 5.0)
  component.width := 200.0
  component.height := 50.0
  component.location.z := -500.0
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Here's a screenshot of the application:



That's using a pretty Windows 7 skinned button in a hover state.

Friday, April 2, 2010

AngelCode Fonts - Kerning

I already did most of the legwork earlier this week, but hadn't gotten around to turning on support for kerning, but that's all changed now:



Pretty easy to see the benefits of kerning here. However, this example also shows I seem to have a little problem with my low-hanging characters like 'g' and 'p'. Hopefully that will be fixed in the next update.

For now, here's the source:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m1 = Matrix4().translate(x = -200.0, z = -1000.0)
  val m2 = Matrix4().translate(x = -200.0, y = -25.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](5)
  a(0) = MatrixState(m1)
  a(1) = () => font.drawString("VAST Kerning Example Enabled", true)
  a(2) = MatrixState(m2)
  a(3) = () => font.drawString("VAST Kerning Example Disabled", false)
  a(4) = fps
  r.renderable := RenderList(a)
 }
}

A couple more days of effort and we can hopefully dig into some much more interesting features. :)

Wednesday, March 31, 2010

AngelCode Fonts - Second Steps

I was determined to get some more work done on this today after my sorry screenshot I posted last night. I've added parsing support to kerning but have not implemented it graphically. Hopefully I'll get around to that tomorrow. However, the xOffset, yOffset, and xAdvance functionality is working now and I have a much better screenshot to post:



I've also cleaned up the process by adding a "drawString" method to AngelCodeFont. See the following example code:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(x = -70.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](3)
  a(0) = MatrixState(m)
  a(1) = () => font.drawString("Hello World!")
  a(2) = fps
  r.renderable := RenderList(a)
 }
}

Tuesday, March 30, 2010

AngelCode Fonts - First Steps

I spent a little bit of time the past couple of evenings writing a parser in Scala to process AngelCode font files so sgine could support bitmap fonts and though the actual results look a bit sad, the progress is quite nice. :)

Now, I know this looks ugly, but for a combined time of less than two hours I think it's some decent progress:



You'll notice the x and y offsets are not specified, and I sort of hard-coded multi-character rendering, but still, it's a start. :)

Here's the code required:
package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](13)
  a(0) = MatrixState(m)
  a(1) = () => font('H').draw(-60.0)
  a(2) = () => font('e').draw(-40.0)
  a(3) = () => font('l').draw(-20.0)
  a(4) = () => font('l').draw(0.0)
  a(5) = () => font('o').draw(20.0)
  a(6) = () => font(' ').draw(40.0)
  a(7) = () => font('W').draw(60.0)
  a(8) = () => font('o').draw(80.0)
  a(9) = () => font('r').draw(100.0)
  a(10) = () => font('l').draw(120.0)
  a(11) = () => font('d').draw(140.0)
  a(12) = fps
  r.renderable := RenderList(a)
  
  println("Renderer started! " + 81.asInstanceOf[Char] + " - " + font.face + ", " + font.size)
 }
}

Next step is to properly support drawing of Strings correctly. More to come soon.
Scala Engine for high-performance interactive applications.