I’m trying to implement this : http://http.developer.nvidia.com/GPUGems3/gpugems3_ch23.html
I think it’s almost working, can someone help me?
I don’t know if the depth buffer is really linear.
I don’t know if it should be the expected result.
PS: I can’t copy paste the code from gedit properly, it loses the correct indentation, please use the code in the files.
FILES
http://www.sendspace.com/file/m7173i
DETAILS
[color=indigo]Application class
#####################################################
## Fast Offscreen Particles ##
#####################################################
### Imports ###
from panda3d.core import *
loadPrcFileData('', 'dump-generated-shaders 1')
loadPrcFileData('', 'compressed-textures 0')
loadPrcFileData('', 'show-buffers 1')
loadPrcFileData('', 'basic-shaders-only 0')
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.particles.Particles import Particles
from direct.particles.ParticleEffect import ParticleEffect
from direct.particles.ForceGroup import ForceGroup
from direct.filter.FilterManager import *
### Class constants ###
GREY = Vec4(.5, .5, .5, .5)
BLACK = Vec4(0, 0, 0, 1)
WHITE = Vec4(1, 1, 1, 1)
DIVIDOR = 1 # 1 for full details
PARTICLE_EFFECT = Filename("steam.ptf") # "fireish.ptf" "steam.ptf"
class Application(DirectObject):
def __init__(self):
self.setup_scene()
self.setup_particles()
self.setup_buffers()
self.setup_cameras()
self.setup_passes()
def setup_scene(self):
self.particles = render.attachNewNode("particles")
self.scene = render.attachNewNode("scene")
sphere = loader.loadModel("charbon.egg")
sphere.setScale(2)
tex_sphere = loader.loadTexture('charbon.jpg')
sphere.setTexture(tex_sphere)
sphere.reparentTo(self.scene)
def setup_buffers(self):
self.particles_map = Texture() # particles albedo buffer
self.particles_depth_map = Texture() # particles linear depth buffer
self.scene_depth_map = Texture() # scene linear depth buffer
self.scene_color_map = Texture() # scene albedo buffer
self.z_buffer_particles = base.win.makeTextureBuffer('z_particles', base.win.getXSize()/DIVIDOR, base.win.getYSize()/DIVIDOR, self.particles_depth_map)
self.z_buffer_scene = base.win.makeTextureBuffer('z_scene', base.win.getXSize(), base.win.getYSize(), self.scene_depth_map)
self.color_buffer_scene = base.win.makeTextureBuffer('color_scene', base.win.getXSize(), base.win.getYSize(), self.scene_color_map)
self.color_buffer_particles = base.win.makeTextureBuffer('particles', base.win.getXSize()/DIVIDOR, base.win.getYSize()/DIVIDOR, self.particles_map)
def setup_cameras(self):
# Cameras creation
self.scene_cam = base.makeCamera(self.color_buffer_scene)
self.displayRegion_scene = base.win.makeDisplayRegion()
self.displayRegion_scene.setCamera(self.scene_cam)
self.particles_cam = base.makeCamera(self.color_buffer_particles)
self.particles_cam.reparentTo(base.cam)
self.z_scene_cam = base.makeCamera(self.z_buffer_scene)
self.z_scene_cam.reparentTo(base.cam)
self.z_particles_cam = base.makeCamera(self.z_buffer_particles)
self.z_particles_cam.reparentTo(base.cam)
# Clear colors
base.win.setClearColorActive(True)
base.win.setClearColor(GREY)
self.z_particles_cam.node().getDisplayRegion(0).setClearColor(WHITE)
self.z_particles_cam.node().getDisplayRegion(0).setClearColorActive(1)
self.z_scene_cam.node().getDisplayRegion(0).setClearColor(WHITE)
self.z_scene_cam.node().getDisplayRegion(0).setClearColorActive(1)
self.particles_cam.node().getDisplayRegion(0).setClearColor(GREY)
self.particles_cam.node().getDisplayRegion(0).setClearColorActive(1)
self.scene_cam.node().getDisplayRegion(0).setClearColor(BLACK)
self.scene_cam.node().getDisplayRegion(0).setClearColorActive(1)
# Masks
scene_mask = BitMask32(1)
particles_mask = BitMask32(2)
self.scene_cam.node().setCameraMask(scene_mask)
self.particles_cam.node().setCameraMask(particles_mask)
self.z_scene_cam.node().setCameraMask(scene_mask)
self.z_particles_cam.node().setCameraMask(particles_mask)
self.scene.hide(particles_mask)
self.particles.hide(scene_mask)
# Cameras activation
base.cam.node().setActive(0)
self.scene_cam.node().setActive(1)
def setup_particles(self):
# Particles creation
base.enableParticles()
self.p = ParticleEffect()
self.p.cleanup()
self.p = ParticleEffect()
self.p.loadConfig(PARTICLE_EFFECT)
self.p.start(self.particles)
self.p.setPos(Vec3(0,0,0))
self.p.setScale(2)
def setup_passes(self):
z_shader = ShaderAttrib.make()
z_shader = z_shader.setShader(Shader.load("depth.cg"))
self.z_scene_cam.node().setTagStateKey("z buffer pass")
self.z_scene_cam.node().setTagState("True", RenderState.make(z_shader))
self.z_particles_cam.node().setTagStateKey("z buffer pass")
self.z_particles_cam.node().setTagState("True", RenderState.make(z_shader))
self.filterMan = FilterManager(base.win, self.scene_cam)
self.original_map = Texture()
# Z buffer pass
self.scene.setTag("z buffer pass", "True")
self.particles.setTag("z buffer pass", "True")
self.particles.setShaderInput("particles", loader.loadTexture('fire.png'))
self.scene.setShaderInput("particles", self.particles_map)
self.scene.setShaderInput("active", 0)
self.particles.setShaderInput("active", 1)
# Particles compositing pass
particles_comp_map = Texture()
final_quad = self.filterMan.renderSceneInto(colortex = self.original_map)
final_quad.setShader(loader.loadShader("particles_comp.cg"))
final_quad.setShaderInput("color", self.original_map)
final_quad.setShaderInput("pe", self.p )
final_quad.setShaderInput("camera", self.particles_cam )
final_quad.setShaderInput("particles", self.particles_map)
final_quad.setShaderInput("particles_depth", self.particles_depth_map)
final_quad.setShaderInput("scene_depth", self.scene_depth_map)
### Update per frame ###
def update(self,task):
dt = globalClock.getDt()
return task.cont
app = Application()
run()
[color=indigo]Linear depth shader
//Cg
void vshader(in float4 vtx_position : POSITION,
in float4 vtx_texcoord0 : TEXCOORD0,
uniform sampler2D k_particles : TEXUNIT0,
uniform float4x4 mat_modelproj,
out float2 l_texcoord : TEXCOORD1,
out float4 l_position : POSITION,
out float4 l_depth : TEXCOORD0)
{
l_texcoord = vtx_texcoord0;
l_position = mul(mat_modelproj, vtx_position);
l_depth.x = (l_position.z/l_position.w);
}
void fshader( in float4 l_depth : TEXCOORD0,
in float2 l_texcoord : TEXCOORD1,
uniform float3 k_active,
uniform sampler2D k_particles : TEXUNIT0,
out float4 o_color0 : COLOR0)
{
float4 particles = tex2D(k_particles, l_texcoord);
o_color0 = float4(l_depth.x,l_depth.x,l_depth.x,particles.a);
if(k_active.x==0)o_color0 = float4(l_depth.x,l_depth.x,l_depth.x,1);
}
[color=indigo]Particles compositing shader
//Cg
void vshader(in float4 vtx_position : POSITION,
uniform float4 texpad_color,
uniform float4x4 mat_modelproj,
out float4 l_position : POSITION,
out float2 l_texcoord : TEXCOORD0,
out float4 l_screenpos : TEXCOORD1)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord = (vtx_position.xz * texpad_color.xy) + texpad_color.xy;
l_screenpos = l_position;
}
void fshader(in float2 l_texcoord : TEXCOORD0,
in float4 l_screenpos : TEXCOORD1,
uniform sampler2D k_color : TEXUNIT0,
uniform sampler2D k_particles : TEXUNIT1,
uniform sampler2D k_particles_depth : TEXUNIT2,
uniform sampler2D k_scene_depth : TEXUNIT3,
uniform float4 vspos_pe,
uniform float4 vspos_camera,
uniform float4 texpix_color,
uniform float4 texpad_color,
out float4 o_color : COLOR)
{
float scene_depth = tex2D(k_scene_depth, l_texcoord);
float particles_depth = tex2D(k_particles_depth, l_texcoord);
float4 scene = tex2D(k_color, l_texcoord);
float4 particles = tex2D(k_particles, l_texcoord);
float fade = saturate(scene_depth - particles_depth) * distance(vspos_pe,vspos_camera);
fade = clamp( fade, 0.0, 1.0 );
float4 output = (fade * particles) + ((1.0 - fade) * scene);
o_color = output ;
}