Making Particles Opaque

Is anyone aware of a way to make the very whitest of white on a graphic used in a ParticleSystem render opaque?  It seems that if any begin/end colors other than white/white are used it renders with a transparency.  I’ve looked through the ParticleSystem settings and played around with the blend states for the ParticleSystem but I haven’t quite found the right combination yet – if one exists.  Any pointers to the setting or a workaround would be greatly appreciated!



Here’s a snapshot (showing status effects of zap, sleep, and poison) of what I’m looking at – I want the bubbles (poison status effect :wink: to render without transparency.  The graphic used consists of absolute black (background) and absolute white (bubble).



Mmm… do the textures have an alpha channel? have you tried that?

I tried both with and without alpha channels on the graphic.  I have not yet looked at the handling in the ParticleSystem class yet.  Here are a couple of test graphics if you want to have a go at it ; - )



no alpha:





with alpha (the question mark is white, black dots are corner markers):

I guess the only way is to override the BlendState manually? If you render them as Opaque your particles will be rendered inside an ugly black square, don't see why you would want that.

"I guess the only way is to override the BlendState manually"



I tried that and I got the ugly black state you saw. 

i'll post a solution in ~6-8 hours, if you can be patient :slight_smile: had the same problem. the default setting for particles is additive blending, what you need is "normal" blending

Actually I had the same issue recently. Just render it with SourceAlpha, OneMinusSourceAlpha blend state and make sure the alpha in the bubble image is correct.

HamsterofDeath said:

i'll post a solution in ~6-8 hours, if you can be patient :) had the same problem. the default setting for particles is additive blending, what you need is "normal" blending


and...

Momoko_Fan said:

Actually I had the same issue recently. Just render it with SourceAlpha, OneMinusSourceAlpha blend state and make sure the alpha in the bubble image is correct.


I'm still not finding quite where to make this change,  for example the code for blending the particles (I believe) is associated directly with the particle system definition, thus:


// ...
// end of particle system (particleSys) definition

      BlendState as = (BlendState) particleSys.getRenderState(RenderState.RS_BLEND);
      if (as == null) {
         as = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
         as.setBlendEnabled(true);
         as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
         as.setDestinationFunction(BlendState.DestinationFunction.One);
         as.setTestEnabled(true);
         as.setTestFunction(BlendState.TestFunction.GreaterThan);
         particleSys.setRenderState(as);
         particleSys.updateRenderState();
      }

// z-buffer setup and the rest...



If I set the SourceFunction to OneMinusSourceAlpha then the particle system doesn't display at all.  So, I'm guessing that this override has to take place somewhere else, but where?  A code slice would be nice ;)

I'm confused - if you use a texture with the appropraite transparency and don't use alpha blending, does that not give the correct appearence? (like the question marks)

Alric said:

I'm confused - if you use a texture with the appropraite transparency and don't use alpha blending, does that not give the correct appearence? (like the question marks)


The correct appearance in this case should be that anything that is absolute white in a graphic with proper alpha blending should not be transparent --  Only the regions with alpha blending should be.

See the below screen shot from something else that I'm working on (modified for use here -- particles are larger and with longer lifespans) but using the q-2.png graphic from above.  Not applying the alpha blending results in the area that should be transparent showing up as black.

Sorry I meant to type additive blending - so with alpha blending to make the right areas opaque/transparent, rather than additive blending which goes off color.

Alric said:

Sorry I meant to type additive blending - so with alpha blending to make the right areas opaque/transparent, rather than additive blending which goes off color.


Given that, how would that be set up in the case of working with particles?  I'm still missing something here.

Just reread the posts and I think it's what you were already talking about with Momoko fan - but it's set in the destination function not source (or particle editor has a handy check box  :D).



I hacked up one of the jmetests and used your question mark graphic (the one with blobs in the corners) to test it:



public class TestParticleCreating extends SimpleGame {

    public static void main(String[] args) {

        TestParticleCreating app = new TestParticleCreating();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }
   
   public void simpleInitGame() {
      try {
           MultiFormatResourceLocator texture_locator = new MultiFormatResourceLocator(getURL("data/textures/"), ".jpg", ".png", ".tga");
           ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE, texture_locator);
       } catch (URISyntaxException e) {
           e.printStackTrace();
       }
      
      Sphere s = new Sphere("s", 12, 12, 100);
      s.setLightCombineMode(LightCombineMode.Off);
      s.setRandomColors();
      s.setModelBound( new BoundingBox() );
      s.updateModelBound();
      
      rootNode.attachChild(s);
      s.setLocalTranslation(0, 0, -200);
      
      rootNode.attachChild( createParticleEffect() );
   }
   
   public ParticleMesh createParticleEffect() {
      ParticleMesh mesh = null;
         BlendState as1 = display.getRenderer().createBlendState();
         as1.setBlendEnabled( true );
         as1.setSourceFunction( BlendState.SourceFunction.SourceAlpha );
         //as1.setDestinationFunction( BlendState.DestinationFunction.One );
         as1.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
         as1.setTestEnabled( true );
         as1.setTestFunction( BlendState.TestFunction.GreaterThan );
         as1.setEnabled( true );

         TextureState ts = display.getRenderer().createTextureState();
         ts.setTexture(
                 TextureManager.loadTexture(
                       getURL("data/textures/q-2.png"),
                         Texture.MinificationFilter.Trilinear,
                         Texture.MagnificationFilter.Bilinear ) );
         ts.setEnabled( true );

         mesh = ParticleFactory.buildParticles("particles", 10);
         mesh.setEmissionDirection( new Vector3f( 1f, 0f, 0f ) );
         mesh.setControlFlow(false);
         mesh.setReleaseRate(5);
         mesh.setMaximumAngle( 0.0f );
         mesh.setSpeed( 1.0f );
         mesh.setMinimumLifeTime( 750.0f );
         mesh.setMaximumLifeTime( 900.0f );
         mesh.setStartSize( 3f );
         mesh.setEndSize( 5.0f );
         mesh.setStartColor( ColorRGBA.white );
         mesh.setEndColor( ColorRGBA.white );
         mesh.setInitialVelocity( 0.025f );

         mesh.forceRespawn();
        
         mesh.setModelBound(new BoundingBox());
         mesh.updateModelBound();
        
         ZBufferState zbuf = display.getRenderer().createZBufferState();
         zbuf.setWritable( false );
         zbuf.setEnabled( true );
         zbuf.setFunction( ZBufferState.TestFunction.LessThanOrEqualTo );

         mesh.setRenderState( ts );
         mesh.setRenderState( as1 );
         mesh.setRenderState( zbuf );
        
         return mesh;
   }
}

Alric – try your test with colors other than white as you can’t see what I’m talking about using white on white.  Try, magenta and magenta or a combination of colors.



Just to be clear, what I would like to happen is that no blending takes place in the scene on a particle where the graphic representation of it (q-2.png, in this case) is absolute white – meaning that you can’t see the background or other particles through it – and I would like that to last from the birth to the death of the particle.



Here’s a visual mock-up:







Color explanations: grey is distant background, red is a mid-distance object, brown is a near-distance object, and the purple question mark simulates a particle that is between the brown and red objects (and is at mid-life in turning from dark purple to magenta).


Well I'm not blonde or senior but I'm clearly having some sort of moment  :-o

Well… I could be off my rocker by keeping up with this line of inquiry, but I moreso hope that your moment was caused only by my choice of colors :wink:


Out of curiosity, what was the problem just using 24bit pngs?

basixs said:

Out of curiosity, what was the problem just using 24bit pngs?


The problem is that instead of rendering like the left image in the mock-up visual above, it renders like the right side -- where you can see obects more distant to it through its transparency, even where the image is specified as absolute white.  There are some cases when I would like the absolute white areas of a particle image file to render opaque.

I believe that I'm using a png with the correct alpha -- created in The GIMP and saved as png with default settings.  See the question mark png nearer the top of this thread.  If there's something wrong with my image type, then I am unaware of it.

It sounds like what you want is to use a texture with an alpha channel (like your q-2.png) and to use alpha based blending (SourceAlpha, OneMinusSourceAlpha – in the editor, you would turn OFF the additive blending checkbox).  Finally, you'd want to make sure you set the alpha in your vertex coloring to always be fully on (in the editor, alpha=255.  in code, that's 1.0f)



Doing all of these three steps in the editor gives me colorable particles with a transparent background and an always opaque foreground.

renanse said:

Doing all of these three steps in the editor gives me colorable particles with a transparent background and an always opaque foreground.


Thanks for the checklist.  It works.  In code (for posterity) the BlendState for this situation looks like:


BlendState bs = (BlendState) particleSys.getRenderState(RenderState.RS_BLEND);
bs = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
bs.setBlendEnabled(true);
bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
bs.setTestEnabled(true);
bs.setTestFunction(BlendState.TestFunction.GreaterThan);