Difficulties with using RadialGradientPaint as a lighting system

Hi all
Following the advice of a number of helpful members of this forum I’ve implemented a lighting system for my game engine, using RadialGradientPaints and BufferedImages. For the most part, it works well - the issue arises when I attempt to attach lights to physics bodies, or even position them in certain ways. The gradient itself doesn’t seem to move correctly and this results in an almost blocky view of the light as it moves - instead of moving entirely fluidly it seems to clip.

I’m almost sure this has something to do with some dodgy math somewhere down the line, or my attempts to join everything to Box2D. The effect is visible with the red light on the left - the light’s been pushed upwards and the light has too (it corresponds to the centre of the box) but the paint hasn’t.

Here is the code that I render the lightmap with:


 public void renderLightmap(int camX, int camY, float interpolation) {      
        if (lightMap == null || lightMap.validate(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration()) == VolatileImage.IMAGE_INCOMPATIBLE || loadedMap.lightmapInvalid){
            lightMap = RenderCanvas.makeVolatileImage(Core.canvas.getWidth(), Core.canvas.getHeight());
        }        

        Graphics2D g2 = (Graphics2D) lightMap.getGraphics();
        

        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
        g2.setColor(ambientColour);
        g2.fillRect(0, 0, lightMap.getWidth(), lightMap.getHeight());
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));

        float[] dist = {0.0f, 1.0f};

        for (Light l : loadedMap.lights.values()) {
            if (onScreen((int) l.x * pixelsPerMetre + camX, (int) l.y * pixelsPerMetre + camY, (int) l.radius * pixelsPerMetre, (int) l.radius * pixelsPerMetre) && l.enabled) {
                Color[] colours = {new Color(l.r, l.g, l.b, l.a), BLANK};
                RadialGradientPaint p = new RadialGradientPaint(new Point.Float((l.x - l.radius / 2) * pixelsPerMetre, (l.y - l.radius / 2) * pixelsPerMetre), l.radius * pixelsPerMetre, dist, colours);
                Vec2 vel = l.owner.physicalRepresentation.worldObject.getLinearVelocity();
                
                g2.setPaint(p);
                g2.fillRect(((int) (l.x + (vel.x * interpolation) - l.radius) * pixelsPerMetre) + camX, ((int) (l.y + (vel.y * interpolation) - l.radius) * pixelsPerMetre) + camY, (int) (l.radius * 2) * pixelsPerMetre, (int) (l.radius * 2) * pixelsPerMetre);                
            }
        }

        //loadedMap.lightmapInvalid = false;
    }

Which is called every frame by:


renderLightmap(camX, camY, interpolation);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
g2.drawImage(lightMap, 0, 0, null);

An update method is called for the entity that controls the light thirty times a second:


    public void update() {
        Vec2 pos = this.physicalRepresentation.worldObject.getWorldCenter();        
        
        l.x = pos.x + l.radius / 2;
        l.y = pos.y + l.radius / 2;
    }

physicalRepresentation is a reference to a PhysicsObject object, while its worldObject member is its respective Body in the Box2D world.
So basically, I’m stumped as to why the radialgradientpaint isn’t quite ‘keeping up’ with the light itself, even though its centre moves as it should, it seems to clip funnily.

Thank you for any help.