Particle blending issue

Hey there, I’ve run into a peculiar graphical issue with my game, I’m using the default particle material definition for projectiles and their explosion effects, and oddly enough they appear to be a different (unintended) colour on another PC i tested my game on.

Here is the texture I’m using for the projectile in question:
https://dl.dropboxusercontent.com/u/37297132/plasmaball.png

I’m applying it both as a texture and a glowmap on the material, no other properties are set.
The geometries i apply the material onto are put into the transparent queuebucket (the translucent bucket seems to totally screw up the coloring, also oddly enough, only one instance is drawn at a time)

Here’s how it looks on my PC:
https://dl.dropboxusercontent.com/u/37297132/color_b.png

Here’s how it looks on my mate’s PC:
https://dl.dropboxusercontent.com/u/37297132/color_r.png

It seems on my machine the very first projectile shot has a different alpha falloff than the rest… odd.
On my mate’s pc, all projectiles seem to have this weird alpha falloff, along with the color being red instead of the purple-ish blue I intend to have.

Both of us are using Windows 7 64 bit, my gfx card is an ATI Radeon HD 4730, while my mate’s gfx card is an Nvidia Geforce GTX 760

Any ideas about what could be amiss here? It’s not a terrible issue, but having such seemingly random discrepancies between differing systems is somewhat worrying. I can provide additional information if needed.

Do both machines have the latest graphics driver installed?

My driver isn’t super old, I have Catalyst 13.9, (2013/Oct/28)
Mate’s told me he has a driver version of 332.21, (2014.Jan.7)

Can we see the actual material setup? How are you creating the particles? …and so on.

Usually I expect nvidia to be the “right way” especially with the latest drivers… which means it’s strange that it shows red. ATI’s OpenGL implementation is notoriously driver version sensitive.

Ok so I’ve cooked up a test project with all the relevant codes that are involved in making the projectile, I’ve also set up a logic for attaching and detaching them similar to the one I use in my game.

https://dl.dropboxusercontent.com/u/37297132/TestProjectile.zip

I shall correct my earlier statement, previously I said the first shot projectile has more vivid colors, but it’s actually the one farthest away from the camera.

But anyway, tried this snippet on both PCs and the results are the same as before, so whatever’s causing this should be in the code i included in the project linked.

I’ve included all the postprocessing filters that i use.
Without bloom and the glowmap set, only the farthest projectile is drawn. Even if i set depthwrite to true on the material’s getAdditionalRenderState.

I suppose the furthest projectile is somehow drawn twice when bloom is on? Would explain why the farthest one has the more vivid colors.
Just tried setting the queuebucket to translucent and it also only draws the farthest away instance of the projectile, and the colors are all messed up (orangish-greenish), regardless of depthwrite.

I wish there was some way to illustrate this in a simpler one class test that could be posted directly. It will probably be a week before I have time to unzip someone else’s project.

Hopefully others are not as time constrained. Especially since I bet seeing the code will spot the problem right away.

@pspeed said: I wish there was some way to illustrate this in a simpler one class test that could be posted directly. It will probably be a week before I have time to unzip someone else's project.

Hopefully others are not as time constrained. Especially since I bet seeing the code will spot the problem right away.

One problem with posting code directly is that the forum messes up double quotes.

The test project is in fact a single-class project, but there is something strange about the project configuration. In order to get it to run I had to paste the source code into a fresh BasicGame project.

