123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- package h3d.pass;
- @ignore("shader")
- class Blur extends ScreenFx<h3d.shader.Blur> {
- /**
- How far in pixels the blur will go.
- **/
- public var radius(default,set) : Float;
- /**
- How much the blur increases or decreases the color amount (default = 1)
- **/
- public var gain(default,set) : Float;
- /**
- Set linear blur instead of gaussian (default = 0).
- **/
- public var linear(default, set) : Float;
- /**
- Adjust how much quality/speed tradeoff we want (default = 1)
- **/
- public var quality(default,set) : Float;
- var values : Array<Float>;
- var offsets : Array<Float>;
- public function new( radius = 1., gain = 1., linear = 0., quality = 1. ) {
- super(new h3d.shader.Blur());
- this.radius = radius;
- this.quality = quality;
- this.gain = gain;
- }
- function set_radius(r) {
- if( radius == r )
- return r;
- values = null;
- return radius = r;
- }
- function set_quality(q) {
- if( quality == q )
- return q;
- values = null;
- return quality = q;
- }
- function set_gain(s) {
- if( gain == s )
- return s;
- values = null;
- return gain = s;
- }
- function set_linear(b) {
- if( linear == b )
- return b;
- values = null;
- return linear = b;
- }
- function gauss( x:Float, s:Float ) : Float {
- if( s <= 0 ) return x == 0 ? 1 : 0;
- var sq = s * s;
- var p = Math.pow(2.718281828459, -(x * x) / (2 * sq));
- return p / Math.sqrt(2 * Math.PI * sq);
- }
- function calcValues() {
- values = [];
- offsets = [];
- var tot = 0.;
- var qadj = hxd.Math.clamp(quality) * 0.7 + 0.3;
- var width = radius > 0 ? Math.ceil(hxd.Math.max(radius - 1, 1) * qadj / 2) : 0;
- var sigma = Math.sqrt(radius) * 2;
- for( i in 0...width + 1 ) {
- var i1 = i * 2;
- var i2 = i == 0 ? 0 : i * 2 - 1;
- var g1 = gauss(i1, sigma);
- var g2 = gauss(i2,sigma);
- var g = g1 + g2;
- values[i] = g;
- offsets[i] = i == 0 ? 0 : (g1 * i1 + g2 * i2) / (g * i * Math.sqrt(qadj));
- tot += g;
- if( i > 0 ) tot += g;
- }
- // eliminate too low contributing values
- var minVal = values[0] * (0.01 / qadj);
- while( values.length > 2 ) {
- var last = values[values.length-1];
- if( last > minVal ) break;
- tot -= last * 2;
- values.pop();
- }
- tot /= gain;
- for( i in 0...values.length )
- values[i] /= tot;
- if( linear > 0 ) {
- var m = gain / (values.length * 2 - 1);
- for( i in 0...values.length ) {
- values[i] = hxd.Math.lerp(values[i], m, linear);
- offsets[i] = hxd.Math.lerp(offsets[i], i == 0 ? 0 : (i * 2 - 0.5) / (i * qadj), linear);
- }
- }
- }
- public function getKernelSize() {
- if( values == null ) calcValues();
- return radius <= 0 ? 0 : values.length * 2 - 1;
- }
- public function apply( ctx : h3d.impl.RenderContext, src : h3d.mat.Texture, ?output : h3d.mat.Texture ) {
- if( radius <= 0 && shader.fixedColor == null ) {
- if( output != null ) Copy.run(src, output);
- return;
- }
- if( output == null ) output = src;
- if( values == null ) calcValues();
- var tmp = ctx.textures.allocTarget(src.name+"BlurTmp",src.width,src.height,false,src.format);
- shader.Quality = values.length;
- shader.values = values;
- shader.offsets = offsets;
- shader.texture = src;
- shader.pixel.set(1 / src.width, 0);
- engine.pushTarget(tmp);
- render();
- engine.popTarget();
- shader.texture = tmp;
- shader.pixel.set(0, 1 / src.height);
- var outDepth = output.depthBuffer;
- output.depthBuffer = null;
- engine.pushTarget(output);
- render();
- engine.popTarget();
- output.depthBuffer = outDepth;
- }
- }
|