PDA

View Full Version : shadows in mirror


chris_user
02-17-2011, 03:37 AM
one more problem...

in the attached sample I have the problem that the shadow just appears in the mirror, but no longer on the original object; if mirroring is deactivated it looks like it should, has anybody a clue for me whats going wrong?


object loading and running the scene:

import viz
import projector
import vizspace

viz.go()

viz.MainView.move([-6,2,0])
viz.MainView.setEuler([90,20,0])


###SPACENAVIGATOR###
def spacemove(e):
viz.MainView.move(viz.Vector(e.pos)*e.elapsed)
viz.callback(vizspace.TRANSLATE_EVENT,spacemove)

def spacerot(e):
viz.MainView.setAxisAngle(1,0,0,e.ori[0]*e.elapsed,viz.HEAD_ORI,viz.REL_LOCAL)
viz.MainView.setAxisAngle(0,1,0,e.ori[1]*e.elapsed,viz.HEAD_ORI,viz.REL_LOCAL)
viz.MainView.setAxisAngle(0,0,1,e.ori[2]*e.elapsed,viz.HEAD_ORI,viz.REL_LOCAL)
viz.callback(vizspace.ROTATE_EVENT,spacerot)

def spacebuttondown(button):
print 'Button',button,'pressed'
viz.callback(vizspace.BUTTONDOWN_EVENT,spacebutton down)

def spacebuttonup(button):
print 'Button',button,'released'
viz.callback(vizspace.BUTTONUP_EVENT,spacebuttonup )


###OBJECTS###
plane = viz.addTexQuad()
plane.setScale(3,3,3)
plane.setEuler(0,90,90)

ball = viz.add('white_ball.wrl')
ball.setPosition(0,1,0)

ground = viz.add('tut_ground.wrl')
ground.setPosition(0,-.1,0)

###MIRROR###
def addMirror(mirror,mat=None):

#If mirror matrix is not specifed, get matrix of mirror object
if mat is None:
mat = mirror.getMatrix()

#Position of mirror
pos = viz.Vector(mat.getPosition())

#Direction mirror is pointing
dir = viz.Vector(mat.getForward())
dir.normalize()

#Quaternion rotation of mirrorw
quat = mat.getQuat()

#Create render texture
tex = viz.addRenderTexture()

#Create render node for rendering reflection
lens = viz.addRenderNode(size=[1024,1024])
lens.attachTexture(tex)
lens.setInheritView(True,viz.POST_MULT)
lens.disable(viz.CULL_FACE,op=viz.OP_SET_OVERRIDE)

#Setup reflection matrix
rot = viz.Matrix.quat(quat)
invRot = rot.inverse()
lens.setMatrix(viz.Matrix.translate(pos*-1.0)*invRot*viz.Matrix.scale(1,1,-1)*rot*viz.Matrix.translate(pos))

#Setup reflection clip plane
plane = vizmat.Plane(pos=pos,normal=dir)
dist = plane.distance([0,0,0])
lens.clipPlane([-dir[0],-dir[1],-dir[2],dist+0.001])

#Project reflection texture onto mirror
mirror.texture(tex)
mirror.texGen(viz.TEXGEN_PROJECT_EYE)


#Use existing painting as mirror and specify the matrix
mirrorsurface = viz.addTexQuad()
mirrorsurface.scale(6.5,3,.1)
mirrorsurface.setPosition([3.66, 1, 0]) #Y,Z,X
#mirrorsurface.alpha(0.1)
mirrorsurface.appearance(viz.TEXMODULATE)
mirrorsurfacerotation = [90,0,0] #rotation around the Z,Y,X axes
mirrorsurface.rotate(mirrorsurfacerotation)
m = viz.Matrix()
m.setPosition(mirrorsurface.getPosition(viz.ABS_GL OBAL))
m.setEuler(mirrorsurfacerotation[0]-180,-mirrorsurfacerotation[1], mirrorsurfacerotation[2]) #Z,X,Y

#Apply mirror settings to mirror object
addMirror(mirrorsurface,m)

#Increase ambient lighting
#viz.MainView.getHeadLight().ambient(.7,.7,.7)

###SHADOW###
#Shadow resolution (power of two)
#Higher values mean sharper shadows, but take more texture memory
SHADOW_RES = 512

#Postion of shadow projector
SHADOW_POS = [0,2,0]

#Controls size of orthographic shadow projector
#Large values mean larger area is covered, but resolution will be diluted
SHADOW_AREA = [10,10]

#Create shadow projector
import Shadow
shadow = Shadow.ShadowProjector(size=SHADOW_RES,pos=SHADOW_ POS,area=SHADOW_AREA)

#Add avatar as a shadow caster
shadow.addCaster(ball)

#Add ground as shadow receiver
shadow.addReceiver(plane)

Shadow.py

import viz
import projector

class ShadowProjector(object):
def __init__(self,kernel=9,alpha=1,size=256,pos=(0,10, 0),euler=(0,90,0),area=[5,5],scene=viz.MainScene):

#Create render texture
self.shadowTex = viz.addRenderTexture(wrap=viz.CLAMP_TO_BORDER,bord erColor=viz.WHITE)

