I’ve searched a little bit, disabled Starling, Dragonbones and Sounds and it seems that Starling alone generates such problems. I decided to move everything from Starling to OpenFL and for that I need DisplacementMapFilter working or at least knowing how to implement custom filters. I bet having DisplacementMapFilter within OpenFL itself is much better for the community so I’ve tried but I’m stuck and I guess I need your help a little bit. I cannot get this to work - as you can see, I’ve commented out gl_FragColor and made it fully red but no changes are displayed on the screen - I get the exact same bitmap even though shader is at least validated because I can put a breakpoint within __initShader and it catches activity in there.
Shader and mappings are based on Starling implementation for now.
This is my filter Work-In-Progress (ImageDataUitl.displace() also).
package openfl.filters;
#if !flash
// TODO
import lime._internal.graphics.ImageDataUtil;
// TODO
import openfl.display.BitmapDataChannel;
import openfl.geom.Matrix3D;
import openfl.geom.Rectangle;
import openfl.geom.Point;
import openfl.display.BitmapData;
import openfl.display.DisplayObjectRenderer;
import openfl.display.Shader;
import openfl.geom.ColorTransform;
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
@:access(openfl.geom.Point)
@:access(openfl.geom.Rectangle)
@:final class DisplacementMapFilter extends BitmapFilter {
@:noCompletion private static var __displacementMapShader = new DisplacementMapShader();
public var alpha (get, set):Float;
public var color (get, set):Int;
// public var componentX (get, set):Int;
// public var componentY (get, set):Int;
// public var mapBitmap (get, set):BitmapData;
// public var mapPoint (get, set):Point;
// public var mode (get, set):String;
// public var scaleX (get, set):Float;
// public var scaleY (get, set):Float;
@:noCompletion private var __alpha:Float;
@:noCompletion private var __color:Int;
@:noCompletion private var __componentX:Int;
@:noCompletion private var __componentY:Int;
@:noCompletion private var __mapBitmap:BitmapData;
@:noCompletion private var __mapPoint:Point;
@:noCompletion private var __mode:String;
@:noCompletion private var __scaleX:Float;
@:noCompletion private var __scaleY:Float;
@:noCompletion private var __horizontalPasses:Int;
@:noCompletion private var __verticalPasses:Int;
private static var sOffset:Array<Float> = [0.5, 0.5, 0.0, 0.0];
private static var sMatrix:Matrix3D = new Matrix3D();
private static var sMatrixData:Array<Float> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
public function new(mapBitmap:BitmapData = null, mapPoint:Point = null, componentX:Int = 0, componentY:Int = 0, scaleX:Float = 0.0, scaleY:Float = 0.0, mode:String = 'wrap', color:Int = 0, alpha:Float = 0.0) {
super();
__color = color;
__alpha = alpha;
__componentX = componentX;
__componentY = componentY;
__mapBitmap = mapBitmap;
__mapPoint = mapPoint;
__mode = mode;
__scaleX = scaleX;
__scaleY = scaleY;
__needSecondBitmapData = false;
__preserveObject = true;
__renderDirty = true;
__numShaderPasses = 1;
}
public override function clone():BitmapFilter {
return new DisplacementMapFilter (
__mapBitmap.clone(),
__mapPoint.clone(),
__componentX,
__componentY,
__scaleX,
__scaleY,
__mode,
__color,
__alpha
);
}
@:noCompletion private override function __applyFilter(bitmapData:BitmapData, sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point):BitmapData {
ImageDataUtil.displace(bitmapData.image, sourceBitmapData.image, __mapBitmap.image, __componentX, __componentY, __scaleX, __scaleY);
return bitmapData;
}
private function __getMapMatrix(out:Matrix3D):Matrix3D {
if (out == null) {
out = new Matrix3D();
}
var columnX:Int, columnY:Int;
var scale:Float = 1.0;
var textureWidth:Float = 720.0;
var textureHeight:Float = 660.0;
for (i in 0...16) {
sMatrixData[i] = 0;
}
if (__componentX == BitmapDataChannel.RED) {
columnX = 0;
} else if (__componentX == BitmapDataChannel.GREEN) {
columnX = 1;
} else if (__componentX == BitmapDataChannel.BLUE) {
columnX = 2;
} else {
columnX = 3;
}
if (__componentY == BitmapDataChannel.RED) {
columnY = 0;
} else if (__componentY == BitmapDataChannel.GREEN) {
columnY = 1;
} else if (__componentY == BitmapDataChannel.BLUE) {
columnY = 2;
} else {
columnY = 3;
}
sMatrixData[Std.int(columnX * 4)] = __scaleX * scale / textureWidth;
sMatrixData[Std.int(columnY * 4 + 1)] = __scaleY * scale / textureHeight;
out.copyRawDataFrom(new Vector<Float>(16, true, sMatrixData));
return out;
}
@:noCompletion private override function __initShader(renderer:DisplayObjectRenderer, pass:Int):Shader {
#if !macro
__getMapMatrix(sMatrix);
__displacementMapShader.offsets.value = sOffset;
__displacementMapShader.displacements.value = sMatrixData;
__displacementMapShader.mapTexture.input = __mapBitmap;
#end
js.Browser.console.log(__displacementMapShader);
return __displacementMapShader;
}
// Get & Set Methods
@:noCompletion private function get_alpha():Float {
return __alpha;
}
@:noCompletion private function set_alpha(value:Float):Float {
if (value != __alpha) {
__renderDirty = true;
}
return __alpha = value;
}
@:noCompletion private function get_color():Int {
return __color;
}
@:noCompletion private function set_color(value:Int):Int {
if (value != __color) {
__renderDirty = true;
}
return __color = value;
}
}
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
private class DisplacementMapShader extends BitmapFilterShader {
@:glFragmentSource(
"
uniform sampler2D openfl_Texture;
uniform sampler2D mapTexture;
uniform mat4 openfl_Matrix;
uniform vec4 offsets;
uniform mat4 displacements;
varying vec2 openfl_TextureCoordv;
varying vec2 mapTextureCoordv;
void main(void) {
vec4 map_coords = texture2D(mapTexture, mapTextureCoordv);
vec4 map_coords_offseted = map_coords - offsets;
vec4 displacements_multiplied = map_coords_offseted * openfl_Matrix;
vec4 result = vec4(openfl_TextureCoordv, 0.0, 0.0) + displacements_multiplied;
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //texture2D(openfl_Texture, vec2(result));
}
"
)
@:glVertexSource(
"
uniform mat4 openfl_Matrix;
attribute vec4 openfl_Position;
attribute vec2 openfl_TextureCoord;
varying vec2 openfl_TextureCoordv;
varying vec2 mapTextureCoordv;
void main(void) {
gl_Position = openfl_Matrix * openfl_Position;
openfl_TextureCoordv = openfl_TextureCoord;
mapTextureCoordv = openfl_TextureCoord;
}
"
)
public function new() {
super();
#if !macro
offsets.value = [0.5, 0.5, 0.0, 0.0];
displacements.value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
#end
}
}
#else
typedef DisplacementMapFilter = flash.filters.DisplacementMapFilter;
#end
and this is my test app:
class Main extends Sprite {
public function new() {
super();
this.addChild(new Bitmap(Assets.getBitmapData('assets/test.png')));
this.filters = [
new DisplacementMapFilter(
Assets.getBitmapData('assets/test_map.jpg')
)
];
}
}