Soot effect

Hi again,



As a part of the indoor fire effect I’m working on, I’ve put together something that looks kinda like soot being “splatted” onto the wall in contact with a flame. When the particles (a small percentage of them) in the flame touch the wall, they paint dots on a java.awt.image.BufferedImage and I reload a texture with this image and put it on top of the wall texture. Similar to what hevee does here. This seems to be extremely heavy, and it crashes hard (at least in XP it does, it hasn’t crashed in Ubuntu yet) after a while with this info:



java.lang.OutOfMemoryError: Direct buffer memory
   at java.nio.Bits.reserveMemory(Unknown Source)
   at java.nio.DirectByteBuffer.<init>(Unknown Source)
   at java.nio.ByteBuffer.allocateDirect(Unknown Source)
   at com.jme.util.geom.BufferUtils.createByteBuffer(BufferUtils.java:850)
   at com.jme.util.TextureManager.loadImage(TextureManager.java:675)
   at com.jme.util.TextureManager.loadTexture(TextureManager.java:432)
   at com.jme.util.TextureManager.loadTexture(TextureManager.java:423)
   at no.hig.nilspl.SootSplatter.splat(SootSplatter.java:243)
   at no.hig.rss.SurfaceInfluence.apply(SurfaceInfluence.java:65)


Is this just the wrong way to do things? Could I get the same effect with Renderer.updateTextureSubImage() and in that case, is it an easy way to get a com.jme.image.Image out of a BufferedImage? They look kinda incompatible to me..  :(

It looks like this from behind. The horizontal "line" happens because of the roof/ceiling between first and second floor.


Here's the important section of my code:


Vector2f offset = calculateTextureOffset(tri.getNormal(), store, tm);
      
// Get the image for the spatial and paint a dot on it.
TextureState ts = (TextureState)s.getRenderState(StateType.Texture);      
int width = ts.getTexture(1).getImage().getWidth();
int height = ts.getTexture(1).getImage().getHeight();
      
Graphics2D g2d = (Graphics2D)images[index].getGraphics();
g2d.setColor(SOOT_COLOR);
g2d.fillOval( (int)(width*offset.x), (int)(height*offset.y), 3, 3);
      
// Create a new texture from the updated image and put it back
// onto the spatial.
      
TextureManager.releaseTexture(ts.getTexture(1));
Texture newTex = TextureManager.loadTexture(images[index],
      Texture.MinificationFilter.Trilinear,
      Texture.MagnificationFilter.Bilinear, 1, false);
ts.setTexture(newTex, 1);
s.updateRenderState();      


Are there such things as rendertargets for OpenGL (JME) as with DirectX?  It seems to me that it would be a better option to do this stored in GPU-side memory instead of CPU-side memory, so you don't get this OutOfMemoryError.  That looks like the technique you would use for a rendertarget.

To avoid the memory problem, can you try also a texState.deleteTextureId(x) after release Texture?

instead of reloading the texture you can just update it from a buffer. have a look at LWJGLTextureUpdater or jmedesktops backing canvas to get an idea about that.

Thank you for your replies  :slight_smile:


texState.deleteTextureId(x)


I tried this, but sadly it did not work.

I'm gonna try to get it to work with LWJGLTextureUpdater, but I'm having trouble getting image data from a BufferedImage into a ByteBuffer..
nednull said:

I'm gonna try to get it to work with LWJGLTextureUpdater, but I'm having trouble getting image data from a BufferedImage into a ByteBuffer..


Maybe you can get ideas from TestMultiFaceBox which creates a Texture from a BufferedImage.
http://code.google.com/p/jmonkeyengine/source/browse/trunk/src/jmetest/shape/TestMultiFaceBox.java