#Create render node to render shadow caster to texture
self.shadowPass = viz.addRenderNode(scene=scene,size=[size,size],inheritView=False,autoClip=False)
self.shadowPass.setClearColor(viz.WHITE)
self.shadowPass.attachTexture(self.shadowTex)
self.shadowPass.setScene(None)

#Apply shader to render node so everything is black
code = """
#define I %alpha%
void main()
{
gl_FragColor = vec4(I,I,I,1.0);
}
"""
shader = viz.addShader(frag=code.replace('%alpha%',str(1.0-alpha)))
self.shadowPass.apply(shader,op=viz.OP_SET_OVERRID E)

#Create projector for projecting shadow texture onto receivers
self.texProj = projector.add(self.shadowTex,scene=scene,cubemap=F alse)

#Save all render node passes
self.passes = [self.shadowPass]

#Setup render nodes to blur shadow texture
if kernel:
blur_source = """
uniform sampler2D srcImage;
void main(void)
{
vec4 color = vec4(0,0,0,0);
%code%
color.a = 1.0;
gl_FragColor = color;
}"""
horz_source = 'color += texture2D( srcImage, gl_TexCoord[0].xy + vec2( %f, 0.0 ) ) * %f;'
vert_source = 'color += texture2D( srcImage, gl_TexCoord[0].xy + vec2( 0.0, %f ) ) * %f;'

#Calculate weight and offsets for blur code
weights = []
offsets = []
mid = float(kernel - 1)
kernel *= 2
for i in xrange(0,kernel,2):
offsets.append( ((i-mid) / 2.0) * (1.0 / size) )
x = (i - mid) / mid
weights.append( 0.05 + ((-(x*x) + 1.0) / 4.0) )

#Normalize weights
frac = 1.0 / sum(weights)
weights = [ frac * x for x in weights ]

#Create blur code for shaders
horz_blur_code = []
vert_blur_code = []
for w,o in zip(weights,offsets):
horz_blur_code.append(horz_source%(o,w))
vert_blur_code.append(vert_source%(o,w))

#Create shaders
horzBlurShader = viz.addShader(frag=blur_source.replace('%code%','\ n'.join(horz_blur_code)))
vertBlurShader = viz.addShader(frag=blur_source.replace('%code%','\ n'.join(vert_blur_code)))
srcImageUniform = viz.addUniformInt('srcImage',0)

#Render texture for ping-ponging
tex2 = viz.addRenderTexture()

"""
Pass 2 renders the shadow texture onto a quad.
The quad has a shader attached which blurs the texture horizontally.
"""
self.blurPass1 = viz.addRenderNode(scene=scene)
self.blurPass1.setHUD(0,200,0,200,renderQuad=True)
self.blurPass1.setSize(size,size)
self.blurPass1.setBuffer(viz.RENDER_FBO)
self.blurPass1.setOrder(viz.PRE_RENDER,1)
self.blurPass1.attachTexture(tex2)
self.blurPass1.texture(self.shadowTex)
self.blurPass1.apply(horzBlurShader)
self.blurPass1.apply(srcImageUniform)
self.passes.append(self.blurPass1)

"""
Pass 3 renders the texture from pass 2 onto a quad.
The quad has a shader attached which blurs the texture vertically.
"""
self.blurPass2 = viz.addRenderNode(scene=scene)
self.blurPass2.setHUD(0,200,0,200,renderQuad=True)
self.blurPass2.setSize(size,size)
self.blurPass2.setBuffer(viz.RENDER_FBO)
self.blurPass2.setOrder(viz.PRE_RENDER,2)
self.blurPass2.attachTexture(self.shadowTex)
self.blurPass2.texture(tex2)
self.blurPass2.apply(vertBlurShader)
self.blurPass2.apply(srcImageUniform)
self.passes.append(self.blurPass2)

#Remove texture/shader/uniforms (already applied)
horzBlurShader.remove()
vertBlurShader.remove()
srcImageUniform.remove()
tex2.remove()

#Initialize shadow area/pos/euler
self.setArea(area)
self.setPosition(pos)
self.setEuler(euler)

def addCaster(self,node):
"""Add a shadow caster node"""
node.duplicate(viz.MainScene,self.shadowPass)

def addReceiver(self,node,unit=1):
"""Add a shadow receiver node"""
self.texProj.affect(node,unit)

def setPosition(self,pos):
"""Set position of shadow projector"""
self.shadowPass.setPosition(pos)
self.texProj.setPosition(pos)

def setEuler(self,euler):
"""Set euler of shadow projector"""
self.shadowPass.setEuler(euler)
self.texProj.setEuler(euler)

def setArea(self,area):
"""Set [width,height] area of orthographic projection of shadow"""
proj = viz.Matrix.ortho(-area[0]/2.0,area[0]/2.0,-area[1]/2.0,area[1]/2.0,0.1,1000)
self.shadowPass.setProjectionMatrix(proj)
self.texProj.ortho(area[0],area[1])

def visible(self,mode):
"""Enable shadow projector"""
for p in self.passes:
p.visible(mode)
self.texProj.visible(mode)

def remove(self):
"""Permanently remove all resources"""
for p in self.passes:
p.remove(False)
self.shadowTex.remove()
self.texProj.remove()



thanks in advance