confusing bug with textures and opacity

Hello. I took a screenshot, and the opaque part of one of the textures came out without the texture, just white.

The pair of textures:

lowPassFilter = AlphaTestAttrib.make(RenderAttrib.MLess,0.5)
lampposttex= loader.loadTexture( 'streetlight2.png', 'streetlight-opacity.png' )
lampposttex.setWrapU(Texture.WMClamp)
lampposttex.setWrapV(Texture.WMClamp)
lampposttex.setMinfilter(Texture.FTLinearMipmapLinear)
lampposttex.setAnisotropicDegree(2)

Here’s the creation of the node that gets the texture:

        if which== 'L':
            cardmaker.setUvRange( Point2( 0, 0 ), Point2( 1, 1 ) )
        elif which== 'R':
            cardmaker.setUvRange( Point2( 1, 0 ), Point2( 0, 1 ) )
        pole= cardmaker.generate( )
        polepath= group.attachNewNode( pole )
        polescale= 5.0
        polepath.setScale( Vec3( 1, .5, 2 )* polescale )
        polepath.setTexture( lampposttex )
        polepath.setAttrib(lowPassFilter)

And here’s the screenshot code:

base.accept( 'f7', lambda: base.win.saveScreenshot( Filename( 'driving scene 1.png' ) ) )
base.accept( 'f8', lambda: base.win.saveScreenshot( Filename( 'driving scene 2.png' ) ) )

Why would the scene render with the texture intact, but the screenshot omit it?

Also I noticed that MsPaint displays them properly, but they are blank in Internet Explorer and Chrome. I’ve had other problems with a PNG that displays in the browser but not in Paint!

I’m guessing that the texture is in fact intact in the screenshot, but the alpha channel on those pixels is 0. When you save a screenshot, it also saves the alpha channel of the framebuffer (if you specify a file format that supports alpha, such as png), but the alpha channel is normally invisible, and if you haven’t been thinking about setting the alpha channel to a specific value when you set up the scene, it might have surprising values in it. In particular, it might have 0 where you want to see detail in your image, and many image-display programs will interpret 0 as transparent or plain white.

Solution: either use an image format that doesn’t support alpha (such as bmp or jpg), or take care that your alpha values are set to non-0 in your scene, or remove the alpha channel after you have saved the screenshot.

David

Let me get this straight. There is disagreement about what the meaning of an alpha value of 0 is. Also, I want the alpha channel to be 1.0 at these places.

Well, I’d like to be true to the intention if it doesn’t involve bending too far over backwards. So let’s try to get the alpha set to 1.0.

In practice, you have to go out of your way to really control alpha, but the key points are:

(a) make sure your clear (that is, background) color is (0, 0, 0, 1) instead of (0, 0, 0, 0) or anything else ending in 0.

(b) make sure you don’t have alpha on any of your models or textures. If you are not using transparency, this is easy. If you are using alpha for transparency, then use a blend mode that doesn’t copy the alpha value to the framebuffer. This precludes the use of multisample alpha, which is an advanced alpha mode anyway.

David

The clear color was observed to end in 0:

–>print base.win.getClearColor( )
VBase4(0.41, 0.41, 0.41, 0)

However, changing the last coordinate to 0 didn’t fix it.

I need opacity on the pictures of my streetlamps, because they aren’t rectangular textures. They need to only be opaque at mask coordinates. The key features of the snippet are setTexture to a texture that was loaded in the two-argument constructor, texture and opacity. Then I set an Attrib of:

AlphaTestAttrib.make(RenderAttrib.MLess,0.5)

Before you go too far down this route, make sure that my analysis is correct: that if you remove the alpha channel from the screenshot image, it looks as you expect it to. Note that you can use the command “image-trans -chan 3 -o output.png input.png” to strip the alpha channel.

And, if that sort of process is sufficient, I’d say stick with it, and don’t worry about what goes into the framebuffer–it’s probably not worth it, unless you really want to put specific alpha values at specific points in the resulting screenshot.

David

Your technique was successful. After running that command, the files were correctly visible in Chrome. The clear color index 3 could remain at 0 as well.

IIRC, PNG is the only popular compressed lossless format. What a shame its definition isn’t agreed on.

The format itself is well-defined. What’s not well-defined is the visual interpretation of an alpha channel, which is somewhat outside the scope of a file format to specify.

David

If bytes 0…N are defined to be “a PNG file”, then the PNG file format is well defined, but somewhat useless.

Less sarcastically, if 1 byte in every pixel is defined to be “assorted purpose”, then the format is well defined, but also useless. Or, if the purpose of the idolated “fourth channel” is one of two things, but no bytes indicate which of the two, then the format is well defined but only as useful as our best guess.

I take you to say that the latter is the case; specifically, that the syntax is defined, but the semantics is not.

Yeah. PNG does do a pretty good job of defining the semantic interpretation of the RGB channels, but I don’t believe it says anything about the alpha channel. If anything, it implicit says that alpha channel means transparency, where the background depends on the context in which the image is displayed.

This means, of course, that when Panda writes a value into the alpha channel that doesn’t necessarily mean transparency, then Panda is violating convention. But maybe the alpha channel should mean transparency; Panda doesn’t really know what you have in mind for the alpha channel.

David

I don’t think the evidence supports this (self-deprecating) assertion. MsPaint and Ms Internet Explorer don’t even have the same behavior when it comes to the interpretation of the alphas.

Can I run this “image-trans” from Python directly? It sounds like 0.0 is supposed to mean 1.0 in some cases, as though transparency and opacity were transposed.

Sure, image-trans is just using the PNMImage interface, which you can access directly from Panda. For that matter, you can use base.win.getScreenshot() instead of base.win.saveScreenshot() or base.screenshot() to retrieve the screenshot directly into a PNMImage, instead of writing it to disk, and then you can strip off the alpha channel yourself before writing it wherever you want it.

David