Java custom Paint implementation performance issue

2019-05-14 16:57发布

问题:

I'm using Java to create a game, and I'm using TexturePaint to texture areas in the background. Performance is fine using java.awt.TexturePaint, however, I want to have areas having an inherent rotation, so I tried implementing a custom Paint called OrientedTexturePaint:

public class OrientableTexturePaint implements Paint {

    private TexturePaint texture;
    private float orientation;

    public OrientableTexturePaint(TexturePaint paint, float orientation)
    {
        texture = paint;
        this.orientation = HelperMethods.clampRadians((float)Math.toRadians(orientation));
    }

    public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) 
    {
        AffineTransform newTransform = (AffineTransform)xform.clone();
        newTransform.rotate(orientation);
        return texture.createContext(cm, deviceBounds, userBounds, newTransform, hints);
    }

    public int getTransparency() 
    {
        return texture.getTransparency();
    }


}

Only problem is, there's a huge performance hit: the frame rate drops from a comfortable (capped) 60fps to about 3fps. Furthermore, if I implement this as a pure wrapper to TexturePaint - without creating the new transform, simply passing the arguments to TexturePaint's methods and returning what TexturePaint returns, I get the same result.

i.e.:

public class MyTexturePaint implements Paint {

    private TexturePaint texture;

    public OrientableTexturePaint(TexturePaint paint, float orientation)
    {
        texture = paint;
    }

    public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) 
    {
        return texture.createContext(cm, deviceBounds, userBounds, xform, hints);
    }

    public int getTransparency() 
    {
        return texture.getTransparency();
    }
}

performs massively worse than TexturePaint does. How come, and is there any way to get around this?

回答1:

I would paint the rotated portion to a BufferedImage and then paint that to the background. Then you only have to update the BufferedImage when there is a change to the rotated portions.

If you don't create a cache this way, if you do the painting from scratch each time, you have to consider the pipeline of the paint model and how complex that is. Performance is about reducing the bottlenecks in the rendering pipeline, and passing everything through a texturepaint process sounds like a massive bottleneck. Textures are to be created once, used often, not created often, used once.