How to render to texture 2 textures blended together with transparency

How can I use render to texture to create two textures, and then apply those two textures in a texturestate onto a quad?

The first one grabs background, (a terrain) the second grabs some quads in various positions around the terrain.  I'd like to regenerate the texture without redrawing the terrain.  This is for a minimap by the way.



When I attempt to render the second texture, the background is solid black, so my attempt to decal blend them just overwrites the first texture.


      tRenderer.render(fakeScene.getChild(0), fakeTex);  //render the terrain object to fakeTex
      tRenderer.render(fakeScene.getChild(2), fakeTex2);   //render the green quad objects to fakeTex2, hopefully without the background
      fakeTex2.setApply(Texture.AM_DECAL);          //decal type should ignore the alpha=0 pixels

      TextureState ts2 = display.getRenderer().createTextureState();
      ts2.setEnabled(true);
      ts2.setTexture(fakeTex,0);
      ts2.setTexture(fakeTex2,1);
        miniMapQuad.copyTextureCoords(0, 1);
      miniMapQuad.setRenderState(ts2);



I also tried to set the background of tRenderer to 0 alpha,

tRenderer.setBackgroundColor(new ColorRGBA(0,0,0,0f));


thinking that might do the trick, but it still captures solid (0,0,0,1) as the background.

Anyone have any idea what I'm doing wrong?

Use a paintable graphics-context.



Here is a simple way to do it (for the second texture):


        tLightMap = new Texture();
        {
           tLightMap.setFilter(Texture.FM_LINEAR);//toggle filter OFF for clean edges
           tLightMap.setMipmapState(Texture.MM_LINEAR_LINEAR); //toggle Mipmap OFF for clean edges
           tLightMap.setWrap(Texture.WM_ECLAMP_S_ECLAMP_T);
           tLightMap.setApply(Texture.AM_COMBINE);
          tLightMap.setCombineScaleRGB(1.0f);
          tLightMap.setCombineFuncRGB(Texture.ACF_MODULATE);
          {//OP 0
             tLightMap.setCombineSrc0RGB(Texture.ACS_TEXTURE);
             tLightMap.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
          }
          {//OP 1
             tLightMap.setCombineSrc1RGB(Texture.ACS_PREVIOUS);
             tLightMap.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
          }
        }
       
        // fill the map with light
        lightMapGfx = ImageGraphics.createInstance(lightMapSize,lightMapSize,1);
        {
           lightMapGfx.setColor(Color.LIGHT_GRAY);
           lightMapGfx.fillRect(0,0,lightMapSize, lightMapSize);
           lightMapGfx.update();
        }
       
        tLightMap.setImage(lightMapGfx.getImage()); // attach lightmap to texture



then you can paint on the 'lightMapGfx ' like Graphics2D:


        int width = 2;
        int depth = 2;
        float intension = 1.0f;

        Point p = new Point(50,50);

       lightMapGfx.setColor(new Color(.1f,.1f,.1f,intension));
       lightMapGfx.fillRect(p.x-(width/2), p.y-(depth/2), width, depth);

        lightMapGfx.update(tLightMap, false);


While that would work it's not exactly fast.



Did you set an AlphaState, beamanbr?

The default RTT target is RGB.  Try calling:


fakeTex2.setRTTSource(Texture.RTT_SOURCE_RGBA);

Oh, btw, you should make that call on the texture before using the texturerenderer's setupTexture method.

I did try an alphastate on the quad, yes.  I also just tried renanses' suggestion about rtt target.  It didn't seem to help, but I think I'm just doing something out of order, or not calling an updateRenderState(); or something.  My codebase is huge now, but this is essentailly what I have:



    private void setupGraphics()
    {
//lots of code above, cut for clairity.....
      tRenderer = display.createTextureRenderer(256, 256, false, true, false, false,
              TextureRenderer.RENDER_TEXTURE_2D,
              0);
      tRenderer.setBackgroundColor(new ColorRGBA(0, 0, 0, 0f));
      fakeTex = new Texture();
      fakeTex2 = new Texture();
      fakeTex2.setRTTSource(Texture.RTT_SOURCE_RGBA);
      fakeTex2.setApply(Texture.AM_DECAL);
      fakeTex.setWrap(Texture.WM_CLAMP_S_CLAMP_T);
      tRenderer.setupTexture(fakeTex);
      tRenderer.setupTexture(fakeTex2);
      tRenderer.getCamera().setLocation(new Vector3f(1100, 2000, 1050f));
      tRenderer.getCamera().lookAt(new Vector3f(1100, 0, 1040f),new Vector3f(0, 1, 0));
      tRenderer.getCamera().setFrustumPerspective(
                45.0f,
                (float)display.getWidth() / (float)display.getHeight(),
                1.0f,
                55000.0f);
      tRenderer.updateCamera();

                refreshMinimapUnits();
        }

   private void refreshMinimap()  //full minimap refresh, works fine but too slow for real-time
   {                                            //assumes minimapquad is single-textured with fakeTex
      mmCounter++;
      if (mmCounter>20)
      {
         mmCounter=0;
         tRenderer.getCamera().setLocation(new Vector3f(1100-mmOffsetx*10, 2000+(mmZoom*50), 1050f+mmOffsety*10));
         tRenderer.render(fakeScene, fakeTex);
         mapNeedsRefresh = false;
      }      
   }
       private void refreshMinimapUnits()
   {
      mapNeedsRefresh = false;

      tRenderer.setBackgroundColor(new ColorRGBA(0,0,0,0f));
      tRenderer.getCamera().setLocation(new Vector3f(1100, 2000+(mmZoom*50), 1050f));
      tRenderer.render(fakeScene.getChild(0), fakeTex);             //when this works, I'll remove this line so only the node
      tRenderer.render(fakeScene.getChild(2), fakeTex2);           //with the quads is rendered, using the old fakeTex
      fakeTex2.setApply(Texture.AM_DECAL);

      TextureState ts2 = display.getRenderer().createTextureState();
      ts2.setEnabled(true);
      ts2.setTexture(fakeTex,0);
      ts2.setTexture(fakeTex2,1);
                miniMapQuad.copyTextureCoords(0, 1);
      miniMapQuad.setRenderState(as);
      miniMapQuad.setRenderState(ts2);
      miniMapQuad.updateRenderState();
   }



By the way, I've worked around this issue by only calling maprefresh if units are moving one in 20 frames.  This cut the framerate issue to negligible, and still looks good.  It just seems to me that this should be and is possible, and is a cool trick that I and others might want to take advantage of in the future.