Auto Shader Transparency

I have a model without any transparency. If I render it without any shading and then take a screenshot, I get this:

If you click through, you can see that the background is transparent (where nothing is being drawn), but the model itself has no alpha.

When I turn on render.setShaderAuto(True), I get a strange effect where the black areas are being saved with an alpha of 0, turning them transparent:

This happens consistently with many models. Any idea why the auto shader is setting an alpha value of 0 when my material doesn’t have any transparency on it? To be clear, it renders properly - this is only when calling GraphicsWindow.getScreenshot().

It was suggested in IRC to render twice - once with a transparent background and once without. You can then figure out the parts of the image that aren’t supposed to be transparent. Code is below. It works, but it’s ugly. If anyone has any better suggestions, let me know.

def getScreenshot(p3dApp):
    
    def screenshotStep():
        p3dApp.taskMgr.step()
        p3dApp.taskMgr.step()
        pnmss = PNMImage()
        p3dApp.win.getScreenshot(pnmss)
        resulting_ss = StringStream()
        pnmss.write(resulting_ss, "screenshot.png")
        screenshot_buffer = resulting_ss.getData()
        pilimage = Image.open(StringIO(screenshot_buffer))
        pilimage.load()
        
        #pnmimage will sometimes output as palette mode for 8-bit png so convert
        pilimage = pilimage.convert('RGBA')
        return pilimage
    
    base.setBackgroundColor(VBase4(1,1,1,1))
    pilimage = screenshotStep()
    
    badalpha = pilimage.split()[-1]
    badalpha = numpy.array(badalpha.getdata())
    
    base.setBackgroundColor(VBase4(0,0,0,0))
    pilimage = screenshotStep()
    nicealpha = pilimage.split()[-1]
    
    combined_alpha = numpy.array(nicealpha.getdata())
    combined_alpha[badalpha == 0] = 255
    nicealpha.putdata(combined_alpha)
    
    pilimage.putalpha(nicealpha)
    
    return pilimage

Are you trying to make a screenshot with base.screenshot ? I think you could use another image format, such as jpg. If the render artifacts of jpg are an issue to you, maybe you could set to save it as RGB png, not RGBA.

This is a weird issue you’re describing. Is it possible that your texture doesn’t “use” alpha, but still has “alpha” channel in the image?

JPG works fine, but I need the background of the scene to be transparent, which is why I’m using RGBA and PNG.

This particular model doesn’t have any textures, so I’ve ruled that out.

The material color also has alpha channel. I think even vertex colors have one.

I don’t think that’s the issue either. This particular model has two materials - one for the orange and one for the black. Neither have any transparency. Printing out the RenderState for each one:

AlphaTestAttrib:always,1
AntialiasAttrib: none
AudioVolumeAttrib:identity
AuxBitplaneAttrib(0)
ClipPlaneAttrib:identity
ColorAttrib:off
ColorBlendAttrib:none
ColorScaleAttrib:identity
ColorWriteAttrib:rgba
CullFaceAttrib:cull_clockwise
CullBinAttrib:(default)
DepthOffsetAttrib:(0)
DepthTestAttrib:less
DepthWriteAttrib:on
FogAttrib:(off)
LightAttrib:identity
LightRampAttrib:
MaterialAttrib:Material  a(0.588 0.588 0.588 1) d(0.996078 0.560784 0 1) s(0.27 0.27 0.27 1) e(0 0 0 1) s10 l0 t0
RenderModeAttrib:filled
RescaleNormalAttrib:auto
ScissorAttrib:[0 1 0 1]
ShadeModelAttrib:smooth
ShaderAttrib
(SRS_front_enable, 0)(SRS_back_enable, 0)(SRS_front_comparison_function, 7)(SRS_front_stencil_fail_operation, 0)(SRS_front_stencil_pass_z_fail_operation, 0)(SRS_front_stencil_pass_z_pass_operation, 0)(SRS_reference, 0)(SRS_read_mask, 4294967295)(SRS_write_mask, 4294967295)(SRS_back_comparison_function, 7)(SRS_back_stencil_fail_operation, 0)(SRS_back_stencil_pass_z_fail_operation, 0)(SRS_back_stencil_pass_z_pass_operation, 0)(SRS_clear, 0)(SRS_clear_value, 0)
TexMatrixAttrib:
TextureAttrib:all off
TexGenAttrib:
TransparencyAttrib:none

AlphaTestAttrib:always,1
AntialiasAttrib: none
AudioVolumeAttrib:identity
AuxBitplaneAttrib(0)
ClipPlaneAttrib:identity
ColorAttrib:off
ColorBlendAttrib:none
ColorScaleAttrib:identity
ColorWriteAttrib:rgba
CullFaceAttrib:cull_clockwise
CullBinAttrib:(default)
DepthOffsetAttrib:(0)
DepthTestAttrib:less
DepthWriteAttrib:on
FogAttrib:(off)
LightAttrib:identity
LightRampAttrib:
MaterialAttrib:Material  a(0 0 0 1) d(0 0 0 1) s(0.27 0.27 0.27 1) e(0 0 0 1) s10 l0 t0
RenderModeAttrib:filled
RescaleNormalAttrib:auto
ScissorAttrib:[0 1 0 1]
ShadeModelAttrib:smooth
ShaderAttrib
(SRS_front_enable, 0)(SRS_back_enable, 0)(SRS_front_comparison_function, 7)(SRS_front_stencil_fail_operation, 0)(SRS_front_stencil_pass_z_fail_operation, 0)(SRS_front_stencil_pass_z_pass_operation, 0)(SRS_reference, 0)(SRS_read_mask, 4294967295)(SRS_write_mask, 4294967295)(SRS_back_comparison_function, 7)(SRS_back_stencil_fail_operation, 0)(SRS_back_stencil_pass_z_fail_operation, 0)(SRS_back_stencil_pass_z_pass_operation, 0)(SRS_clear, 0)(SRS_clear_value, 0)
TexMatrixAttrib:
TextureAttrib:all off
TexGenAttrib:
TransparencyAttrib:none

That is a little strange. Have you tried inspecting the generated shaders to see if you can tell where it is computing the alpha value from?

Note that, to be perfectly clear here, the shader is not technically generating transparency. It is simply writing an alpha value of 0 where your black material falls. It does appear that the alpha value should be 1 where your black material falls, but perhaps the generated shader doesn’t respect this due to an oversight.

David

I haven’t. Not sure how to do that?

Yeah, and it displays properly on the screen. It’s only when I extract the screen buffer so I can save it as a screenshot that the alpha values are incorrect.

Set “dump-generated-shaders 1” in your Config.prc file.

David

While trying to reproduce the problem to dump the shaders, I noticed that doing this fixes the problem:

render.setTransparency(TransparencyAttrib.MAlpha, 1)

if that gives any more clues as to what’s going on. Apparently, it’s when shaders are on and transparency is off that this happens.

I dumped the shaders:
genshader0: pastebin.com/XcreJC5C
genshader1: pastebin.com/cGNXQWtS