So, here I presented a problem with my motion blur attempt. It was partially resolved (thanks), but the result still looks awful, not to mention that it ignores depth changes altogether. Then I thought a radial blur might work for my case quite well, so here’s what I came up with:
from direct.filter.FilterManager import FilterManager
from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", "want-directtools #t")
loadPrcFileData("", "textures-auto-power-2 #t")
loadPrcFileData("", "win-size 1200 900")
from direct.showbase.ShowBase import ShowBase
from panda3d.core import *
zoom_blur_pass = """\
//Cg
//
//Cg profile arbvp1 arbfp1
void vshader(
in float4 vtx_position : POSITION,
out float4 l_position : POSITION,
out float2 l_texcoord0 : TEXCOORD0,
out float2 l_center,
uniform float4x4 mat_modelproj,
uniform float4 texpad_frame,
uniform float2 k_center
)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord0 = vtx_position.xz * texpad_frame.xy + texpad_frame.xy;
l_center = texpad_frame.xy * k_center * 2;
}
void fshader(
in float2 l_texcoord0 : TEXCOORD0,
in float2 l_center,
out float4 o_color : COLOR,
uniform sampler2D k_frame,
uniform float k_shift
)
{
float2 vec = (l_center - l_texcoord0) * k_shift;
o_color = tex2D(k_frame, l_texcoord0 - vec) * 0.25 +
tex2D(k_frame, l_texcoord0 ) * 0.5 +
tex2D(k_frame, l_texcoord0 + vec) * 0.25;
}
"""
zoom_blur_merge = """\
//Cg
//
//Cg profile arbvp1 arbfp1
// Merges the frame (k_frame) with the blurred sample (k_blur) based on the distance from center
const float INV_AREA_SIZE = 2.;
const float WEIGHT_EXP = 3.;
void vshader(
in float4 vtx_position : POSITION,
out float4 l_position : POSITION,
out float4 l_texcoord0 : TEXCOORD0,
out float2 l_center,
uniform float4x4 mat_modelproj,
uniform float4 texpad_frame,
uniform float2 k_center
)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord0.xy = vtx_position.xz * texpad_frame.xy + texpad_frame.xy;
l_texcoord0.wz = vtx_position.xz * texpad_frame.zy * INV_AREA_SIZE + texpad_frame.xy;
// .wz used for correcting the weighting pattern shape
l_center = texpad_frame.xy * k_center * 2;
}
void fshader(
in float4 l_texcoord0 : TEXCOORD0,
in float2 l_center,
out float4 o_color : COLOR,
uniform sampler2D k_frame,
uniform sampler2D k_blur
)
{
float dist = length(l_center - l_texcoord0.wz);
float weight = smoothstep(0., 1., pow(dist, WEIGHT_EXP)); // It's so smooth I'm slidin' outta this chair!
o_color = lerp(tex2D(k_frame, l_texcoord0.xy), tex2D(k_blur, l_texcoord0.xy), weight);
//o_color = float4(weight, weight, weight, 1); // Shows the blur weighting pattern
}
"""
class BlurTest(ShowBase):
def __init__(self):
ShowBase.__init__(self)
environ = base.loader.loadModel("models/environment")
environ.reparentTo(base.render)
environ.setScale(0.25, 0.25, 0.25)
environ.setPos(-8, 42, -1)
def _makeTexture():
tex = Texture()
tex.setWrapU(Texture.WMClamp)
tex.setWrapV(Texture.WMClamp)
return tex
scale = 2 # Amount the blur texture is downscaled for some extra... blur.
passes = 5 # Increases the quality ... exponentially! Yay!
# For more fine-tuning change the constants in zoom_blur_merge
# variable center.. hard coded for now
center = Vec2(0.5, 0.5)
# Blur length control... camera velocity can be used for this.
shift = 0.05
fm = FilterManager(base.win, base.cam)
source = _makeTexture()
f_quad = fm.renderSceneInto(colortex = source)
prevtex = source
for i in xrange(passes):
blurtex = _makeTexture()
b_quad = fm.renderQuadInto(colortex = blurtex, div = scale, align = scale)
b_quad.setShaderInput('frame', prevtex)
b_quad.setShaderInput('shift', shift)
b_quad.setShaderInput('center', center)
b_quad.setShader(Shader.make(zoom_blur_pass))
prevtex = blurtex
shift /= 2.
f_quad.setShaderInput('frame', source)
f_quad.setShaderInput('blur', prevtex)
f_quad.setShaderInput('center', center)
f_quad.setShader(Shader.make(zoom_blur_merge))
app = BlurTest()
app.run()
It works quite well… for a hack. You’d just have to wire it up with camera movement (center being the projected direction and shift it’s velocity). The only little problem is that the borders flicker a bit.
Screenshot:
Still, a working REAL motion blur would be welcome…