Lately i’ve been working on rim-lighting effect in panda. I know that there’s already another discussion about it but that uses shaders and my intent is to use cubemaps for it.
If you don’t know what a rim-light effect is, just think about Mario Galaxy: That’s that “light from behind” effect which looks pretty nice.
I created a cubemap which is black on front, white on back, and gradient from black to white on the other faces. I tried to apply it replacing the existing one (With a MEyeCubeMap as TexGenAttrib) to my model and here’s the result:
Now I wanted panda to replace the black with the original texture and keep the white as it is. I thought about using a texture stage with MBlend enabled but I got unexpected results. MBlend is supposed to use the color I set (white) where the texture is white and use the original texture where it is black, but it does not. Here’s the code:
from pandac.PandaModules import *
sphere = loader.loadModel('./models/ball')
ts = TextureStage('ts')
tex = loader.loadCubeMap('cubemap_#.png')
and here’s the result:
As you can see, the cubemap isn’t visible at all. There’s some difference if I set an ambient light on it:
It looks like the ambient light affects only the black part of the cubemap, but the borders are still not white. How can i solve this issue?
The cubemap is a grayscale and has no alpha channel.
Why not use MAdd? Basically that does about the same thing.
Otherwise you can use combine mode CMInterpolate to interpolate into a white color based on the cube map.
I think you simply failed to set a sort value on your TextureStage. This means you didn’t guarantee an ordering between it and the default TextureStage, so it’s random whether your blend texture is on the top layer (where you wanted it) or on the bottom layer (where it blends between itself and the untextured color, which is pure white until you create an ambient light).
MAdd has the advantage that it doesn’t care about ordering.
Incidentally, for this purpose a sphere map would be just as good as a cube map, and a bit lighter-weight.
I simply had to add “ts.setSort(1)” in the code leaving MBlend, and now it works very nicely:
Thanks a lot for the help!
A couple of comments:
First, you had a good idea and solution to the problem you were trying to solve. It’s always interesting to see new ways that old things are applied to get new results. Good work.
Second, I think drwr is right. A spheremap may be a better solution just from a processing standpoint. Since you’re clamping the cubemap to the eyeposition you’re basically just using a spheremap anyway, the difference is that a cubemap is 6 images versus a spheremap which is 1 image.
Third, your approach has certain advantages and disadvantages with regard to shaders. By specifying the color in the cubemap image you can have the lighting effect be completely different on any given model, and the lighting can cause mixtures of colors between the cubemap and model’s native texture. Which a shader could probably be written to do this, Panda3D is doing it natively.
The main disadvantage I see is that which shaders, you are using the model’s texture itself to produce the Mario Galaxy effect.