Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.82k stars 821 forks source link

DisplacementMapFilter don`t work with Starling.profile = "auto" on iOS devices #1009

Closed alevys closed 6 years ago

alevys commented 6 years ago

Hi! On the iPad AIR and iPhone 6 not working DisplacementMapFilter, if you select Starling.profile = "auto". If you select a profile Context3DProfile.BASELINE_CONSTRAINED, then everything works fine.

package
{

    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.MovieClip;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3DProfile;
    import flash.filesystem.File;

    import starling.core.Starling;
    import starling.display.Image;
    import starling.display.Sprite;
    import starling.events.EnterFrameEvent;
    import starling.events.Event;
    import starling.filters.DisplacementMapFilter;
    import starling.textures.Texture;
    import starling.utils.AssetManager;
    import starling.utils.StringUtil;

    public class MainTest extends MovieClip
    {
        private var _mapXOffset:Number = 0;
        private var _mapYOffset:Number = 0;
        private var _assetManager:AssetManager;
        private var _filter:DisplacementMapFilter;

        public function MainTest() {
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.stage.align = StageAlign.TOP_LEFT;
            this.stage.frameRate = 60;

            var _starling:Starling = new Starling(Sprite, stage, null, null, "auto", "auto");

            _starling.antiAliasing = 0;
            _starling.skipUnchangedFrames = true;
            _starling.addEventListener(Event.ROOT_CREATED, handler_rootCreated);
            _starling.start();
        }

        private function handler_rootCreated(event:Event):void {
            _assetManager = new AssetManager(Starling.contentScaleFactor);
            _assetManager.verbose = false;

            var appDir:File = File.applicationDirectory;
            _assetManager.enqueue(appDir.resolvePath(StringUtil.format("assets/landscape/landscape_atlas_x{0}.xml", Starling.contentScaleFactor)));
            _assetManager.enqueue(appDir.resolvePath(StringUtil.format("assets/landscape/landscape_atlas_x{0}.atf", Starling.contentScaleFactor)));
            _assetManager.loadQueue(onProgress);
        }

        private function onProgress(ratio:Number):void {
            if (ratio == 1) {
                initView();
            }
        }

        private function initView():void {
            var bgTexture:Texture = _assetManager.getTexture("landscape_1");
            var waterTexture:Texture = _assetManager.getTexture("landscape_1_water");

            var landscape:Image = new Image(bgTexture);
            Starling.current.stage.addChild(landscape);

            var water:Image = new Image(waterTexture);
            Starling.current.stage.addChild(water);

            var _noiseData:BitmapData = new BitmapData(256, 256, false);
            _noiseData.perlinNoise(10 * Starling.contentScaleFactor, 5 * Starling.contentScaleFactor, 4, 5, true, true, 0, true);
            var _displaceTexture:Texture = Texture.fromBitmapData(_noiseData, false, false, Starling.contentScaleFactor);

            _filter = new DisplacementMapFilter(_displaceTexture, BitmapDataChannel.BLUE, BitmapDataChannel.RED, -1, -7);
            _filter.mapRepeat = true;
            water.filter = _filter;

            water.addEventListener(EnterFrameEvent.ENTER_FRAME, handler_frame);
        }

        private function handler_frame(event:EnterFrameEvent):void {
            _mapXOffset += event.passedTime * 8;
            _mapYOffset += event.passedTime * 14;

            _filter.mapX = _mapXOffset;
            _filter.mapY = _mapYOffset;
        }
    }
}
PrimaryFeather commented 6 years ago

Thanks a lot for creating the issue — I'll look into it!

Quick question: was there also another iOS device model on which it worked? Or did it basically show up on all your iOS test devices?

(Because I just tried my old DisplacementMapFilter example on a 6S, on which it worked fine. I did not try on a iPad 6 / Air 1 yet, though, and I didn't yet try you code specifically.)

Thanks in advance!

alevys commented 6 years ago

Error appears on the iPhone 6, iPhone 7 and iPad AIR

PrimaryFeather commented 6 years ago

Got it!

The problem was that you had mapRepeat activated, but didn't use a POT-texture. That caused an error in the shader. It doesn't show up in `baselineConstrained', because in that profile, all textures are POT-textures.

I just added a workaround to the code. mapRepeat still doesn't work with this kind of texture, but the setting is now silently ignored if it's not supported.

To use mapRepeat, create your texture like this:

Texture.fromBitmapData(perlinData, false, false, 1, "bgra", true);

Note the final true parameter. That's called forcePotTexture.

alevys commented 6 years ago

Now everything works fine. Thank you very much!

PrimaryFeather commented 6 years ago

I'm happy to hear that! Cheers! :smile: