diff --git a/features/display/Shaders/Assets/diffuse.png b/features/display/Shaders/Assets/diffuse.png new file mode 100644 index 0000000..0c64abf Binary files /dev/null and b/features/display/Shaders/Assets/diffuse.png differ diff --git a/features/display/Shaders/Assets/normals.png b/features/display/Shaders/Assets/normals.png new file mode 100644 index 0000000..3051097 Binary files /dev/null and b/features/display/Shaders/Assets/normals.png differ diff --git a/features/display/Shaders/Assets/openfl.png b/features/display/Shaders/Assets/openfl.png new file mode 100644 index 0000000..dc6895c Binary files /dev/null and b/features/display/Shaders/Assets/openfl.png differ diff --git a/features/display/Shaders/Assets/openfl.svg b/features/display/Shaders/Assets/openfl.svg new file mode 100644 index 0000000..ff69474 --- /dev/null +++ b/features/display/Shaders/Assets/openfl.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/features/display/Shaders/Assets/openfl_logo.png b/features/display/Shaders/Assets/openfl_logo.png new file mode 100644 index 0000000..daddf98 Binary files /dev/null and b/features/display/Shaders/Assets/openfl_logo.png differ diff --git a/features/display/Shaders/Source/BitmapExample.hx b/features/display/Shaders/Source/BitmapExample.hx new file mode 100644 index 0000000..07b1720 --- /dev/null +++ b/features/display/Shaders/Source/BitmapExample.hx @@ -0,0 +1,83 @@ +package; +import openfl.Assets; +import openfl.display.Bitmap; +import openfl.display.BitmapData; +import openfl.display.Sprite; +import openfl.events.Event; +import openfl.events.KeyboardEvent; +import openfl.events.MouseEvent; +import openfl.geom.Point; +import openfl.Lib; +import openfl.ui.Keyboard; +import shaders.BackgroundShader; + +class BitmapExample extends Sprite +{ + + public function new() + { + super(); + addEventListener(Event.ADDED_TO_STAGE, init); + } + + function init(_) { + + // we create a transparent bitmap + var bd = new BitmapData(stage.stageWidth, stage.stageHeight); + var bmp = new Bitmap(bd); + addChild(bmp); + + // and initialize our shader + var bgShader = new BackgroundShader(); + bgShader.uZoom = 800 * bmp.scaleX; + // As an example, we add a bitmap to show how we can use BitmapDatas in our shader + bgShader.uSampler1 = Assets.getBitmapData("assets/openfl.png"); + + bmp.shader = bgShader; + + var movement = new Point(); + + var t = Lib.getTimer() / 1000; + // we update its parameters each frame + addEventListener(Event.ENTER_FRAME, function(_) { + bgShader.uGlobalTime = (Lib.getTimer() / 1000) - t; + bgShader.uMovement[0] += movement.x; + bgShader.uMovement[1] += movement.y; + }); + + // keep the background always there when resizing the stage + stage.addEventListener(Event.RESIZE, function(_) { + bmp.scaleX = stage.stageWidth / bmp.bitmapData.width; + bmp.scaleY = stage.stageHeight / bmp.bitmapData.height; + bgShader.uZoom = 800 * bmp.scaleX; + }); + + // some movement logic + stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent) { + switch(e.keyCode) { + case Keyboard.RIGHT: + movement.x = -1; + case Keyboard.LEFT: + movement.x = 1; + case Keyboard.UP: + movement.y = -1; + case Keyboard.DOWN: + movement.y = 1; + } + }); + + stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent) { + switch(e.keyCode) { + case Keyboard.RIGHT: + movement.x = 0; + case Keyboard.LEFT: + movement.x = 0; + case Keyboard.UP: + movement.y = 0; + case Keyboard.DOWN: + movement.y = 0; + } + }); + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/FilterExample.hx b/features/display/Shaders/Source/FilterExample.hx new file mode 100644 index 0000000..a4a67fa --- /dev/null +++ b/features/display/Shaders/Source/FilterExample.hx @@ -0,0 +1,142 @@ +package; +import openfl._legacy.display.BitmapData; +import openfl.Assets; +import openfl.display.Bitmap; +import openfl.display.Shape; +import openfl.display.Sprite; +import openfl.events.Event; +import openfl.display.Shader; +import openfl.events.KeyboardEvent; +import openfl.filters.BitmapFilter; +import openfl.filters.BlurFilter; +import openfl.filters.ColorMatrixFilter; +import openfl.filters.DropShadowFilter; +import openfl.filters.GlowFilter; +import openfl.filters.ShaderFilter; +import openfl.geom.ColorTransform; +#if !flash +import shaders.DotShader; +import shaders.RGBShiftShader; +#end +import openfl.geom.Rectangle; +import openfl.text.TextField; +import openfl.text.TextFormat; +import openfl.ui.Keyboard; + +class FilterExample extends Sprite { + + public function new() { + super(); + addEventListener(Event.ADDED_TO_STAGE, init); + } + + function init(_) { + + var bitmapData = Assets.getBitmapData("assets/openfl.png"); + var left = new Sprite(); + var right = new Sprite(); + addChild(left); + addChild(right); + left.addChild(new Bitmap(bitmapData)); + right.addChild(new Bitmap(bitmapData)); + left.y = right.y = stage.stageHeight / 2 - bitmapData.height / 2; + right.x = left.x + left.width; + + var text = new TextField(); + text.defaultTextFormat = new TextFormat('_sans', 32, 0xFFFFFF); + text.text = "OpenFL with filters!"; + text.x = 100; + text.y = 100; + text.width = 600; + text.filters = [new DropShadowFilter(), new GlowFilter(),]; + addChild(text); + + var shape = new Shape(); + shape.graphics.beginFill(0xEE00EE); + shape.graphics.drawCircle(100, 100, 100); + shape.x = 200; + shape.y = 200; + shape.filters = [new DropShadowFilter()]; + addChild(shape); + + var normal:Array = [ + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0 + ]; + var sepia:Array = [ + 0.393, 0.7689999, 0.18899999, 0, 0, + 0.349, 0.6859999, 0.16799999, 0, 0, + 0.272, 0.5339999, 0.13099999, 0, 0, + 0,0,0,1,0 + ]; + var invert:Array = [ + -1, 0, 0, 0, 255, + 0, -1, 0, 0, 255, + 0, 0, -1, 0, 255, + 0, 0, 0, 1, 0 + ]; + var grayscale:Array = [ + 0.5, 0.5, 0.5, 0, 0, + 0.5, 0.5, 0.5, 0, 0, + 0.5, 0.5, 0.5, 0, 0, + 0, 0, 0, 1, 0 + ]; + + var colors = [normal, sepia, invert, grayscale]; + var randColors = function() { + return colors[Std.int(colors.length * Math.random())]; + }; + + var blurFilter = new BlurFilter(); + var colorMatrixFilter = new ColorMatrixFilter(randColors()); + + #if flash + var filterArray:Array = [blurFilter, colorMatrixFilter]; + #else + + var rgbShader = new RGBShiftShader(); + var rgbFilter = new ShaderFilter(rgbShader); + // this filter needs to extend the cached bitmap + rgbFilter.topExtension = rgbFilter.bottomExtension = 4; + rgbFilter.leftExtension = rgbFilter.rightExtension = 4; + + var filterArray:Array = [rgbFilter, blurFilter, colorMatrixFilter]; + #end + + this.filters = filterArray; + + var removeFilters = false; + var added = true; + stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent) { + switch(e.keyCode) { + case Keyboard.C: + colorMatrixFilter.matrix = randColors(); + case Keyboard.S: + if(added) + removeChild(shape); + else + addChild(shape); + added = !added; + case _: + removeFilters = !removeFilters; + } + + this.filters = removeFilters ? null : filterArray; + }); + + + addEventListener(Event.ENTER_FRAME, function(_) { + #if !flash + rgbShader.angle += 0.05; + + // We need to re-apply the filters to signal the cached bitmap to update. + this.filters = removeFilters ? null : filterArray; + #end + }); + } + +} + + diff --git a/features/display/Shaders/Source/LightExample.hx b/features/display/Shaders/Source/LightExample.hx new file mode 100644 index 0000000..d98fd4b --- /dev/null +++ b/features/display/Shaders/Source/LightExample.hx @@ -0,0 +1,61 @@ +package; + +import openfl.Assets; +import openfl.display.Bitmap; +import openfl.display.BitmapData; +import openfl.display.Shader; +import openfl.display.Sprite; +import openfl.events.Event; +import openfl.events.MouseEvent; +import openfl.geom.Point; +import openfl.Lib; +import shaders.LightShader; + +/** + * ... + * @author MrCdK + */ +class LightExample extends Sprite { + + public function new() { + super(); + addEventListener(Event.ADDED_TO_STAGE, init); + } + + function init(_) { + // diffuse.png and normals.png from http://www.goodboydigital.com/pixijs/examples/20/ + var diffuse = Assets.getBitmapData("assets/diffuse.png"); + var normal = Assets.getBitmapData("assets/normals.png"); + + var sprite = new Sprite(); + addChild(sprite); + sprite.addChild(new Bitmap(diffuse)); + + var lightShader = new LightShader(); + sprite.shader = lightShader; + + lightShader.uSamplerN = normal; + lightShader.uAmbientColor = [0.6, 0.6, 1, 0.2]; + lightShader.uLightColor = [1, 0.8, 0.6, 1]; + lightShader.uLightPos = [0, 0, 0.075]; + lightShader.uFalloff = [0.4, 1, 20]; + lightShader.uResolution = [sprite.width, sprite.height]; + + stage.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent) { + lightShader.uLightPos[0] = e.stageX; + lightShader.uLightPos[1] = e.stageY; + }); + + stage.addEventListener(MouseEvent.MOUSE_WHEEL, function(e:MouseEvent) { + lightShader.uLightPos[2] += e.delta * 0.005; + }); + + var bounds; + stage.addEventListener(Event.RESIZE, function(_) { + sprite.scaleX = stage.stageWidth / diffuse.width; + sprite.scaleY = stage.stageHeight / diffuse.height; + lightShader.uResolution = [stage.stageWidth, stage.stageHeight]; + }); + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/Main.hx b/features/display/Shaders/Source/Main.hx new file mode 100644 index 0000000..30fedf2 --- /dev/null +++ b/features/display/Shaders/Source/Main.hx @@ -0,0 +1,27 @@ +package; + +import openfl.display.Bitmap; +import openfl.display.BitmapData; +import openfl.display.FPS; +import openfl.display.Shader; +import openfl.display.Sprite; +import openfl.events.Event; +import openfl.events.MouseEvent; +import openfl.geom.ColorTransform; +import openfl.Lib; +import flash.net.SharedObject; + +class Main extends Sprite { + + public function new() { + super(); + addChild(new BitmapExample()); + //addChild(new SpriteExample()); + //addChild(new FilterExample()); + //addChild(new TilesheetExample()); + //addChild(new LightExample()); + + addChild(new FPS(10, 10)); + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/SpriteExample.hx b/features/display/Shaders/Source/SpriteExample.hx new file mode 100644 index 0000000..9b3661d --- /dev/null +++ b/features/display/Shaders/Source/SpriteExample.hx @@ -0,0 +1,55 @@ +package; + +import openfl._legacy.display.BitmapData; +import openfl.Assets; +import openfl.display.Bitmap; +import openfl.display.Sprite; +import openfl.events.Event; +import openfl.display.Shader; +import openfl.events.KeyboardEvent; +import openfl.filters.BlurFilter; +import openfl.geom.Rectangle; +import shaders.DotShader; +import shaders.RGBShiftShader; + + +class SpriteExample extends Sprite { + + public function new() { + super(); + addEventListener(Event.ADDED_TO_STAGE, init); + } + + function init(_) { + + // we initialize stuff + var bitmapData = Assets.getBitmapData("assets/openfl.png"); + var left = new Sprite(); + var right = new Sprite(); + addChild(left); + addChild(right); + var bm1 = new Bitmap(bitmapData); + var bm2 = new Bitmap(bitmapData); + + left.addChild(bm1); + right.addChild(bm2); + + left.y = right.y = stage.stageHeight / 2 - bitmapData.height / 2; + right.x = left.x + left.width; + + var rgbShader = new RGBShiftShader(); + var dotShader = new DotShader(); + + // The rgbShader will be applied to all the children of this sprite + this.shader = rgbShader; + + // but "right" will have a dotShader, so it won't have applied the rgbShader + right.shader = dotShader; + + stage.addEventListener(KeyboardEvent.KEY_DOWN, function(_) { + this.cacheAsBitmap = !this.cacheAsBitmap; + }); + + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/TilesheetExample.hx b/features/display/Shaders/Source/TilesheetExample.hx new file mode 100644 index 0000000..61ed94e --- /dev/null +++ b/features/display/Shaders/Source/TilesheetExample.hx @@ -0,0 +1,68 @@ +package; + +import openfl.Assets; +import openfl.display.Sprite; +import openfl.display.Tilesheet; +import openfl.events.Event; +import openfl.events.KeyboardEvent; +import openfl.geom.Matrix; +import openfl.geom.Rectangle; +import openfl.ui.Keyboard; +import shaders.RGBShiftShader; + +class TilesheetExample extends Sprite { + + public function new() { + super(); + addEventListener(Event.ADDED_TO_STAGE, init); + } + + function init(_) { + // Our usual setup + var sprite = new Sprite(); + addChild(sprite); + + var bitmapData = Assets.getBitmapData("assets/openfl.png"); + var sy = stage.stageHeight / 2 - bitmapData.height / 2; + // the tilesheet array + var tsArray = [0, sy, 0, bitmapData.width, sy, 0]; + // we create the tilesheet object + var tilesheet = new Tilesheet(bitmapData); + tilesheet.addTileRect(bitmapData.rect); + + var rgbShader = new RGBShiftShader(); + rgbShader.amount += 0.05; + + // The matrix we will apply to the cached bitmap + var m = new Matrix(); + m.scale(0.4, 0.4); + m.rotate(45); + // we assign the matrix + sprite.cacheAsBitmapMatrix = m; + sprite.cacheAsBitmap = true; + // and disable smooth on the cached bitmap + sprite.cacheAsBitmapSmooth = false; + + sprite.graphics.drawTiles(tilesheet, tsArray, rgbShader); + + var swapShader = false; + stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e) { + switch(e.keyCode) { + case Keyboard.C: + sprite.cacheAsBitmap = !sprite.cacheAsBitmap; + trace("The sprite " + (sprite.cacheAsBitmap ? "is cached" : "isn't cached")); + case Keyboard.S: + sprite.cacheAsBitmapSmooth = !sprite.cacheAsBitmapSmooth; + trace("The cached sprite " + (sprite.cacheAsBitmapSmooth ? "is smooth" : "isn't smooth")); + case Keyboard.SPACE: + swapShader = !swapShader; + sprite.shader = swapShader ? rgbShader : null; + sprite.graphics.drawTiles(tilesheet, tsArray, swapShader ? null : rgbShader); + // we need to reassign the value so that the cached bitmap can be updated + sprite.cacheAsBitmap = sprite.cacheAsBitmap; + trace("The shader is applied to " + (swapShader ? "the sprite" : "the drawTiles function")); + } + }); + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/shaders/BackgroundShader.hx b/features/display/Shaders/Source/shaders/BackgroundShader.hx new file mode 100644 index 0000000..201dc09 --- /dev/null +++ b/features/display/Shaders/Source/shaders/BackgroundShader.hx @@ -0,0 +1,44 @@ +package shaders; + +import openfl.display.Shader; + +class BackgroundShader extends Shader { + + // Created by inigo quilez - iq/2015 + // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + // https://www.shadertoy.com/view/Ml2GWy + @fragment var code = [ + 'uniform float uZoom;', + 'uniform float uGlobalTime;', + 'uniform vec2 uMovement;', + 'uniform sampler2D uSampler1;', + 'void main() {', + ' vec2 pos = 256.0*gl_FragCoord.xy/uZoom;', + ' pos -= uMovement;', + ' vec3 col = vec3(0.0);', + ' for( int i=0; i<6; i++ ) ', + ' {', + ' vec2 a = floor(pos);', + ' vec2 b = fract(pos);', + ' vec4 w = fract((sin(a.x*7.0+31.0*a.y + 0.01*uGlobalTime)+vec4(0.035,0.01,0.0,0.7))*13.545317); // randoms', + ' col += w.xyz * // color', + ' smoothstep(0.45,0.55,w.w) * // intensity', + ' sqrt( 16.0*b.x*b.y*(1.0-b.x)*(1.0-b.y) ); // pattern', + ' pos /= 2.0; // lacunarity', + ' col /= 2.0; // attenuate high frequencies', + ' }', + ' col = pow( 2.5*col, vec3(1.0,1.0,0.7) ); // contrast and color shape', + ' vec4 final = vec4( col, 1.0 ) * texture2D(uSampler1, ${Shader.vTexCoord});', + ' gl_FragColor = colorTransform(final, ${Shader.vColor}, ${Shader.uColorMultiplier}, ${Shader.uColorOffset});', + '}', + ]; + + public function new() { + super(); + // default values + uZoom = 800; + // we can access the automatically created GLShaderParamenter to change some values we can't change with the public property + __uSampler1.smooth = true; + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/shaders/DotShader.hx b/features/display/Shaders/Source/shaders/DotShader.hx new file mode 100644 index 0000000..a299e83 --- /dev/null +++ b/features/display/Shaders/Source/shaders/DotShader.hx @@ -0,0 +1,45 @@ +package shaders; + +import openfl.display.Shader; + +/** + * @author alteredq / http://alteredqualia.com/ + * + * Dot screen shader + * based on glfx.js sepia shader + * https://github.com/evanw/glfx.js + */ +class DotShader extends Shader { + + // https://github.com/mrdoob/three.js/blob/master/examples/js/shaders/DotScreenShader.js + @fragment var fragment = [ + + 'uniform vec2 center;', + 'uniform float angle;', + 'uniform float scale;', + + 'float pattern() {', + 'float s = sin( angle ), c = cos( angle );', + 'vec2 tex = ${Shader.vTexCoord} * ${Shader.uTextureSize} - center;', + 'vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;', + 'return ( sin( point.x ) * sin( point.y ) ) * 4.0;', + '}', + + 'void main() {', + 'vec4 color = texture2D( ${Shader.uSampler}, ${Shader.vTexCoord} );', + 'float average = ( color.r + color.g + color.b ) / 3.0;', + 'float p = pattern();', + 'gl_FragColor = vec4(vec3( average * 10.0 - 5.0 + p ), color.a);', + '}' + ]; + + public function new() { + super(); + + //default values + scale = 0.5; + angle = 1.57; + center = [0.5, 0.5]; + } + +} \ No newline at end of file diff --git a/features/display/Shaders/Source/shaders/LightShader.hx b/features/display/Shaders/Source/shaders/LightShader.hx new file mode 100644 index 0000000..bc7353e --- /dev/null +++ b/features/display/Shaders/Source/shaders/LightShader.hx @@ -0,0 +1,40 @@ +package shaders; +import openfl.display.Shader; + +class LightShader extends Shader { + + // based on https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6 + @fragment var fragment = [ + 'uniform vec3 uLightPos;', + 'uniform vec4 uLightColor;', + 'uniform vec4 uAmbientColor;', + 'uniform vec3 uFalloff;', + 'uniform vec2 uResolution;', + 'uniform sampler2D uSamplerN;', + + 'void main(void) {', + ' vec4 dc = texture2D(${Shader.uSampler}, ${Shader.vTexCoord});', + ' vec3 nc = texture2D(uSamplerN, ${Shader.vTexCoord}).rgb;', + + ' vec3 ld = vec3((uLightPos.xy/uResolution.xy) - ${Shader.vTexCoord}, uLightPos.z);', + ' ld.x *= uResolution.x / uResolution.y;', + + ' float D = length(ld);', + ' vec3 N = normalize(nc * 2.0 - 1.0);', + ' vec3 L = normalize(ld);', + + ' vec3 diffuse = (uLightColor.rgb * uLightColor.a) * max(dot(N, L), 0.0);', + ' vec3 ambient = uAmbientColor.rgb * uAmbientColor.a;', + + ' float attenuation = 1.0 / ( uFalloff.x + (uFalloff.y*D) + (uFalloff.z*D*D) );', + ' vec3 intensity = ambient + diffuse * attenuation;', + ' vec3 finalColor = dc.rgb * intensity;', + + ' gl_FragColor = colorTransform(vec4(finalColor, dc.a), ${Shader.vColor}, ${Shader.uColorMultiplier}, ${Shader.uColorOffset});', + '}', + ]; + + public function new() { + super(); + } +} \ No newline at end of file diff --git a/features/display/Shaders/Source/shaders/RGBShiftShader.hx b/features/display/Shaders/Source/shaders/RGBShiftShader.hx new file mode 100644 index 0000000..dabd356 --- /dev/null +++ b/features/display/Shaders/Source/shaders/RGBShiftShader.hx @@ -0,0 +1,41 @@ +package shaders; + +import openfl.display.Shader; +import openfl.display.Shader.GLShaderPrecision; + +/** + * @author felixturner / http://airtight.cc/ + * + * RGB Shift Shader + * Shifts red and blue channels from center in opposite directions + * Ported from http://kriss.cx/tom/2009/05/rgb-shift/ + * by Tom Butterworth / http://kriss.cx/tom/ + * + * amount: shift distance (1 is width of input) + * angle: shift angle in radians + */ +class RGBShiftShader extends Shader { + + // https://github.com/mrdoob/three.js/blob/master/examples/js/shaders/RGBShiftShader.js + @fragment var code = [ + + 'uniform float amount;', + 'uniform float angle;', + + 'void main() {', + 'vec2 offset = amount * vec2( cos(angle), sin(angle));', + 'vec4 cr = texture2D(${Shader.uSampler}, ${Shader.vTexCoord} + offset);', + 'vec4 cga = texture2D(${Shader.uSampler}, ${Shader.vTexCoord});', + 'vec4 cb = texture2D(${Shader.uSampler}, ${Shader.vTexCoord} - offset);', + 'gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);', + '}' + ]; + + public function new() { + super(); + + //default values + amount = 0.005; + angle = 1.0; + } +} \ No newline at end of file diff --git a/features/display/Shaders/project.xml b/features/display/Shaders/project.xml new file mode 100644 index 0000000..fb750bf --- /dev/null +++ b/features/display/Shaders/project.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/features/display/Shaders/shaders.hxproj b/features/display/Shaders/shaders.hxproj new file mode 100644 index 0000000..ebb2a9b --- /dev/null +++ b/features/display/Shaders/shaders.hxproj @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "$(CompilerPath)/haxelib" run lime build "$(OutputFile)" $(TargetBuild) -$(BuildConfig) -Dfdb + + + + + + + + \ No newline at end of file