Gamua / Starling-Framework

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

Starling Texture.fromCamera() flickering and a part of the picture is missing on Windows #1094

Closed pol2095 closed 2 years ago

pol2095 commented 2 years ago

Problem Description

Starling Texture.fromCamera() flickering and a part of the picture is missing on Windows

Steps to Reproduce

package com
{
    import flash.media.Camera;

    import starling.display.Image;
    import starling.display.Sprite;
    import starling.events.Event;
    import starling.textures.Texture;

    public class MyCamera extends Sprite
    { 
        private var texture:Texture;
        private var image:Image;
        private var camera:Camera;

        public function MyCamera()
        {           
            addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            camera = Camera.getCamera();
            texture = Texture.fromCamera(camera, 1, function():void
            {
                image = new Image(texture);
                addChild(image);
            });
        }
    }
}

Known Workarounds

no workaround

PrimaryFeather commented 2 years ago

I wish I could help, but this is a case where Starling simply uses the texture that's provided by AIR and wraps it in a Starling texture – so if that fails, the problem is very probably happening on a lower level. Thus, opening up the issue in the AIRSDK issue tracker (which you already did) is your best chance to get help. I'm crossing my fingers that you get a response soon!

pol2095 commented 2 years ago

It's strange this code work on Windows :

package
{
    import com.adobe.utils.AGALMiniAssembler;

    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProfile;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DRenderMode;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.VideoTexture;
    import flash.events.Event;
    import flash.events.VideoTextureEvent;
    import flash.geom.Matrix3D;
    import flash.media.Camera;
    import flash.utils.ByteArray;

    public final class Main extends Sprite
    {
        private var stage3D:Stage3D;
        private var context3D:Context3D;
        //
        private var program:Program3D;
        private var indexBuffer:IndexBuffer3D;
        //
        private var videoTexture:VideoTexture;

        /**
         * Constructor.
         */
        public function Main():void
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            stage3D = stage.stage3Ds[0];
            stage3D.addEventListener(Event.CONTEXT3D_CREATE, contextCreateHandler);
            stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.STANDARD_CONSTRAINED);
        }

        private function contextCreateHandler(e:Event):void
        {
            context3D = stage3D.context3D;
            //context3D.enableErrorChecking = true;
            context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, true);

            // create
            createShaders();
            setConstant();
            setBuffer();

            // camera
            var camera:Camera = Camera.getCamera();
            camera.setMode(stage.stageWidth, stage.stageHeight, 60);
            videoTexture = context3D.createVideoTexture();
            videoTexture.attachCamera(camera);
            videoTexture.addEventListener(Event.TEXTURE_READY, renderFrame);
            videoTexture.addEventListener(VideoTextureEvent.RENDER_STATE, videoTexture_renderStateHandler);
        }

        private function renderFrame(e:Event):void
        {
            trace("Render on stage3D with VideoTexture Object.");
            context3D.clear(0, 0, 0, 1);
            context3D.drawTriangles(indexBuffer);
            context3D.present();
        }

        private function videoTexture_renderStateHandler(event:VideoTextureEvent):void
        {
            context3D.setTextureAt(0, videoTexture);
            context3D.setProgram(program);
        }

        /**
         * create Stage3D shader programs.
         */
        private function createShaders():void
        {
            // create shaders
            var agalAssembler:AGALMiniAssembler = new AGALMiniAssembler();

            // vertex
            var vertexShader:ByteArray = agalAssembler.assemble(Context3DProgramType.VERTEX, "m44 op, va0, vc0 \n" + "mov v0, va1\n");

            // fragment
            var fragmentShader:ByteArray;

            var code:Array;

            // normal
            code = [
                "mov ft0 v0",
                "tex ft0, ft0, fs0<2d,clamp,linear>",
                "mov oc, ft0",
            ];
            fragmentShader = agalAssembler.assemble(Context3DProgramType.FRAGMENT, code.join("\n"));
            program = context3D.createProgram();
            program.upload(vertexShader, fragmentShader);
        }

        /**
         * set constants for shaders.
         */
        private function setConstant():void
        {
            var mtx:Matrix3D = new Matrix3D();
            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mtx, false);
        }

        /**
         * create and set buffers for shaders.
         */
        private function setBuffer():void
        {
            // vertex buffer
            var vertexBuffer:VertexBuffer3D = context3D.createVertexBuffer(4, 4);
            vertexBuffer.uploadFromVector(Vector.<Number>([-1, -1, 0, 1, -1, 1, 0, 0, 1, -1, 1, 1, 1, 1, 1, 0]), 0, 4);

            // index buffer
            indexBuffer = context3D.createIndexBuffer(6);
            indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 1, 2, 3]), 0, 6);

            context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);
            context3D.setVertexBufferAt(1, vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
        }
    }
}
PrimaryFeather commented 2 years ago

Thanks for taking the time to creating that minimal sample! I found the reason for the problem and describe it here and here.

I'll reopen this issue – I'd prefer for Harman to fix this at the source, but that's not decided yet. If need be, I will add the workaround directly to Starling.

pol2095 commented 2 years ago

Fixed by Harman.