Multitexturing - Textures Considered White [SOLVED]

I’ve started texturing the vehicles in my game and I decided I wanted to make use of gloss maps and glow maps, but I’ve run into a problem. When I add additional textures to my model, the gloss and glow textures are being treated as if they were plain white images. This didn’t happen when I was storing the gloss or glow information in an alpha channel and using the MModulateGloss and MModulateGlow modes for my texture stages. Since I can’t use multiple alpha channels, I need to apply the two maps separately. When I use MGloss and MGlow and add the textures separately, the gloss and glow maps are treated as if they were blank white images. I’ve gone through the manual and the forums and for the life of me, I can’t figure out why this is happening. I did check my gpu’s limit on the number of texture stages using the method in the manual, and I came up with 4.

Here’s my code, so you know what I’m doing.

self.colorTS = TextureStage(self.name + "_Color_TexStage")
self.colorTS.setMode(TextureStage.MModulate)
self.glossTS = TextureStage(self.name + "_Gloss_TexStage")
self.glossTS.setMode(TextureStage.MGloss)

self.teamTex = self.assetLoader.loadTexture("SuicideJockeys/TeamTex.png")
self.highGlossTex = self.assetLoader.loadTexture("Shared/HighGloss.png")

self.frontMolding.setTexture(self.colorTS, self.teamTex)
self.frontMolding.setTexture(self.glossTS, self.highGlossTex)

I’m using panda 1.6.2, if that matters.

You do need to enable the shader generator (with self.frontMolding.setShaderAuto()) in order to enable special maps like gloss and glow maps.

David

I have a call to render.setShaderAuto() in my program, and I do see gloss and glow effects. The problem is that the effects are not limited by the textures I am feeding them. The gloss is too bright for a mostly 25% gray image, and the glow is emitting from parts of the texture that are quite black.

I figured I should provide a more clear example of the issue I’m running into. Here is a another code snippet from my further testing:

self.colorTS = TextureStage(self.name + "_Color_TexStage")
self.colorTS.setMode(TextureStage.MModulate)
self.glowTS = TextureStage(self.name + "_Glow_TexStage")
self.glowTS.setMode(TextureStage.MGlow)

self.discTex = self.assetLoader.loadTexture("Discs/ColorGloss01.png")
self.discGlow = self.assetLoader.loadTexture("Discs/Glow01.png")

self.frontDisc.setTexture(self.colorTS, self.discTex)
self.frontDisc.setTexture(self.glowTS, self.discGlow)

Here are the two images being used for the textures, the first is ColorGloss01.png, and the second is Glow01.png:


ColorGloss01.png


Glow01.png

And here is the resulting effect:

You can see by comparing the two images that only the blue parts should be glowing, the rest should not. I left the bloom filter on for this image because it makes the effect even more obvious, but I assure you that with the bloom off the light gray areas have their emission maxed out by the glow.

I can’t figure out why Glow01.png isn’t limiting the glow effect, and I have the same problem with gloss maps.

The glow map should be in the alpha channel. Change your code to the following, that is the most efficient way:

self.colorGlowTS = TextureStage(self.name + "_Color_Glow_TexStage")
self.colorGlowTS.setMode(TextureStage.MModulateGlow)

self.discTex = self.assetLoader.loadTexture("Discs/ColorGloss01.png", "Discs/Glow01.png")

self.frontDisc.setTexture(self.colorGlowTS, self.discTex)

Note that I’m now loading the glow map into the alpha channel of the texture, by specifying it as second parameter in the loadTexture call.

I understand that, and I have gotten it to work that way. I can also get gloss maps to work that way. However, I wanted to get both a gloss map and a glow map on the same node. Is that not possible?

Sure, that’s possible. Just keep in mind that glow and gloss maps need to be stored in the alpha channel of a texture, even in MGlow/MGloss mode.

Okay. I couldn’t get it to work when I was doing:

self.discTex = self.assetLoader.loadTexture("Discs/ColorGloss01.png", "Shared/LowGloss.png")
self.discGlow = self.assetLoader.loadTexture("Discs/ColorGloss01.png", "Discs/Glow01.png")

I changed it to:

self.discTex = self.assetLoader.loadTexture("Discs/ColorGloss01.png", "Shared/LowGloss.png")
self.discGlow = self.assetLoader.loadTexture("Discs/Blank.png", "Discs/Glow01.png")

And now it works as intended. It’s annoying that I can’t use the same primary texture for both alphas, but that’s a bitter pill I can swallow.

Well, your first solution should work just as well, as long as the mode is set to MGlow and not MModulateGlow.

It is set to MGlow. When I tried it the first way, applying the textures thusly:

self.frontDisc.setTexture(self.colorGlossTS, self.discTex)
self.frontDisc.setTexture(self.glowTS, self.discGlow)

The glow just didn’t happen. It looked the same as if I didn’t apply the glow texture at all.

loadTexture() will cache texture loads based on the primary texture name. So the second call to loadTexture() with the same primary texture name will return the first texture, even though you have specified a different alpha texture name.

David

I figured that’s what was happening. Is there any way to get around that without loading a different image?

There are other hacks you can do, including TexturePool.releaseTexture(), or an explicit call to tex.read(), but probably using a different texture file is the easiest and least hacky solution.

It’s going to end up consuming redundant memory anyway, so there’s not really any good reason to avoid doing this.

David

Okay. I’m probably better off using an all white png anyway, then. It will take less memory than a png with something in it. Thanks, everyone.

For the record, if your color channel is 100% white, you don’t need to specify a color channel at all:

tex = loader.loadTexture("Discs/Glow01.png")
tex.setFormat(tex.FAlpha)

This, again, makes no difference to your memory usage.

Another approach is to define Glow01.png as a two-channel grayscale/alpha image, with the desired color in the color channel, and the desired alpha in the alpha channel. Then you don’t have to use the two-parameter loadTexture() call at all.

(Honestly, I don’t know why the manual recommends the two-parameter loadTexture() call over simply putting the alpha channel in the right place in the first place.)

David

As always, thanks for your help everyone.