Bloom filter ignores deactivated clear color?

I’ve attempted to create two scenes with their associated cameras and display regions, which overlap one another, and to apply bloom on both of them. What happens is that the region with lower sort order gets obscured by the background of the region with higher sort order, although both have clear color deactivated. If I don’t try to set bloom effect, then regions are overlapped with transparency as expected. Panda 1.7.2. The test code:

from pandac.PandaModules import *
from direct.filter.CommonFilters import *
import direct.directbase.DirectStart

base.setBackgroundColor(0.2, 0.2, 0.2)

def make_scene (sort, clear_color,
                light_color, light_hpr,
                model_pos, model_hpr):

    scene = NodePath("scene")
    camera = base.makeCamera(
        win=base.win, sort=sort,
        clearDepth=True, clearColor=clear_color)
    camera.reparentTo(scene)

    light1 = AmbientLight("light1")
    light1.setColor(light_color * 0.2)
    light1np = NodePath(light1)
    light1np.reparentTo(scene)
    scene.setLight(light1np)

    light2 = DirectionalLight("light2")
    light2.setColor(light_color)
    light2np = NodePath(light2)
    light2np.reparentTo(scene)
    light2np.setHpr(light_hpr)
    scene.setLight(light2np)

    model1 = loader.loadModel("cube")
    model1.reparentTo(scene)
    model1.setPos(model_pos)
    model1.setHpr(model_hpr)

    return scene, camera

scene1, camera1 = make_scene(
    sort=1,
    clear_color=Vec4(0.2, 0.1, 0.1, 1.0),
    light_color=Vec4(1.0, 0.2, 0.1, 1.0),
    light_hpr=Vec3(30, -30, 0),
    model_pos=Point3(-2, 20, 2),
    model_hpr=Vec3(60, 45, 0),
)

scene2, camera2 = make_scene(
    sort=2,
    clear_color=Vec4(0.1, 0.1, 0.2, 1.0),
    light_color=Vec4(0.1, 0.2, 1.0, 1.0),
    light_hpr=Vec3(30, -30, 0),
    model_pos=Point3(2, 20, -2),
    model_hpr=Vec3(45, 60, 0),
)

dispreg1 = camera1.node().getDisplayRegion(0)
dispreg1.setClearColorActive(False)

dispreg2 = camera2.node().getDisplayRegion(0)
dispreg2.setClearColorActive(False)

filters1 = CommonFilters(base.win, camera1)
filters1.setBloom()
filters1.setBloom(mintrigger=0.2, desat=0.0, size="large")

filters2 = CommonFilters(base.win, camera2)
filters2.setBloom()
filters2.setBloom(mintrigger=0.2, desat=0.0, size="large")

run()

In particular, the non-transparent background with bloom is black, although none of the set background colors are black (window background is gray, and clear colors for two created regions are dark red and dark blue).

Is this a bug or some sort of hardware/driver limitation, and what could be a workaround?

After some more tinkering, I realized it makes no sense to have two bloom filters applied separately (at least as in the code above), since bloom requires some sort of background to produce halos. E.g. if I set transparency on filter quads produced by FilterManager, then I do get transparency and bloom on object surfaces in both scenes, but there are no halos.

Instead I emulated what FilterManager does: I created an off-screen buffer, set both scenes/display regions/cameras in it, made an on-screen 2D quad with that buffer’s texture, and applied a single bloom effect to the quad. The code:

import math

from pandac.PandaModules import *
from direct.filter.CommonFilters import *
import direct.directbase.DirectStart

ConfigVariableString("textures-power-2").setValue("none")

base.setBackgroundColor(0.1, 0.1, 0.1)

# Create a scene root node and a camera for it.
def make_scene (buffer, sort, clear_color,
                light_color, light_hpr,
                model_pos, model_hpr, model_rspeed):

    scene = NodePath("scene")
    camera = base.makeCamera(
        win=buffer, sort=sort,
        clearDepth=True, clearColor=clear_color)
    camera.reparentTo(scene)
    lens = PerspectiveLens()
    lens.setFov(base.camLens.getFov())
    camera.node().setLens(lens)

    light1 = AmbientLight("light1")
    light1.setColor(light_color * 0.2)
    light1np = NodePath(light1)
    light1np.reparentTo(scene)
    scene.setLight(light1np)

    light2 = DirectionalLight("light2")
    light2.setColor(light_color)
    light2np = NodePath(light2)
    light2np.reparentTo(scene)
    light2np.setHpr(light_hpr)
    scene.setLight(light2np)

    model1 = loader.loadModel("cube")
    model1.reparentTo(scene)
    model1.setPos(model_pos)
    model1.setHpr(model_hpr)

    return scene, camera


fbp = FrameBufferProperties(base.win.getFbProperties())
wsx = base.win.getXSize()
wsy = base.win.getYSize()
wp = WindowProperties()
wp.setSize(wsx, wsy)
texture = Texture()
buffer = base.graphicsEngine.makeOutput(
    base.win.getPipe(), "buffer", -100, fbp, wp,
    GraphicsPipe.BFRefuseWindow, base.win.getGsg(), base.win)
buffer.addRenderTexture(texture, GraphicsOutput.RTMBindOrCopy)

scene1, camera1 = make_scene(
    buffer=buffer, sort=1,
    clear_color=base.getBackgroundColor(),
    light_color=Vec4(1.0, 0.2, 0.1, 1.0),
    light_hpr=Vec3(30, -30, 0),
    model_pos=Point3(-0.8, 15, 0.8),
    model_hpr=Vec3(60, 45, 0),
    model_rspeed=90.0,
)

scene2, camera2 = make_scene(
    buffer=buffer, sort=2,
    clear_color=None,
    light_color=Vec4(0.1, 0.2, 1.0, 1.0),
    light_hpr=Vec3(30, -30, 0),
    model_pos=Point3(0.8, 15, -0.8),
    model_hpr=Vec3(45, 60, 0),
    model_rspeed=120.0,
)

quadscene = NodePath("filter-quad-scene")
quadcamera = base.makeCamera2d(base.win, sort=7)
quadcamera.reparentTo(quadscene)
cm = CardMaker("filter-quad-card")
cm.setFrameFullscreenQuad()
quad = NodePath(cm.generate())
quad.setTexture(buffer.getTexture())
quad.reparentTo(quadcamera)

filters = CommonFilters(base.win, quadcamera)
filters.setBloom(mintrigger=0.2, desat=0.0, size="large")

run()

This seems to do exactly what I want, but I’m not sure about two things:

Generally, is this code doing more than it should in some way, possibly causing performance loss? The intended real use is where one scene is the game world, and the other scene is player’s 3D control overlay.

More specifically, I had to set textures-power-2 to none, because otherwise I was getting artifacts from texture scaling in the image. I read that non-power-2 texture can cause performance problems, though I’m not seeing any in this example. Should it be OK if this were the only non-power-2 texture, and I manually make sure all other textures are power-2?

Modern GPU’s seem to reliably support non-power-of-two textures, so you can probably safely set it. It’s still smart to use power-of-two sizes for your other textures, as they will probably use up less memory.