If folks want to stare at the code, here it is:
[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.post.filters.FXAAFilter;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.control.BillboardControl;
import com.jme3.scene.shape.Box;
import com.jme3.util.BufferUtils;
import java.util.ArrayList;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    public static void main(String[] args) {
    Main app = new Main();
    app.start();
    }

    Mesh SpriteMesh = new Mesh();
    Material PlasmaDefaultMaterial;

    ArrayList<Geometry> Projectiles = new ArrayList<Geometry>();

    float ShootTimer = 0;
    float ShootDelay = 0.085714f;

    @Override
    public void simpleInitApp() {

     flyCam.setMoveSpeed(16f);
     
     float halfbsize = 0.5f;
     int [] indexes = { 2,0,1, 1,3,2 };
     Vector3f [] vertices = new Vector3f[4];
     vertices[0] = new Vector3f(-halfbsize, -halfbsize, +halfbsize);
     vertices[1] = new Vector3f(+halfbsize, -halfbsize, +halfbsize);
     vertices[2] = new Vector3f(-halfbsize, +halfbsize, +halfbsize);
     vertices[3] = new Vector3f(+halfbsize, +halfbsize, +halfbsize);
     Vector2f[] texCoord = new Vector2f[4];
     texCoord[0] = new Vector2f(0,0);
     texCoord[1] = new Vector2f(1,0);
     texCoord[2] = new Vector2f(0,1);
     texCoord[3] = new Vector2f(1,1);
     SpriteMesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
     SpriteMesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
     SpriteMesh.setBuffer(Type.Index,    3, BufferUtils.createIntBuffer(indexes));
     SpriteMesh.setStatic();
     SpriteMesh.updateBound();
     
     PlasmaDefaultMaterial = new Material(getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
     PlasmaDefaultMaterial.setTexture("Texture", getAssetManager().loadTexture("Textures/plasmaball.png"));
     PlasmaDefaultMaterial.setTexture("GlowMap", getAssetManager().loadTexture("Textures/plasmaball.png"));
    
     FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
     
     CartoonEdgeFilter toon=new CartoonEdgeFilter();
     toon.setEdgeColor(ColorRGBA.Black);
     fpp.addFilter(toon);
     
     // Radius, intensity, scale, bias
     //SSAOFilter ssaoFilter = new SSAOFilter(12.94f, 13.92f, 0.33f, 0.61f);
     
     FXAAFilter AA = new FXAAFilter();
     fpp.addFilter(AA);
     
     SSAOFilter ssaoFilter = new SSAOFilter(1.25f, 4.0f, 1.0f, 0.33f);
     fpp.addFilter(ssaoFilter);
     
     BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);
     bloom.setBlurScale(1.0f); // Default: 1.5f
     bloom.setExposurePower(5f); // Default: 5f
     bloom.setExposureCutOff(0.0f); // Default: 0f
     bloom.setBloomIntensity(1f); // Default 2f
     //bloom.setDownSamplingFactor(1.0f); 
     fpp.addFilter(bloom);
     
     FogFilter fog;
     fog=new FogFilter();
     fog.setFogColor(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f));
     fog.setFogDistance(500); // 500
     fog.setFogDensity(8); // 16
     //fpp.addFilter(fog);
     
     viewPort.addProcessor(fpp);
    

    }

    public void ShootNewProjectile()
    {
    Geometry newProj = new Geometry(“derp”, SpriteMesh);
    newProj.setMaterial(PlasmaDefaultMaterial);
    newProj.setQueueBucket(RenderQueue.Bucket.Transparent);
    BillboardControl BC = new BillboardControl();
    newProj.addControl(BC);
    newProj.setLocalScale(0.6f);
    Projectiles.add(newProj);
    rootNode.attachChild(newProj);
    }

    @Override
    public void simpleUpdate(float tpf) {
    ShootTimer -= tpf;
    if(ShootTimer <= 0)
    {
    ShootTimer = ShootDelay;
    ShootNewProjectile();
    }

     ArrayList&lt;Geometry&gt; UpdateProjectiles = (ArrayList&lt;Geometry&gt;)Projectiles.clone();
     while(!UpdateProjectiles.isEmpty())
     {
         Geometry Pick = UpdateProjectiles.get(0);
         Pick.move(0, 0, -7.5f*tpf);
         if(Pick.getLocalTranslation().z &lt; -10f)
         {
             Projectiles.remove(Pick);
             rootNode.detachChild(Pick);
         }
         UpdateProjectiles.remove(0);
     }
    

    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }
    [/java]

So some random things looking at the code:

-you are using the particle material but you are still rendering quads… so what happens if you instead just use Unshaded? Thought: I’m wondering if the particle shader is getting confused about point sprite versus not point sprite (which would be a bug)

