Trouble with transparency

I am loading png files with alphas onto a Cardmaker object.
I add resulting nodepaths to a bin for rendering sprites after rendering rest of my scene.

Problem:
When I render in my scene - I get nice alpha edges when sprite is close but bad blends when far away.
Same sprite is on right and left side in image below. The nice one on the right was ugly like the left a few frames previous.
Any ideas on proper approach to have nice alpha blending at all distances from camera ?

   def demo(self, parent, edgelength=1 ):
        self.ts = TextureStage('ts')
        self.ts.setMode(TextureStage.MAdd)
        card = CardMaker("tilesheet")
        card.setFrame(-edgelength, edgelength, -edgelength, edgelength)
        card.setColor(0,0,0,1)
        tile = NodePath(card.generate())
        tile.setTransparency(TransparencyAttrib.MAlpha)
        tile.reparentTo(parent)
        tile.setTexScale(self.ts, sizeCELLS, sizeRAWS)
        texture = loader.loadTexture("BLOB_SEQ.png")
        tile.setTexture(self.ts, texture)
        return tile

self.cbm = CullBinManager.getGlobalPtr()
self.cbm.addBin("sprites", CullBinManager.BTBackToFront, 55)

tile.setBin("sprites", 2)

See picture here:

I’m not sure what I see on the screenshot, but if there are multiple overlapping (semi-)transparent object then it’s a good idea to try ‘MDual’ mode for the transparency.

tile.setTransparency(TransparencyAttrib.MDual) 

Instead of setTransparency try setting the colorblend function directly

self.npFlareRoot.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOneMinusIncomingColor ) )

On a minor side-note, may I say that whatever I’m seeing there is rather lovely, and ask first what your game is and how you made those smooth trails?

Interestingly this made the problem slightly worse. Specifically the bad masking stays visible until the sprite gets much closer to the camera. So setTransparency must be doing something in addition to this attribute setting ?

Wezu - Alas its just one image. I tried MDual - no difference to MAdd.

The issue is related to the sprites changing screen size. As they get closer to the camera, they get bigger - at some point the alpha mask works.
I might have guessed something to do with changing mipmap levels (perhaps alpha not being used on any other than the topmost level) - but I don’t have that turned on.

Its also worth noting that if the initial image is 1024 or 128 square - there is no difference to the on-screen behaviour.

Two more images as examples (with fog turned off for easier viewing of the problem):


Thaumaturge - its a rollercoaster art based project. I will release it (less art) when its done.

It looks very interesting. :slight_smile:

As to your problem, I note a two things that seem as though they may be relevant:

  1. Looking at your first image, I note that the sprite on the right shows the background, but not the pipe/cable/whatever that is that seems to run behind it.

  2. When you call setAttrib, you use “OOneMinusIncomingColor” as the final parameter; are you confident that this is what you want? I believe that standard “additive blending” would use “OOneMinusIncomingAlpha” (ColorBlendAttrib.OOneMinusIncomingAlpha) in place of that. Have you tried “OOneMinusIncomingAlpha”, with the other parameters unchanged?

Oh nice job. well caught. This change made the setAttrib call work the same as the setTransparency call.
Good to know how to do.

Here’s how it looks now. You can see the more distant sprite is still ‘bad’.

and your BG comment above prompted me to try a different bg color. and to remove my special bin. so with no bin use at all (which doesn;t seem to affect the issue:

I admit to surprise that my other tubes’s alphas reveal the BG instead of the surrounding tube.
I expect its all related to the same issue.
I am setting the object to transparency (using alphas embedded in png textures) using:

tex = loader.loadTexture(texture)
self.ts = TextureStage('ts'+label)
self.ts.setMode(TextureStage.MReplace)
self.tunnel.setTransparency(TransparencyAttrib.MAlpha)
#self.tunnel.setBin("transparent", 2)
self.tunnel.setTexture(self.ts, tex)

If I change that setTransparency call to the setAttrib call I get:

Hmm…

It looks as though the sprite is being drawn before the the tube, or generating a nearer set of z-values than does the tube, and writing to the depth buffer, therefore preventing the drawing of the tube in those pixels.

You mentioned a special bin; what was special about it?

In particular, there is, I think, a way to ensure that a given set of nodes draws last, which I might help with your sprites.

I think that this page gives information on how to do so; given that you’re using additive blending, I imagine that the “unsorted” bin should do the job.

(I’m not sure offhand of what to suggest for the pipes, but given that they seemed fine beforehand they might not call for changing.)

yes its an interesting sorting problem for the system. The tubes extend from even with the camera into the distance and so their bounds encompass the entire scene.
The sprites have much narrower bounds distributed throughout the scene. So we want to render the sprites last, on top of the scene, but not paying attention to the zbuffer.

Hence the need for bins (I think).

The nested tubes have a slight depth order to ensure they get rendered in the right order. This generally works and I need to tweak it for these thin tubes (problem revealed in the red BG above).

However the trick is how to do it for the sprites.
I will try the unsorted bin.

Thaumaturge - You are a genius sir. That works.
The sprites must be in unsorted bin so they render last.

tile.setBin("unsorted", 2)