It would not appear that directional light has any effect on cartoon shader!

Hello!

I am trying to make the toon shader example work in my world. The inking portion works fine but the light ramp appears to not respond to directional light!

Example code applied to my system:

  # Check video card capabilities.
        if not self.win.getGsg().getSupportsBasicShaders():
            print("Toon Shader: Video driver reports that Cg shaders are not supported.")
            return

        tempnode = NodePath(PandaNode("temp node"))
        tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4))
        tempnode.setShaderAuto()
        self.cam.node().setInitialState(tempnode.getState())

        # Use class 'CommonFilters' to enable a cartoon inking filter.
        # This can fail if the video card is not powerful enough, if so,
        # display an error and exit.
        self.separation = 1.5  # Pixels
        base.filters = CommonFilters(self.win, self.cam)
        filterok = base.filters.setCartoonInk(separation=self.separation)
        if (filterok == False):
            print(
                "Toon Shader: Video card not powerful enough to do image postprocessing")
            return

Cut to lights section:

self.ambient_light = AmbientLight('alight')
        self.ambient_light.setColor((0.8, 0.8, 0.8, 1))
        self.alnp = self.render.attachNewNode(self.ambient_light)
        self.render.setLight(self.alnp)
        self.directional_light = DirectionalLight('dlight')
        self.directional_light.setColor((0.8, 0.8, 0.5, 1))
        self.dlnp = self.render.attachNewNode(self.directional_light)
        self.dlnp.setHpr(0, -60, 0)
        self.render.setLight(self.dlnp)

result is flat but outlined:

I also tried a point light to no success.

Here is a screenshot with the lightramp removed so you can see a directional light is indeed shading the model!

Is there a way to debug the value of the luminance to observe whether or not its passed the threshold? (I suspect this is in shader code, so no).

Ive also experimented with a range of values on the threshold and level0 to no avail.

Ive also tried to set Shader Auto on render, just in case:

base.render.setShaderAuto()

If I set the threshold value down to 0 the entire model turns black. This is very very confusing to me, because of this snippet in the docs:

if (original_luminance > threshold0) {
  luminance = level0;
} else {
  luminance = 0.0;
}

If this were true, i suspect everything to pass this check. I cant believe there is no luminance from the dlight or worse, negative luminance.

Just to check: Are you sure that you didn’t set the level0 value to 0? That would have the effect that you describe, I daresay.

Looking at your code, I think that I may see the problem:

I note that you have an ambient light with an overall value of 0.8–which means, I think, that no point on the object will ever have a luminance less than 0.8.

Since your ramp threshold is 0.5, all points should thus be above the threshold, and thus all points will be shaded at the ramped value of 0.4.

Great theory, it doesnt appear to hold true with my testing.

I lowered the value of ambient lighting and directional lighting.

self.ambient_light = AmbientLight('alight')
self.ambient_light.setColor((0.2, 0.2, 0.2, 1))

#... relevant code
self.directional_light.setColor((0.3, 0.3, 0.3, 1))

then tried various threshold. from 0.1 - 0.9 at 0.1 increments

tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.9, 0.6))

and if this theory were true and all points were being lit, then the effect of the level value (to which i also changed) should adjust the brightness of the model, it doesnt. (am i wrong in this thinking?)

Ha, yeah, i had the same thoughts but i double checked my values and the docs. Doc states parameter 1 is threshold and parameter 2 is level.

static makeSingleThreshold(thresh0: float, lev0: float ) → RenderAttrib

This turns it black.

tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.0, 0.6))

Its interesting, another thread was having issues with the auto shader and directional lights when be exported as gltf. I use blend2bam so, its possible I have a related issues?

I appreciate the help.

Scratch that last theory, i loaded default panda and its having the same effect. So it has to be my code.

Current lights:

self.ambient_light = AmbientLight('alight')
self.ambient_light.setColor((0.3, 0.3, 0.3, 1))
self.alnp = self.render.attachNewNode(self.ambient_light)
self.render.setLight(self.alnp)
self.directional_light = DirectionalLight('dlight')
self.directional_light.setColor((0.3, 0.3, 0.3, 1))
self.dlnp = self.render.attachNewNode(self.directional_light)
self.dlnp.setHpr(0, -60, 0)
self.render.setLight(self.dlnp)

Current ramps:

tempnode = NodePath(PandaNode("temp node"))
tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.7,0.4))
self.camera.node().setInitialState(tempnode.getState())

Current effect is the same flat color.

Its worth noting that the changing of ambient light does indeed shift the brightness of the colors, so it seems as if the dlight just isnt effecting it.

Example dragon values:

#lights
plightnode = PointLight("point light")
plightnode.setAttenuation((1, 0, 0))
plight = render.attachNewNode(plightnode)
plight.setPos(30, -50, 0)
alightnode = AmbientLight("ambient light")
alightnode.setColor((0.8, 0.8, 0.8, 1))
alight = render.attachNewNode(alightnode)
render.setLight(alight)
render.setLight(plight)

#ramps
tempnode = NodePath(PandaNode("temp node"))
tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4))
tempnode.setShaderAuto()
self.cam.node().setInitialState(tempnode.getState())

I even tried the no attenuating point lamp! ha

New development! Interestingly, the panda does respond to point lights, but, not directional lights! And my model does not!

Correction, panda is responding to directional light as well. It just was not apparent to me. So this takes me back to perhaps its a data pipeline issue?

Wait, looking at the code that you just posted–why are you applying the light-ramp to the camera?

Indeed, trying out your code in a simple program, I seem to be able to get a working ramp by instead applying it to render. (And reducing the threshold-value–I think that it’s too high for the lights to pass at their values given there.)

Here follows a short test-program that works on my system, and with a simple test-model of mine, at least:

from direct.showbase.ShowBase import ShowBase

from panda3d.core import AmbientLight, DirectionalLight, LightRampAttrib

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        model2 = loader.loadModel("sphere")
        model2.setScale(0.5)
        model2.setPos(0, 2, 0.5)
        model2.reparentTo(render)

        self.ambient_light = AmbientLight('alight')
        self.ambient_light.setColor((0.3, 0.3, 0.3, 1))
        self.alnp = self.render.attachNewNode(self.ambient_light)
        self.render.setLight(self.alnp)
        self.directional_light = DirectionalLight('dlight')
        self.directional_light.setColor((0.3, 0.3, 0.3, 1))
        self.dlnp = self.render.attachNewNode(self.directional_light)
        self.dlnp.setHpr(0, -60, 0)
        self.render.setLight(self.dlnp)

        render.setAttrib(LightRampAttrib.makeSingleThreshold(0.2,0.4))

        render.setShaderAuto()

app = Game()
app.run()

And two screenshots–the first without the light-ramping (for reference), and the second with light-ramping:


I did that because the example did that. I have switched the light lamp to render and the panda still responds but my own model does not. I made my intensity values match yours.

Current Lights:

plightnode = PointLight("point light")
plightnode.setAttenuation((1, 0, 0))
plight = render.attachNewNode(plightnode)
plight.setPos(30, 300, 0)
render.setLight(plight)
self.ambient_light = AmbientLight('alight')
self.ambient_light.setColor((0.3, 0.3, 0.3, 1))
self.alnp = self.render.attachNewNode(self.ambient_light)
self.render.setLight(self.alnp)
self.directional_light = DirectionalLight('dlight')
self.directional_light.setColor((0.3, 0.3, 0.3, 1))
self.dlnp = self.render.attachNewNode(self.directional_light)
self.dlnp.setHpr(0, -60, 0)
self.render.setLight(self.dlnp)

Current Ramp:

 base.render.setShaderAuto()
 base.render.setAttrib(LightRampAttrib.makeSingleThreshold(0.2,0.4))

Current Effect:

Its crazy, brand new exported sphere with blend2bam works. Lego model doesnt

Here is the material shader. Again, this material works under vertex shading when render.setAutoShader() is not present.

Maybe it’s somehow interconnected. The problem with the exporter should not be excluded.

Yeah i think its related.

I wish the dang egg exporter would function so that I could just test that. Maybe ill start looking into that. I have so many pipeline issues.

Im pretty confident at this point that its related to gltf export. I tried obj(wavefront) and while the material fro principle bsdf had its only color issue, it was absolute responding to directional ligt. I think this is the key. Unfortunately, I dont know where to go with this.

Yes! With this information, i was able to do some testing with the yabee egg exporter and realized its failing because of the blender material!! So perhaps i can skip this and go to egg by figuringout out my materials!!

1 Like