-what happens if you comment out: viewPort.addProcessor(fpp); Let’s just remove post processing completely from the equation for a bit. Disabling the filters is not the same thing since at various times there were bugs relating to this. Best just not to include them at all until everything else is working like it’s supposed to.

-is there a particularly good reason for doing the clone shuffle in this loop?
[java]
ArrayList UpdateProjectiles = (ArrayList)Projectiles.clone();
while(!UpdateProjectiles.isEmpty())
{
Geometry Pick = UpdateProjectiles.get(0);
Pick.move(0, 0, -7.5f*tpf);
if(Pick.getLocalTranslation().z < -10f)
{
Projectiles.remove(Pick);
rootNode.detachChild(Pick);
}
UpdateProjectiles.remove(0);
}
[/java]

It’s not the problem but I’m just wondering if you know about Iterator and Iterator.remove().
[java]
for( Iterator it = Projectiles.iterator(); it.hasNext(); ) {
Geometry geom = it.next();
geom.move(0, 0, -7.5f*tpf);
if( geom.getLocalTranslation().z < -10f ) {
geom.removeFromParent();
it.remove();
}
}
[/java]

I really should’ve tried using the unshaded definition, because it works like a charm, and there doesn’t seem to be a difference in performance. The projectiles don’t blend together quite as well though…

Commenting out the FilterPostProcessor seems to make no difference (aside from the absence of its intended effect, of course)

I’m probably using the particle definition wrong… is there actually a way to draw sprites in a more efficient manner than how I was doing it up until now?

I did in fact have no idea about the existance of Iterator, cloning the list was the best idea I could come up with to avoid accidentally skipping an entity if the list’s indexes changed during an update cycle. It didn’t seem to create any crazy GC freeze with some few hundreds of entities in the list, so I was content but not happy with it. Thanks for pointing it out for me!

Also, I had the opportunity to test my game on yet another PC, Nvidia card, same results as on my mate’s comp, so it seems a difference between how the different card vendors handle it with their drivers.
At this point I’m pretty sure that even on my PC the particles aren’t drawn the “correct way”, it just happens to be closer to the intended color by chance. It’s a damn shame too, because the blending was so silky smooth compared to the unshaded def.

The main difference between the “non working” particle.j3md way and your “better working” unshaded.j3md way is the fact that particle always turns on point sprite mode and sets alpha additive blending. If you set AlphaAdditive blend mode on your unshaded material then you should get similar blending. For the intended effect, it’s probably more appropriate.

re: ATI, it could be that treating a point sprite material like a quad material was confusing it where is it confuses nvidia in a different way.

It’s not that. I already knew I had to set additive alpha blending, the thing I was missing are the softened edges. Besides, disabling the pointsprite property makes no difference whatsoever.
Neither of these lines did anything
[java]PlasmaDefaultMaterial.getAdditionalRenderState().setPointSprite(false);
PlasmaDefaultMaterial.setBoolean(“PointSprite”, false);[/java]
I even decided to just make a copy of the particle matdef and edit it to make sure
[java]RenderState {
Blend AlphaAdditive
DepthWrite Off
PointSprite Off
// AlphaTestFalloff 0.01
}[/java]

By the way, is there a way to make AO and the edge filter ignore the unshaded sprites, aside from using the translucent bucket? I’d like to keep the bloom effect on it.

Here’s how particle made them look
https://dl.dropboxusercontent.com/u/37297132/Screenshot%202014-01-26%2010.12.14.png
Here’s how it is with unshaded
https://dl.dropboxusercontent.com/u/37297132/Screenshot%202014-01-26%2010.15.47.png
And here’s how it looks without bloom
https://dl.dropboxusercontent.com/u/37297132/Screenshot%202014-01-26%2010.16.19.png

For anyone stumbling into this issue in the future, I managed to get around it.
It’s not a “fix” per se, rather a simple edit to the particle material definition.
Basically what I did was make it use the softparticle vert and frag files across all the different render modes, and it looks as intended now on all PCs i’ve tried it on.