diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index 9ced537dbd..22645dd99d 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -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") diff --git a/direct/src/filter/FilterManager.py b/direct/src/filter/FilterManager.py index 32c52f7350..73b1d732c4 100644 --- a/direct/src/filter/FilterManager.py +++ b/direct/src/filter/FilterManager.py @@ -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 diff --git a/direct/src/filter/filter-bloomi.sha b/direct/src/filter/filter-bloomi.sha new file mode 100644 index 0000000000..37d6556377 --- /dev/null +++ b/direct/src/filter/filter-bloomi.sha @@ -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; +} + diff --git a/direct/src/filter/filter-bloomx.sha b/direct/src/filter/filter-bloomx.sha new file mode 100644 index 0000000000..6819936fc4 --- /dev/null +++ b/direct/src/filter/filter-bloomx.sha @@ -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; +} diff --git a/direct/src/filter/filter-bloomy.sha b/direct/src/filter/filter-bloomy.sha new file mode 100644 index 0000000000..2351c70dd3 --- /dev/null +++ b/direct/src/filter/filter-bloomy.sha @@ -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; +} diff --git a/direct/src/filter/filter-copy.sha b/direct/src/filter/filter-copy.sha new file mode 100644 index 0000000000..ce7f867554 --- /dev/null +++ b/direct/src/filter/filter-copy.sha @@ -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); +} + diff --git a/direct/src/filter/filter-down4.sha b/direct/src/filter/filter-down4.sha new file mode 100644 index 0000000000..54d2967262 --- /dev/null +++ b/direct/src/filter/filter-down4.sha @@ -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); +} +