another shadow question

Spotlights are good for casting shadows, but I already use a Directional light for my scene and don’t want the spotlight to lit the environment. Is it possible to set the spotlight to only cast shadows but not effect the environment?

And there is also this:

Does this have anything to do with self shadowing?

That sounds like a likely guess.

David

You can avoid self-shadowing artifacts by using setDepthOffset(1).

No wait, I have done that:

from panda3d.core import *
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.actor import Actor


class World(DirectObject):
	def __init__(self):
		
		# SpotLight
		self.slight = render.attachNewNode(Spotlight("Spot"))
		self.slight.setPos(0,-100,100)
		self.slight.lookAt(0,0,0)
		render.setLight(self.slight)
		
		self.slight.node().setShadowCaster(True, 1024, 1024)
		self.slight.node().showFrustum()
		self.slight.node().getLens().setFov(80)
		self.slight.node().getLens().setNearFar(40,300)
		
		# Ambient Light
		self.alight = render.attachNewNode(AmbientLight("Ambient"))
		self.alight.node().setColor(Vec4(0.2, 0.2, 0.2, 1))
		render.setLight(self.alight)
		
		# Important! Enable the shader generator.
		render.setShaderAuto()
		
		
		# Load the scene.
		self.environ =loader.loadModel('environment')
		self.environ.setScale(0.4)
		self.environ.setPos(0,50,0)
		self.environ.reparentTo(render)
		self.environ.setDepthOffset(1)
		
		# animated model
		self.pandaModel=Actor.Actor('panda-model',{'walk':'panda-walk4'})
		self.pandaModel.reparentTo(render)
		self.pandaModel.setPos(0,0,0)
		self.pandaModel.setScale(0.01)
		self.pandaModel.setDepthOffset(1)
		
		self.pandaWalk = self.pandaModel.actorInterval('walk',playRate=1.8)
		self.pandaWalk.loop()
     
  
World()
run()

Add more offset.

What?

The shadow must be pushed farther away from the light. Don’t tell me the autoshader doesn’t give you a way.

Sorry, I really don’t get what you mean by that.

I suppose .setDepthOffset(anyValue) is an interface to adjust shadows’ push bias.

Well whatever it should do, it doesn’t. I don’t see any difference and too high values give me this:

setDepthOffset is a way to offset an object in the depth buffer. A value of 1 means the smallest amount possible that makes a difference. IMHO this is a better solution than the hacky push matrix in the shader. (DepthOffsetAttrib translates to glPolygonOffset, which is the usual way to fix shadow artifacts in the OpenGL world.)

In general, you don’t need to use a depth offset. With the built-in shadow algorithm, only the backsides of objects cast shadows, so these artifacts can only happen on the backside - but this is not a problem because the dot product is cut off so the surface is dark anyway. Therefore, self-shadowing artifacts usually only occur on very-thin objects (where the backside of the object casts shadow on its front side), like plant leaves, or surfaces orthogonal to the light (this usually only happens with directional lights that make a perfect angle, this is why I don’t recommend using directional lights for shadow casting).
Side-effect of this approach is that you may see light leaking through edges, as you can see near the trunk of the tree, but that’s a different story.

So I’m suspecting that the artifacts that you’re dealing with here aren’t self-shadowing artifacts. Perhaps a depth buffer precision problem? Can you try a higher-resolution depth buffer, or making the near/far clip of the light as tight as possible?

‘dot product’?

Oh, but directional lights are the best way to make sunlight in my knowledge. If all I have to do is call setDepthOffset() then I rather stick with it. Though I have also tried this example with a spotlight.

How about ‘self.slight.node().getLens().setNearFar(1,40)’? Same:

How do you do that? The ‘depth-bits’ in Config.prc? I tried some higher values with no luck if thats what you mean.

Is this same for you?:

from panda3d.core import *
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.actor import Actor


class World(DirectObject):
   def __init__(self):
      
      # SpotLight
      self.slight = render.attachNewNode(Spotlight("Spot"))
      self.slight.setPos(0,-100,100)
      self.slight.lookAt(0,0,0)
      render.setLight(self.slight)
      
      self.slight.node().setShadowCaster(True, 1024, 1024)
      self.slight.node().showFrustum()
      self.slight.node().getLens().setFov(80)
      self.slight.node().getLens().setNearFar(40,300)
      
      # Ambient Light
      self.alight = render.attachNewNode(AmbientLight("Ambient"))
      self.alight.node().setColor(Vec4(0.2, 0.2, 0.2, 1))
      render.setLight(self.alight)
      
      # Important! Enable the shader generator.
      render.setShaderAuto()
      
      
      # Load the scene.
      self.environ =loader.loadModel('environment')
      self.environ.setScale(0.4)
      self.environ.setPos(0,50,0)
      self.environ.reparentTo(render)
      self.environ.setDepthOffset(1)
      
      # animated model
      self.pandaModel=Actor.Actor('panda-model',{'walk':'panda-walk4'})
      self.pandaModel.reparentTo(render)
      self.pandaModel.setPos(0,0,0)
      self.pandaModel.setScale(0.01)
      self.pandaModel.setDepthOffset(1)
      
      self.pandaWalk = self.pandaModel.actorInterval('walk',playRate=1.8)
      self.pandaWalk.loop()
     
 
World()
run()

EDIT: I tried this on the official 1.7.0 release and its the same.

I can say for sure now that its not my code that has problems, I tried the official panda sample with .oobe(). “Tut-Shadow-Mapping-Basic” and there is the same problem, with or without setDepthOffset(1).

Here I just added the environment model to the sample:

Soo, can someone try this out and tell me if its the same for them? Or maybe theres something wrong on my side?

I’m getting similar issues with my terrain, using spotlight or directional light.

Doesn’t seem to be an issue with perfectly parellel polygons to the light since I’m getting far too many issues for that to be the case.

As anon said, the depth offset seems ineffective.

Ive used loadPrcFileData("", “depth-bits 1” ) and it had no effect.

Heres a screenshot:

Yeah, seems like it.
What resolution do you use for such a big terrain?

well, that shot was at 512x512, but I lowered it to make the problem more visible, I was testing at 2048x2048. Don’t know if that would have caused performance problems if I had any gameplay yet…

Whats the film size of the lense?
I need at least 4096x4096 resolution for 1200,1200 filmsize for a scene with a 3rd person camera. Otherwise I can clearly see some trees not casting anything.