Loading textures with alpha only

I’ve run into a situation where I need a texture with only an alpha. Let me describe it:

I’m recreating the HUD for my game, and in it I have some curved bars to represent values. To make the bars appear to go up and down without distorting their color or curve, I apply a texture with an alpha channel to them, in modulate mode. Because of the modulate mode, the alpha in the textures creates a cut out in the bars. Using that to my advantage, I can offset the texture with the alpha according to the value the bar is connected to, thus determining how much of the bar is removed by the cut out.

For this to work, I need a texture with just an alpha. I can do it by using a small, all white PNG image for RGB and another gray-scale PNG for the alpha and loading them with

tex = loader.loadTexture("White.png", "Alpha.png")

Which is alright, but because of how loadTexture works, if I load White.png more than once with different alphas, I only get the first alpha I loaded. To get new alphas, I need more white.pngs with different names.

Instead of having a couple of pointless, worthless, tiny images loaded into memory, I’d rather just load the alphas and have them work as alphas. Is there a way to make that happen?

Sure. One easy way is:

tex = loader.loadTexture("Alpha.png")
tex.setFormat(tex.FAlpha)

Another reliable way that doesn’t require mucking with the texture settings after loading it is to create an egg file, for instance with egg-texture-cards, and load the texture via that egg file:

egg-texture-cards -f alpha -o Alpha.egg Alpha.png
model = loader.loadModel("Alpha.egg")
tex = model.findTexture("Alpha")

David

I tried using the setFormat method on my texture to make it an alpha, but that didn’t get me the results I wanted.

I get the effect I want with this code:

		self.shieldEgg = loader.loadModel("../Models/ShieldBar.egg")
		
		self.shieldBG = self.shieldEgg.find("**/BackgroundBar")
		self.shieldBar = self.shieldEgg.find("**/ShieldBar")
		self.shieldFrame = self.shieldEgg.find("**/BarFrame")
		
		self.alpha = loader.loadTexture("../Images/HighGlow.png", "../Images/BarAlpha.png")

		self.alpha.setWrapV(Texture.WMClamp)
		
		self.modTS = TextureStage("Modulate")
		self.modTS.setMode(TextureStage.MModulate)
		
		self.shieldBar.setTexture(self.modTS, self.alpha)
		
		self.shieldBar.setTexOffset(self.modTS, 0 ,.5)
		
		self.shieldBG.reparentTo(base.aspect2d)
		self.shieldBar.reparentTo(self.shieldBG)
		self.shieldFrame.reparentTo(self.shieldBar)

The alpha texture, which is just a white image with a thing black line at the top, can be moved up and down to chop off parts of shieldBar.

But with this code:

		self.shieldEgg = loader.loadModel("../Models/ShieldBar.egg")
		
		self.shieldBG = self.shieldEgg.find("**/BackgroundBar")
		self.shieldBar = self.shieldEgg.find("**/ShieldBar")
		self.shieldFrame = self.shieldEgg.find("**/BarFrame")
		
		self.alpha = loader.loadTexture("../Images/BarAlpha.png")
		self.alpha.setFormat(Texture.FAlpha)
		self.alpha.setWrapV(Texture.WMClamp)
		
		self.modTS = TextureStage("Modulate")
		self.modTS.setMode(TextureStage.MModulate)
		
		self.shieldBar.setTexture(self.modTS, self.alpha)
		
		self.shieldBar.setTexOffset(self.modTS, 0 ,.5)
		
		self.shieldBG.reparentTo(base.aspect2d)
		self.shieldBar.reparentTo(self.shieldBG)
		self.shieldFrame.reparentTo(self.shieldBar)

The alpha texture does nothing at all.

For now I’m going to use a work around I just thought off. Since my alpha is just black and white, I’m not using any gray, I can just use the same image for both the RGB and Alpha components. Duh, right?

This code works fine for me to load an alpha-channel image. Maybe your original texture image isn’t grayscale, but is in fact RGB?

from direct.directbase.DirectStart import *
from direct.interval.IntervalGlobal import *
from pandac.PandaModules import *

cm = CardMaker('cm')
cm.setFrame(-0.5, 0.5, -0.5, 0.5)

card1 = aspect2d.attachNewNode(cm.generate())
card2 = aspect2d.attachNewNode(cm.generate())

card1.setColor(0, 0, 1, 1)

tex = loader.loadTexture('models/maps/cmr12.rgb')
tex.setFormat(tex.FAlpha)
card2.setTexture(tex)
card2.setTransparency(TransparencyAttrib.MAlpha)

i = Sequence(card1.posInterval(2, pos = (-0.5, 0, 0), startPos = (0.5, 0, 0)),
             card1.posInterval(2, pos = (0.5, 0, 0), startPos = (-0.5, 0, 0)))
i.loop()

run()

David

Ah, the image does have RGB channels. I’ll try converting it to gray-scale before saving it and see if that works.

Yup, that fixed it. Thanks as always, David.