Terrain Painting

Hi to all.

I have been struggling with this for a long time now and need some help?

I am trying to do runtime terrain painting on a splat texture at the same time

update the texture image without having a noticable drop in performance.

Can anyone please direct me the right way?

I basically want to paint on the transparent splat texture!


A splatting shader comes to me in mind.

We have done theme tests with this.

Per alpha map you can have 4 different textures. If you want more you need additional alphamaps.

For each texture and alpha you need a textureunit.

The implementation depends on the graphichardware.

If you have old hardware you may need to use multi render passes.

If you have need hardware you can implement a shader with sufficient textureunits.

A shader has the advantage of saving memory.

Is this somethink you think of?

i think what he is asking is how to update the alpha texture used for splatting at run-time(and in realtime)

two ways could be:

  • use the same technique as jmedesktop and get the data buffer from the image backing the texture and rebuild it after update through glubuild2dmipmaps for example
  • the render to texture technique

    on madlion's comments:
  • with shader support you can combine 4 alpha texture into one, putting the textures alpha into each channel of the new texture(rgba), and thus render 4 splats per pass
  • without shader support you have to draw one pass per splat layer

    here is a sample of how i did something similar (probably too slow for your "no noticable drop" criteria)

    sample usage

      DrawableTexture drawableTexture = new DrawableTexture(64);
      drawableTexture.setPixelColor(32, 32, ColorRGBA.blue);

      Box box = new Box("box", new Vector3f(-100, -100, -100), new Vector3f(100, 100, 100));
      TextureState ts = display.getRenderer().createTextureState();
      ts.setTexture(drawableTexture.getTexture(), 0);

      //and in your update loop, just fiddle with setPixelColor and do updateTexture,
      //or build nicer fill methods that can take a texture as brush input to fill pixels with...


import com.jme.image.Texture;
import com.jme.renderer.ColorRGBA;
import com.jme.system.JmeException;
import com.jme.util.LoggingSystem;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Util;
import org.lwjgl.opengl.glu.GLU;

import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.logging.Level;

 * MrCoder
public class DrawableTexture {
   private Texture texture;
   private byte[] data;
   private com.jme.image.Image image;
   private BufferedImage awtImage;
   private final int imageSize;

   public DrawableTexture(int imageSize) {
      this.imageSize = imageSize;

   private void initialize() {
      texture = new Texture();

      awtImage = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_4BYTE_ABGR);
      ByteBuffer scratch = ByteBuffer.allocateDirect(
            4 * imageSize * imageSize).order(
      data = (byte[]) awtImage.getRaster().getDataElements(0, 0,
            awtImage.getWidth(), awtImage.getHeight(), null);
      image = new com.jme.image.Image();


   public void updateTexture() {
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureId());
      GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);

      awtImage.getRaster().getDataElements(0, 0, awtImage.getWidth(), awtImage.getHeight(), data);
      ByteBuffer scratch = image.getData();

      ByteBuffer data = image.getData();

      GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, GL11.GL_RGBA8, image.getWidth(),
            GL11.GL_UNSIGNED_BYTE, data);


   public void setPixelColor(int x, int y, ColorRGBA color) {
      if(x < 0 || x >= awtImage.getWidth() || y < 0 || y >= awtImage.getHeight()) {
         LoggingSystem.getLogger().log(Level.SEVERE, "Pixel position is out of bounds!");
         throw new JmeException("Pixel position is out of bounds!");

      int a = (int) (color.a * 255.0f);
      int r = (int) (color.r * 255.0f);
      int g = (int) (color.g * 255.0f);
      int b = (int) (color.b * 255.0f);
      awtImage.setRGB(x, y, (a << 24) | (r << 16) | (g << 8) | (b));

   public void fillTexture(ColorRGBA fillColor) {
      for(int i = 0; i < awtImage.getHeight(); i++) {
         for(int j = 0; j < awtImage.getWidth(); j++) {
            int a = (int) (fillColor.a * 255.0f);
            int r = (int) (fillColor.r * 255.0f);
            int g = (int) (fillColor.g * 255.0f);
            int b = (int) (fillColor.b * 255.0f);
            awtImage.setRGB(i, j, (a << 24) | (r << 16) | (g << 8) | (b));

   public Texture getTexture() {
      return texture;

   public BufferedImage getAwtImage() {
      return awtImage;

   public int getImageSize() {
      return imageSize;

…but it works fast enough for me to do real-time lightmap generation on a terrain with a moving "sun"

Thank you for the great advice, but my problem is a lot

more simple than that!

I just want to change a Texture's buffered image on every loop and

then update what you see on screen.

I don't want to recreate the texture every loop!

Any ideas?

So the only think that changes is the terrain texture, right?

If you are using a shader the texture will recreated/updated on every loop. The shader is executed every rendering loop. Everytime a vertex, fragment/pixel is redrawn (i'm right?).

So if you are use somethink like MrCoder posted to update a texture imagebuffer the shader will do the rest in realtime.

Is this what you want?

I'm no expert but i think this is the way to do want you want. If i understand what you want.

tGiantLabs said:

Thank you for the great advice, but my problem is a lot
more simple than that!

I just want to change a Texture's buffered image on every loop and
then update what you see on screen.

I don't want to recreate the texture every loop!

Any ideas?

well, that's exactly what the code i posted does...

Not exactly what I want. Lets me try the question again.

How can I update an existing texture which image have changed? My current code is

as follows but doesn't seem to work:

           Texture texture = texturemanager.getTexture();
            texture.setImage(TextureManager.loadImage(textureGenerator.getImageIcon().getImage(), true));
            getTextureState().setTexture(texturemanager.getTexture(), 0);

Suppose to work, right?

i don't understand what you mean either :slight_smile:

are there any other way of getting the texture into opengl than glTexImage2D/gluBuild2DMipmaps etc?

my code doesnt rebuild the texture, it just updates the opengl-bound texture with the new image data…

maybe i'm just too tired today :slight_smile:

Well, you can always replace the entire texture… which seems to be what tGiantLabs wants to do.

However, it looks like you're using the same Texture object instead of making a new one. That's ok actually, as long as you reset the texture id first (to 0).

Of course, the getImageIcon -> getImage -> BufferedImage -> ByteBuffer process isn't exactly fast. Maybe you could take a look if (LWJGL)ImageGraphics can be used in your project, that does all the fancy stuff mrCoder talks about for you…

yeah, that's sort of where i got my code from :wink:

and i hope that it's faster than replacing the entire texture…

snip from lwjglimagegraphics almost exactly like my updateTexture method…

Yes, but I mean he could just use ImageGraphics. It works just like any Graphics2D object (which I assume he's using now), and it tracks dirty regions (so it doesn't have to update all of the texture if you change only a bit). Plus it has a very clever mipmap scheme…

ok ok ok :slight_smile: i'll shut up :wink:

Is this still the way to go for run time texture altering