mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
General development of FilterManager and CommonFiltes
This commit is contained in:
parent
b98c5f0bf5
commit
6ac5500f76
@ -18,30 +18,19 @@ clunky approach. - Josh
|
||||
from FilterManager import FilterManager
|
||||
from pandac.PandaModules import Point3, Vec3, Vec4
|
||||
from pandac.PandaModules import NodePath, PandaNode
|
||||
from pandac.PandaModules import Filename
|
||||
from pandac.PandaModules import RenderState, Texture, Shader
|
||||
|
||||
HEADER = """//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float4 l_texcoord : TEXCOORD0,
|
||||
uniform float4 texpad_txcolor,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
l_texcoord=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;
|
||||
}
|
||||
"""
|
||||
import sys,os
|
||||
|
||||
CARTOON_BODY="""
|
||||
float4 cartoondelta = k_cartoonseparation * texpix_txcolor.xwyw;
|
||||
float4 cartoon_p0 = l_texcoord + cartoondelta.xyzw;
|
||||
float4 cartoondelta = k_cartoonseparation * texpix_txnormal.xwyw;
|
||||
float4 cartoon_p0 = l_texcoordN + cartoondelta.xyzw;
|
||||
float4 cartoon_c0 = tex2D(k_txnormal, cartoon_p0.xy);
|
||||
float4 cartoon_p1 = l_texcoord - cartoondelta.xyzw;
|
||||
float4 cartoon_p1 = l_texcoordN - cartoondelta.xyzw;
|
||||
float4 cartoon_c1 = tex2D(k_txnormal, cartoon_p1.xy);
|
||||
float4 cartoon_p2 = l_texcoord + cartoondelta.wzyx;
|
||||
float4 cartoon_p2 = l_texcoordN + cartoondelta.wzyx;
|
||||
float4 cartoon_c2 = tex2D(k_txnormal, cartoon_p2.xy);
|
||||
float4 cartoon_p3 = l_texcoord - cartoondelta.wzyx;
|
||||
float4 cartoon_p3 = l_texcoordN - cartoondelta.wzyx;
|
||||
float4 cartoon_c3 = tex2D(k_txnormal, cartoon_p3.xy);
|
||||
float4 cartoon_mx = max(cartoon_c0,max(cartoon_c1,max(cartoon_c2,cartoon_c3)));
|
||||
float4 cartoon_mn = min(cartoon_c0,min(cartoon_c1,min(cartoon_c2,cartoon_c3)));
|
||||
@ -50,10 +39,9 @@ float cartoon_thresh = dot(cartoon_trigger.xyz,float3(1,1,1));
|
||||
o_color = lerp(o_color, float4(0,0,0,1), cartoon_thresh);
|
||||
"""
|
||||
|
||||
CARTOON_PARAMS="""
|
||||
uniform float4 k_cartoonseparation,
|
||||
uniform float4 k_cartooncutoff,
|
||||
"""
|
||||
class FilterConfig:
|
||||
pass
|
||||
|
||||
class CommonFilters:
|
||||
|
||||
""" Class CommonFilters implements certain common image postprocessing
|
||||
@ -64,10 +52,16 @@ class CommonFilters:
|
||||
self.configuration = {}
|
||||
self.cleanup()
|
||||
|
||||
def loadShader(self, name):
|
||||
fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name)
|
||||
print "loading shader: ", dir
|
||||
return Shader.load(Filename.fromOsSpecific(fn))
|
||||
|
||||
def cleanup(self):
|
||||
self.manager.cleanup()
|
||||
self.textures = {}
|
||||
self.finalQuad = None
|
||||
self.bloom = []
|
||||
|
||||
def reconfigure(self, fullrebuild, changed):
|
||||
|
||||
@ -82,31 +76,98 @@ class CommonFilters:
|
||||
if (len(configuration) == 0):
|
||||
return
|
||||
|
||||
needtexpix = False
|
||||
needtex = {}
|
||||
needtex["color"] = True
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
needtex["normal"] = True
|
||||
if (configuration.has_key("Bloom")):
|
||||
needtex["bloom0"] = True
|
||||
needtex["bloom1"] = True
|
||||
needtex["bloom2"] = True
|
||||
needtex["bloom3"] = True
|
||||
for tex in needtex:
|
||||
self.textures[tex] = Texture("scene-"+tex)
|
||||
needtexpix = True
|
||||
|
||||
self.finalQuad = self.manager.renderSceneInto(textures = self.textures)
|
||||
|
||||
text = HEADER
|
||||
if (configuration.has_key("Bloom")):
|
||||
bloomconf = configuration["Bloom"]
|
||||
bloom0=self.textures["bloom0"]
|
||||
bloom1=self.textures["bloom1"]
|
||||
bloom2=self.textures["bloom2"]
|
||||
bloom3=self.textures["bloom3"]
|
||||
if (bloomconf.size == "large"):
|
||||
scale=8
|
||||
downsampler="filter-down4.sha"
|
||||
elif (bloomconf.size == "medium"):
|
||||
scale=4
|
||||
downsampler="filter-copy.sha"
|
||||
else:
|
||||
scale=2
|
||||
downsampler="filter-copy.sha"
|
||||
self.bloom.append(self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale))
|
||||
self.bloom[0].setShaderInput("src", self.textures["color"])
|
||||
self.bloom[0].setShader(self.loadShader("filter-bloomi.sha"))
|
||||
self.bloom[1].setShaderInput("src", bloom0)
|
||||
self.bloom[1].setShader(self.loadShader(downsampler))
|
||||
self.bloom[2].setShaderInput("src", bloom1)
|
||||
self.bloom[2].setShader(self.loadShader("filter-bloomx.sha"))
|
||||
self.bloom[3].setShaderInput("src", bloom2)
|
||||
self.bloom[3].setShader(self.loadShader("filter-bloomy.sha"))
|
||||
|
||||
text = "//Cg\n"
|
||||
text += "void vshader(float4 vtx_position : POSITION,\n"
|
||||
text += " out float4 l_position : POSITION,\n"
|
||||
text += " uniform float4 texpad_txcolor,\n"
|
||||
text += " uniform float4 texpix_txcolor,\n"
|
||||
text += " out float4 l_texcoordC : TEXCOORD0,\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += " uniform float4 texpad_txnormal,\n"
|
||||
text += " uniform float4 texpix_txnormal,\n"
|
||||
text += " out float4 l_texcoordN : TEXCOORD1,\n"
|
||||
if (configuration.has_key("Bloom")):
|
||||
text += " uniform float4 texpad_txbloom3,\n"
|
||||
text += " out float4 l_texcoordB : TEXCOORD2,\n"
|
||||
text += " uniform float4x4 mat_modelproj)\n"
|
||||
text += "{\n"
|
||||
text += " l_position=mul(mat_modelproj, vtx_position);\n"
|
||||
text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += " l_texcoordN=(vtx_position.xzxz * texpad_txnormal) + texpad_txnormal;\n"
|
||||
if (configuration.has_key("Bloom")):
|
||||
text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n"
|
||||
if (configuration.has_key("HalfPixelShift")):
|
||||
text += " l_texcoordC+=texpix_txcolor*0.5;\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += " l_texcoordN+=texpix_txnormal*0.5;\n"
|
||||
text += "}\n"
|
||||
|
||||
text += "void fshader(\n"
|
||||
text += "float4 l_texcoord : TEXCOORD0,\n"
|
||||
if (needtexpix):
|
||||
text += "uniform float4 texpix_txcolor,\n"
|
||||
text += "float4 l_texcoordC : TEXCOORD0,\n"
|
||||
text += "uniform float4 texpix_txcolor,\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += "float4 l_texcoordN : TEXCOORD1,\n"
|
||||
text += "uniform float4 texpix_txnormal,\n"
|
||||
if (configuration.has_key("Bloom")):
|
||||
text += "float4 l_texcoordB : TEXCOORD2,\n"
|
||||
for key in self.textures:
|
||||
text += "uniform sampler2D k_tx" + key + ",\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += CARTOON_PARAMS
|
||||
text += "uniform float4 k_cartoonseparation,\n"
|
||||
text += "uniform float4 k_cartooncutoff,\n"
|
||||
text += "out float4 o_color : COLOR)\n"
|
||||
text += "{\n"
|
||||
text += " o_color = tex2D(k_txcolor, l_texcoord.xy);\n"
|
||||
text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n"
|
||||
if (configuration.has_key("CartoonInk")):
|
||||
text += CARTOON_BODY
|
||||
if (configuration.has_key("Bloom")):
|
||||
text += "o_color = saturate(o_color);\n";
|
||||
text += "float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n"
|
||||
text += "o_color = 1-((1-bloom)*(1-o_color));\n"
|
||||
text += "}\n"
|
||||
|
||||
print "Using shader: ", text
|
||||
@ -120,6 +181,15 @@ class CommonFilters:
|
||||
self.finalQuad.setShaderInput("cartoonseparation", Vec4(separation,0,separation,0))
|
||||
self.finalQuad.setShaderInput("cartooncutoff", Vec4(cutoff,cutoff,cutoff,cutoff))
|
||||
|
||||
if (changed == "Bloom") or fullrebuild:
|
||||
if (configuration.has_key("Bloom")):
|
||||
bloomconf = configuration["Bloom"]
|
||||
intensity = bloomconf.intensity * 3.0
|
||||
self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw)
|
||||
self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0)
|
||||
self.bloom[0].setShaderInput("desat", bloomconf.desat)
|
||||
self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity)
|
||||
|
||||
def setCartoonInk(self, separation=1, cutoff=0.3):
|
||||
fullrebuild = (self.configuration.has_key("CartoonInk") == False)
|
||||
self.configuration["CartoonInk"] = (separation, cutoff)
|
||||
@ -128,6 +198,45 @@ class CommonFilters:
|
||||
def delCartoonInk(self):
|
||||
if (self.configuration.has_key("CartoonInk")):
|
||||
del self.configuration["CartoonInk"]
|
||||
self.reconfigure(True)
|
||||
self.reconfigure(True, "CartoonInk")
|
||||
|
||||
def setBloom(self, blend=(0.3,0.4,0.3,0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium"):
|
||||
if (maxtrigger==None): maxtrigger=mintrigger+0.8
|
||||
oldconfig = self.configuration.get("Bloom", None)
|
||||
fullrebuild = True
|
||||
if (oldconfig) and (oldconfig.size == size):
|
||||
fullrebuild = False
|
||||
newconfig = FilterConfig()
|
||||
(newconfig.blendx, newconfig.blendy, newconfig.blendz, newconfig.blendw) = blend
|
||||
newconfig.maxtrigger = maxtrigger
|
||||
newconfig.mintrigger = mintrigger
|
||||
newconfig.desat = desat
|
||||
newconfig.intensity = intensity
|
||||
newconfig.size = size
|
||||
self.configuration["Bloom"] = newconfig
|
||||
self.reconfigure(fullrebuild, "Bloom")
|
||||
|
||||
def delBloom(self):
|
||||
if (self.configuration.has_key("Bloom")):
|
||||
del self.configuration["Bloom"]
|
||||
self.reconfigure(True, "Bloom")
|
||||
|
||||
def setHalfPixelShift(self):
|
||||
fullrebuild = (self.configuration.has_key("HalfPixelShift") == False)
|
||||
self.configuration["HalfPixelShift"] = 1
|
||||
self.reconfigure(fullrebuild, "HalfPixelShift")
|
||||
|
||||
def delHalfPixelShift(self):
|
||||
if (self.configuration.has_key("HalfPixelShift")):
|
||||
del self.configuration["HalfPixelShift"]
|
||||
self.reconfigure(True, "HalfPixelShift")
|
||||
|
||||
def setFSBloom(self):
|
||||
fullrebuild = (self.configuration.has_key("FSBloom") == False)
|
||||
self.configuration["FSBloom"] = 1
|
||||
self.reconfigure(fullrebuild, "FSBloom")
|
||||
|
||||
def delFSBloom(self):
|
||||
if (self.configuration.has_key("FSBloom")):
|
||||
del self.configuration["FSBloom"]
|
||||
self.reconfigure(True, "FSBloom")
|
||||
|
@ -61,10 +61,63 @@ class FilterManager:
|
||||
self.win = win
|
||||
self.engine = win.getGsg().getEngine()
|
||||
self.region = region
|
||||
self.wclears = self.getClears(self.win)
|
||||
self.rclears = self.getClears(self.region)
|
||||
self.camera = cam
|
||||
self.caminit = cam.node().getInitialState()
|
||||
self.scales = []
|
||||
self.buffers = []
|
||||
self.sizes = []
|
||||
self.nextsort = self.win.getSort() - 1000
|
||||
self.basex = 0
|
||||
self.basey = 0
|
||||
|
||||
|
||||
def getClears(self,region):
|
||||
clears = []
|
||||
for i in range(GraphicsOutput.RTPCOUNT):
|
||||
clears.append((region.getClearActive(i), region.getClearValue(i)))
|
||||
return clears
|
||||
|
||||
def setClears(self,region,clears):
|
||||
for i in range(GraphicsOutput.RTPCOUNT):
|
||||
(active, value) = clears[i]
|
||||
region.setClearActive(i, active)
|
||||
region.setClearValue(i, value)
|
||||
|
||||
def setStackedClears(self, region, clears0, clears1):
|
||||
clears = []
|
||||
for i in range(GraphicsOutput.RTPCOUNT):
|
||||
(active, value) = clears0[i]
|
||||
if (active == 0):
|
||||
(active, value) = clears1[i]
|
||||
region.setClearActive(i, active)
|
||||
region.setClearValue(i, value)
|
||||
return clears
|
||||
|
||||
def isFullscreen(self):
|
||||
return ((self.region.getLeft() == 0.0) and
|
||||
(self.region.getRight() == 1.0) and
|
||||
(self.region.getBottom() == 0.0) and
|
||||
(self.region.getTop() == 1.0))
|
||||
|
||||
def getScaledSize(self, mul, div, align):
|
||||
|
||||
""" Calculate the size of the desired window. Not public. """
|
||||
|
||||
winx = self.win.getXSize()
|
||||
winy = self.win.getYSize()
|
||||
|
||||
if (div != 1):
|
||||
winx = ((winx+align-1) / align) * align
|
||||
winy = ((winy+align-1) / align) * align
|
||||
winx = winx / div
|
||||
winy = winy / div
|
||||
|
||||
if (mul != 1):
|
||||
winx = winx * mul
|
||||
winy = winy * mul
|
||||
|
||||
return winx,winy
|
||||
|
||||
def renderSceneInto(self, depthtex=False, colortex=False, normaltex=False, textures=None):
|
||||
|
||||
@ -77,9 +130,9 @@ class FilterManager:
|
||||
To elaborate on how this all works:
|
||||
|
||||
* An offscreen buffer is created. It is set up to mimic
|
||||
the original window - it is the same size, uses the
|
||||
same clear colors, and contains a DisplayRegion that
|
||||
uses the original camera.
|
||||
the original display region - it is the same size,
|
||||
uses the same clear colors, and contains a DisplayRegion
|
||||
that uses the original camera.
|
||||
|
||||
* A fullscreen quad and an orthographic camera to render
|
||||
that quad are both created. The original camera is
|
||||
@ -90,6 +143,18 @@ class FilterManager:
|
||||
offscreen buffer. A shader is applied that tints the
|
||||
results pink.
|
||||
|
||||
* Automatic shader generation is enabled by default for
|
||||
the main camera. You can override this by setting
|
||||
shaders on individual nodes, or on the root of your
|
||||
scene graph, but if you do, your own shaders need to
|
||||
generate the outputs that the filter manager is expecting.
|
||||
|
||||
* All clears are disabled on the original display region.
|
||||
If the display region fills the whole window, then clears
|
||||
are disabled on the original window as well. It is
|
||||
assumed that rendering the full-screen quad eliminates
|
||||
the need to do clears.
|
||||
|
||||
Hence, the original window which used to contain the actual
|
||||
scene, now contains a pink-tinted quad with a texture of the
|
||||
scene. It is assumed that the user will replace the shader
|
||||
@ -104,7 +169,11 @@ class FilterManager:
|
||||
|
||||
texgroup = (depthtex, colortex, normaltex, None)
|
||||
|
||||
buffer = self.createBuffer("filter-base", base.win.getXSize(), base.win.getYSize(), texgroup)
|
||||
# Choose the size of the offscreen buffer.
|
||||
|
||||
winx = self.win.getXSize()
|
||||
winy = self.win.getYSize()
|
||||
buffer = self.createBuffer("filter-base", winx, winy, texgroup)
|
||||
|
||||
if (buffer == None):
|
||||
return None
|
||||
@ -137,26 +206,68 @@ class FilterManager:
|
||||
|
||||
self.region.setCamera(quadcam)
|
||||
|
||||
buffer.getDisplayRegion(0).setCamera(self.camera)
|
||||
buffer.getDisplayRegion(0).setActive(1)
|
||||
dr = buffer.getDisplayRegion(0)
|
||||
self.setStackedClears(dr, self.rclears, self.wclears)
|
||||
if (normaltex):
|
||||
dr.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
|
||||
dr.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.0,0.0,0.0,0.0))
|
||||
self.region.disableClears()
|
||||
if (self.isFullscreen()):
|
||||
self.win.disableClears()
|
||||
dr.setCamera(self.camera)
|
||||
dr.setActive(1)
|
||||
|
||||
self.scales.append(1)
|
||||
self.buffers.append(buffer)
|
||||
self.sizes.append((1, 1, 1))
|
||||
|
||||
return quad
|
||||
|
||||
def renderQuadInto(self, scale=1, depthtex=None, colortex=None, auxtex0=None, auxtex1=None):
|
||||
def renderQuadInto(self, mul=1, div=1, align=1, depthtex=None, colortex=None, auxtex0=None, auxtex1=None):
|
||||
|
||||
""" Creates an offscreen buffer for an intermediate
|
||||
computation. Installs a quad into the buffer. Returns
|
||||
the fullscreen quad. """
|
||||
the fullscreen quad. The size of the buffer is initially
|
||||
equal to the size of the main window. The parameters 'mul',
|
||||
'div', and 'align' can be used to adjust that size. """
|
||||
|
||||
self.notify.error('renderQuadInto not implemented yet.')
|
||||
return None
|
||||
texgroup = (depthtex, colortex, auxtex0, auxtex1)
|
||||
|
||||
def createBuffer(self, name, xsize, ysize, texgroup):
|
||||
winx, winy = self.getScaledSize(mul, div, align)
|
||||
|
||||
buffer = self.createBuffer("filter-stage", winx, winy, texgroup, depthbits=0)
|
||||
|
||||
if (buffer == None):
|
||||
return None
|
||||
|
||||
cm = CardMaker("filter-stage-quad")
|
||||
cm.setFrameFullscreenQuad()
|
||||
quad = NodePath(cm.generate())
|
||||
quad.setDepthTest(0)
|
||||
quad.setDepthWrite(0)
|
||||
quad.setColor(Vec4(1,0.5,0.5,1))
|
||||
|
||||
quadcamnode = Camera("filter-quad-cam")
|
||||
lens = OrthographicLens()
|
||||
lens.setFilmSize(2, 2)
|
||||
lens.setFilmOffset(0, 0)
|
||||
lens.setNearFar(-1000, 1000)
|
||||
quadcamnode.setLens(lens)
|
||||
quadcam = quad.attachNewNode(quadcamnode)
|
||||
|
||||
buffer.getDisplayRegion(0).setCamera(quadcam)
|
||||
buffer.getDisplayRegion(0).setActive(1)
|
||||
|
||||
self.buffers.append(buffer)
|
||||
self.sizes.append((1, 1, 1))
|
||||
|
||||
return quad
|
||||
|
||||
def createBuffer(self, name, xsize, ysize, texgroup, depthbits=1):
|
||||
""" Low-level buffer creation. Not intended for public use. """
|
||||
|
||||
print "Creating buffer: ",xsize,ysize,texgroup,depthbits
|
||||
winprops = WindowProperties()
|
||||
winprops.setSize(xsize, ysize)
|
||||
props = FrameBufferProperties()
|
||||
props.setRgbColor(1)
|
||||
props.setDepthBits(1)
|
||||
@ -177,6 +288,10 @@ class FilterManager:
|
||||
buffer.addRenderTexture(auxtex0, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPAuxRgba0)
|
||||
if (auxtex1):
|
||||
buffer.addRenderTexture(auxtex1, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPAuxRgba1)
|
||||
buffer.setSort(self.nextsort)
|
||||
buffer.disableClears()
|
||||
buffer.getDisplayRegion(0).disableClears()
|
||||
self.nextsort += 1
|
||||
return buffer
|
||||
|
||||
|
||||
@ -187,9 +302,12 @@ class FilterManager:
|
||||
for buffer in self.buffers:
|
||||
buffer.clearRenderTextures()
|
||||
self.engine.removeWindow(buffer)
|
||||
self.scales = []
|
||||
self.buffers = []
|
||||
self.region.setCamera(self.camera)
|
||||
self.sizes = []
|
||||
self.setClears(self.win, self.wclears)
|
||||
self.setClears(self.region, self.rclears)
|
||||
self.camera.node().setInitialState(self.caminit)
|
||||
|
||||
self.nextsort = self.win.getSort() - 1000
|
||||
self.basex = 0
|
||||
self.basey = 0
|
||||
|
||||
|
85
direct/src/filter/filter-bloomi.sha
Normal file
85
direct/src/filter/filter-bloomi.sha
Normal file
@ -0,0 +1,85 @@
|
||||
//Cg
|
||||
//
|
||||
// blend.rgb
|
||||
//
|
||||
// This shader converts to black-and-white before calculating
|
||||
// scene brightness. To do this, it uses a weighted average of
|
||||
// R,G,B. The blend parameter controls the weighting.
|
||||
//
|
||||
// desat.x
|
||||
//
|
||||
// Desaturation level. If zero, the bloom's color is equal to
|
||||
// the color of the input pixel. If one, the bloom's color is
|
||||
// white.
|
||||
//
|
||||
// trigger.x
|
||||
//
|
||||
// Must be equal to mintrigger.
|
||||
//
|
||||
// mintrigger is the minimum brightness to trigger a bloom,
|
||||
// and maxtrigger is the brightness at which the bloom
|
||||
// reaches maximum intensity.
|
||||
//
|
||||
// trigger.y
|
||||
//
|
||||
// Must be equal to (1.0/(maxtrigger-mintrigger)) where
|
||||
//
|
||||
// mintrigger is the minimum brightness to trigger a bloom,
|
||||
// and maxtrigger is the brightness at which the bloom
|
||||
// reaches maximum intensity.
|
||||
//
|
||||
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float2 l_texcoordNW : TEXCOORD0,
|
||||
out float2 l_texcoordNE : TEXCOORD1,
|
||||
out float2 l_texcoordSW : TEXCOORD2,
|
||||
out float2 l_texcoordSE : TEXCOORD3,
|
||||
uniform float4 texpad_src,
|
||||
uniform float4 texpix_src,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
|
||||
float4 offs = texpix_src * 0.5;
|
||||
l_texcoordNW = c + float2( offs.x, -offs.y);
|
||||
l_texcoordNE = c + float2( offs.x, offs.y);
|
||||
l_texcoordSW = c + float2(-offs.x, -offs.y);
|
||||
l_texcoordSE = c + float2(-offs.x, offs.y);
|
||||
}
|
||||
|
||||
void fshader(float2 l_texcoordNW : TEXCOORD0,
|
||||
float2 l_texcoordNE : TEXCOORD1,
|
||||
float2 l_texcoordSW : TEXCOORD2,
|
||||
float2 l_texcoordSE : TEXCOORD3,
|
||||
uniform sampler2D k_src : TEXUNIT0,
|
||||
out float4 o_color : COLOR,
|
||||
uniform float4 k_blend,
|
||||
uniform float4 k_trigger,
|
||||
uniform float4 k_desat
|
||||
)
|
||||
{
|
||||
float4 inputNW = tex2D(k_src, l_texcoordNW);
|
||||
float briteNW = dot(inputNW, k_blend);
|
||||
float scaleNW = saturate((briteNW - k_trigger.x) * k_trigger.y);
|
||||
float4 colorNW = scaleNW * lerp(inputNW, float4(1,1,1,1), k_desat.x);
|
||||
|
||||
float4 inputNE = tex2D(k_src, l_texcoordNE);
|
||||
float briteNE = dot(inputNE, k_blend);
|
||||
float scaleNE = saturate((briteNE - k_trigger.x) * k_trigger.y);
|
||||
float4 colorNE = scaleNE * lerp(inputNE, float4(1,1,1,1), k_desat.x);
|
||||
|
||||
float4 inputSW = tex2D(k_src, l_texcoordSW);
|
||||
float briteSW = dot(inputSW, k_blend);
|
||||
float scaleSW = saturate((briteSW - k_trigger.x) * k_trigger.y);
|
||||
float4 colorSW = scaleSW * lerp(inputSW, float4(1,1,1,1), k_desat.x);
|
||||
|
||||
float4 inputSE = tex2D(k_src, l_texcoordSE);
|
||||
float briteSE = dot(inputSE, k_blend);
|
||||
float scaleSE = saturate((briteSE - k_trigger.x) * k_trigger.y);
|
||||
float4 colorSE = scaleSE * lerp(inputSE, float4(1,1,1,1), k_desat.x);
|
||||
|
||||
o_color = (colorNW + colorNE + colorSW + colorSE) * 0.25;
|
||||
}
|
||||
|
47
direct/src/filter/filter-bloomx.sha
Normal file
47
direct/src/filter/filter-bloomx.sha
Normal file
@ -0,0 +1,47 @@
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float4 l_texcoord0 : TEXCOORD0,
|
||||
out float4 l_texcoord1 : TEXCOORD1,
|
||||
out float4 l_texcoord2 : TEXCOORD2,
|
||||
uniform float4 texpad_src,
|
||||
uniform float4 texpix_src,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
|
||||
float offset = texpix_src.x;
|
||||
l_texcoord0 = float4(c.x-offset* -4, c.x-offset* -3, c.x-offset* -2, c.y);
|
||||
l_texcoord1 = float4(c.x-offset* -1, c.x-offset* 0, c.x-offset* 1, c.y);
|
||||
l_texcoord2 = float4(c.x-offset* 2, c.x-offset* 3, c.x-offset* 4, c.y);
|
||||
}
|
||||
|
||||
void fshader(float4 l_texcoord0 : TEXCOORD0,
|
||||
float4 l_texcoord1 : TEXCOORD1,
|
||||
float4 l_texcoord2 : TEXCOORD2,
|
||||
uniform sampler2D k_src : TEXUNIT0,
|
||||
out float4 o_color : COLOR) {
|
||||
float4 color = float4(0,0,0,0);
|
||||
// color = 10 * tex2D(k_src, l_texcoord0.xw);
|
||||
// color += 45 * tex2D(k_src, l_texcoord0.yw);
|
||||
// color += 120 * tex2D(k_src, l_texcoord0.zw);
|
||||
// color += 210 * tex2D(k_src, l_texcoord1.xw);
|
||||
// color += 252 * tex2D(k_src, l_texcoord1.yw);
|
||||
// color += 210 * tex2D(k_src, l_texcoord1.zw);
|
||||
// color += 120 * tex2D(k_src, l_texcoord2.xw);
|
||||
// color += 45 * tex2D(k_src, l_texcoord2.yw);
|
||||
// color += 10 * tex2D(k_src, l_texcoord2.zw);
|
||||
// o_color = color / 1022.0;
|
||||
|
||||
color = 50 * tex2D(k_src, l_texcoord0.xw);
|
||||
color += 100 * tex2D(k_src, l_texcoord0.yw);
|
||||
color += 150 * tex2D(k_src, l_texcoord0.zw);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.xw);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.yw);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.zw);
|
||||
color += 150 * tex2D(k_src, l_texcoord2.xw);
|
||||
color += 100 * tex2D(k_src, l_texcoord2.yw);
|
||||
color += 50 * tex2D(k_src, l_texcoord2.zw);
|
||||
o_color = color / 1200.0;
|
||||
}
|
38
direct/src/filter/filter-bloomy.sha
Normal file
38
direct/src/filter/filter-bloomy.sha
Normal file
@ -0,0 +1,38 @@
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float4 l_texcoord0 : TEXCOORD0,
|
||||
out float4 l_texcoord1 : TEXCOORD1,
|
||||
out float4 l_texcoord2 : TEXCOORD2,
|
||||
uniform float4 texpad_src,
|
||||
uniform float4 texpix_src,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
|
||||
float offset = texpix_src.y;
|
||||
l_texcoord0 = float4(c.y-offset* -4, c.y-offset* -3, c.y-offset* -2, c.x);
|
||||
l_texcoord1 = float4(c.y-offset* -1, c.y-offset* 0, c.y-offset* 1, c.x);
|
||||
l_texcoord2 = float4(c.y-offset* 2, c.y-offset* 3, c.y-offset* 4, c.x);
|
||||
}
|
||||
|
||||
void fshader(float4 l_texcoord0 : TEXCOORD0,
|
||||
float4 l_texcoord1 : TEXCOORD1,
|
||||
float4 l_texcoord2 : TEXCOORD2,
|
||||
uniform sampler2D k_src : TEXUNIT0,
|
||||
uniform float4 k_intensity,
|
||||
out float4 o_color : COLOR) {
|
||||
float4 color = float4(0,0,0,0);
|
||||
color = 50 * tex2D(k_src, l_texcoord0.wx);
|
||||
color += 100 * tex2D(k_src, l_texcoord0.wy);
|
||||
color += 150 * tex2D(k_src, l_texcoord0.wz);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.wx);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.wy);
|
||||
color += 200 * tex2D(k_src, l_texcoord1.wz);
|
||||
color += 150 * tex2D(k_src, l_texcoord2.wx);
|
||||
color += 100 * tex2D(k_src, l_texcoord2.wy);
|
||||
color += 50 * tex2D(k_src, l_texcoord2.wz);
|
||||
o_color = color / 1200.0;
|
||||
o_color = o_color * k_intensity;
|
||||
}
|
20
direct/src/filter/filter-copy.sha
Normal file
20
direct/src/filter/filter-copy.sha
Normal file
@ -0,0 +1,20 @@
|
||||
//Cg
|
||||
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float2 l_texcoord : TEXCOORD0,
|
||||
uniform float4 texpad_src,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
l_texcoord = (vtx_position.xz * texpad_src.xy) + texpad_src.xy;
|
||||
}
|
||||
|
||||
void fshader(float2 l_texcoord : TEXCOORD0,
|
||||
uniform sampler2D k_src : TEXUNIT0,
|
||||
out float4 o_color : COLOR)
|
||||
{
|
||||
o_color = tex2D(k_src, l_texcoord);
|
||||
}
|
||||
|
33
direct/src/filter/filter-down4.sha
Normal file
33
direct/src/filter/filter-down4.sha
Normal file
@ -0,0 +1,33 @@
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
out float4 l_position : POSITION,
|
||||
out float2 l_texcoordNW : TEXCOORD0,
|
||||
out float2 l_texcoordNE : TEXCOORD1,
|
||||
out float2 l_texcoordSW : TEXCOORD2,
|
||||
out float2 l_texcoordSE : TEXCOORD3,
|
||||
uniform float4 texpad_src,
|
||||
uniform float4 texpix_src,
|
||||
uniform float4x4 mat_modelproj)
|
||||
{
|
||||
l_position=mul(mat_modelproj, vtx_position);
|
||||
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
|
||||
l_texcoordNW = c + float2( texpix_src.x, -texpix_src.y);
|
||||
l_texcoordNE = c + float2( texpix_src.x, texpix_src.y);
|
||||
l_texcoordSW = c + float2(-texpix_src.x, -texpix_src.y);
|
||||
l_texcoordSE = c + float2(-texpix_src.x, texpix_src.y);
|
||||
}
|
||||
|
||||
void fshader(float2 l_texcoordNW : TEXCOORD0,
|
||||
float2 l_texcoordNE : TEXCOORD1,
|
||||
float2 l_texcoordSW : TEXCOORD2,
|
||||
float2 l_texcoordSE : TEXCOORD3,
|
||||
uniform sampler2D k_src : TEXUNIT0,
|
||||
out float4 o_color : COLOR) {
|
||||
float4 colorNW = tex2D(k_src, l_texcoordNW);
|
||||
float4 colorNE = tex2D(k_src, l_texcoordNE);
|
||||
float4 colorSW = tex2D(k_src, l_texcoordSW);
|
||||
float4 colorSE = tex2D(k_src, l_texcoordSE);
|
||||
o_color = (colorNW + colorNE + colorSW + colorSE);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user