Does work.
# -*- coding: utf_8 -*-
from panda3d.core import loadPrcFileData
loadPrcFileData("", "framebuffer-stencil #t")
from math import pi, sin, cos
from direct.showbase.ShowBase import ShowBase
from panda3d.core import DirectionalLight, AmbientLight, LVector4, StencilAttrib, NodePath, Camera
from direct.task import Task
class StencilDemo(ShowBase):
def __init__(self):
ShowBase.__init__(self)
self.disableMouse()
# --- Stage 1 we write the silhouettes of the figures in the stencil buffer.
base.win.setSort(1)
cube_stencil = loader.loadModel("cube")
cube_stencil.setColor(LVector4(0, 1, 0, 1))
cube_stencil.reparentTo(render)
# Cube stencil recording.
cube_stencil.node().setAttrib(StencilAttrib.make(1, StencilAttrib.SCFAlways, StencilAttrib.SOKeep, StencilAttrib.SOKeep, StencilAttrib.SOReplace, 10, 0, 0xff))
sphere_stencil = loader.loadModel("sphere")
sphere_stencil.setColor(LVector4(0, 0, 1, 1))
sphere_stencil.reparentTo(render)
# Recording a stencil sphere.
sphere_stencil.node().setAttrib(StencilAttrib.make(1, StencilAttrib.SCFAlways, StencilAttrib.SOKeep, StencilAttrib.SOKeep, StencilAttrib.SOReplace, 20, 0, 0xff))
# --- In step 2, we render the cube using the stencil mask.
# Create a new scene node.
render2 = NodePath('render2')
# Create a camera and configure the camera.
self.camera2 = render2.attachNewNode(Camera('cam2'))
self.camera2.node().setLens(base.cam.node().getLens())
# Create a display region.
self.display_my = base.win.makeDisplayRegion()
self.display_my.setSort(2)
self.display_my.setClearColorActive(True)
self.display_my.setClearColor(base.getBackgroundColor())
self.display_my.setClearDepthActive(True)
self.display_my.setClearDepth(1.0)
# Set the camera for display.
self.display_my.setCamera(self.camera2)
cube_render = loader.loadModel("cube")
cube_render.setColor(LVector4(1, 0, 0, 1))
cube_render.reparentTo(render2)
# Cube stencil reading.
cube_render.node().setAttrib(StencilAttrib.make(1, StencilAttrib.SCFEqual, StencilAttrib.SOKeep, StencilAttrib.SOKeep, StencilAttrib.SOReplace, 10, 0xff, 0xff))
# Light.
alight = AmbientLight('alight')
alight.setColor(LVector4(0.5, 0.5, 0.5, 1))
alnp = render2.attachNewNode(alight)
render2.setLight(alnp)
dlight = DirectionalLight('dlight')
dlight.setColor(LVector4(1.0, 1.0, 1.0, 1))
dlight.setColorTemperature(4000)
dlnp = render2.attachNewNode(dlight)
dlnp.setHpr(0, -60, 0)
render2.setLight(dlnp)
self.accept("a", self.display_my_active)
# Start the camera rotation around the cube.
self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
self.status = True
#Disable region of the display for stage 2.
def display_my_active(self):
self.status = not self.status
self.display_my.setActive(self.status)
# Camera rotation function.
def spinCameraTask(self, task):
angleDegrees = task.time * 30.0
angleRadians = angleDegrees * (pi / 180.0)
self.camera.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 0)
self.camera.setHpr(angleDegrees, 0, angleDegrees)
self.camera2.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 0)
self.camera2.setHpr(angleDegrees, 0, angleDegrees)
return Task.cont
demo = StencilDemo()
demo.run()
I edited the code, now everything works as expected. However, the thought of unnecessary manipulations in panda3D does not give me rest. I think can use OpenGl calls, for example.
Control: Click key “a” - to turn off / on the 2nd stage of the render.
cube.egg.pz (374 Bytes)
sphere.egg.pz (106.2 KB)