flutter_angle 0.3.0 copy "flutter_angle: ^0.3.0" to clipboard
flutter_angle: ^0.3.0 copied to clipboard

Flutters Almost Native Graphics Layer Engine is made by google to use OpenGL ES API calls to one of the hardware-supported APIs available for that platform.

example/lib/main.dart

import 'dart:async';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_angle/flutter_angle.dart';

void main() {
  runApp(ExampleTriangle01());
}


class ExampleTriangle01 extends StatefulWidget {
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<ExampleTriangle01> {
  int? fboId;
  double dpr = 1.0;
  bool ready = false;
  late double width;
  late double height;

  late final glProgram;

  Size? screenSize;
  late final RenderingContext _gl;

  late FlutterAngleTexture sourceTexture;
  FlutterAngle angle = FlutterAngle();
  Framebuffer? defaultFramebuffer;
  WebGLTexture? defaultFramebufferTexture;

  int n = 0;

  int t = DateTime.now().millisecondsSinceEpoch;
  Float32Array? vertices; 
  @override
  void initState() {
    super.initState();
    print(" init state..... ");
  }

  @override
  void dispose(){
    vertices?.dispose();
    vertices = null;
    angle.dispose([sourceTexture]);
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    width = screenSize!.width;
    height = width;

    await angle.init(true);
    setState(() {});

    // web need wait dom ok!!!
    Future.delayed(Duration(milliseconds: 100), () {
      setup();
    });
  }

  void setup() async {
    sourceTexture = await angle.createTexture(      
      AngleOptions(
        width: width.toInt(), 
        height: height.toInt(), 
        dpr: dpr,
      )
    );
    _gl = sourceTexture.getContext();
    ready = true;

    setState(() {});

    prepare();
    animate();
  }

  void initSize(BuildContext context) {
    if (screenSize != null) {
      return;
    }

    final mq = MediaQuery.of(context);

    screenSize = mq.size;
    dpr = mq.devicePixelRatio;

    print(" screenSize: ${screenSize} dpr: ${dpr} ");
    initPlatformState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            initSize(context);
            return SingleChildScrollView(child: _build(context));
          },
        ),
      ),
    );
  }

  Widget _build(BuildContext context) {
    return Column(
      children: [
        Container(
            width: width,
            height: width,
            color: Colors.black,
            child: Builder(builder: (BuildContext context) {
              if (kIsWeb) {
                return ready
                    ? HtmlElementView(
                        viewType: sourceTexture.textureId.toString())
                    : Container();
              } else {
                return ready
                    ? Texture(textureId: sourceTexture.textureId)
                    : Container();
              }
            })),
      ],
    );
  }

  void animate() {
    render();

    Future.delayed(Duration(milliseconds: 40), () {
      animate();
    });
  }

  Future<void> render() async{
    int _current = DateTime.now().millisecondsSinceEpoch;
    double _blue = sin((_current - t) / 500);
    double _green = cos((_current - t) / 500);
    double _red = tan((_current - t) / 500);

    _gl.viewport(0, 0, width.toInt(), height.toInt());
    _gl.clearColor(_red, _green, _blue, 1.0);
    _gl.clear(WebGL.COLOR_BUFFER_BIT);
    
    _gl.useProgram(glProgram);
    _gl.drawArrays(WebGL.TRIANGLES, 0, n);
    _gl.gl.glFinish();

    await angle.updateTexture(sourceTexture,defaultFramebufferTexture);
  }

  void prepare() {
    var vs = """
      #version 300 es
      #define attribute in
      #define varying out
      attribute vec3 a_Position;
      // layout (location = 0) in vec3 a_Position;
      void main() {
          gl_Position = vec4(a_Position, 1.0);
      }
    """;

    var fs = """
      #version 300 es
      out highp vec4 pc_fragColor;
      #define gl_FragColor pc_fragColor

      void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    """;

    if (!initShaders(_gl, vs, fs)) {
      print('Failed to intialize shaders.');
      return;
    }

    // Write the positions of vertices to a vertex shader
    n = initVertexBuffers(_gl);
    if (n < 0) {
      print('Failed to set the positions of the vertices');
      return;
    }
  }

  int initVertexBuffers(RenderingContext gl) {
    // Vertices
    final dim = 3;
    vertices = Float32Array.fromList([
      -0.5, -0.5, 0, // Vertice #2
      0.5, -0.5, 0, // Vertice #3
      0, 0.5, 0, // Vertice #1
    ]);
    
    // Create a buffer object
    dynamic vertexBuffer = gl.createBuffer();
    gl.bindBuffer(WebGL.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(WebGL.ARRAY_BUFFER, vertices!, WebGL.STATIC_DRAW);

    // Assign the vertices in buffer object to a_Position variable
    final a_Position = gl.getAttribLocation(glProgram, 'a_Position').id;
    if (a_Position < 0) {
      print('Failed to get the storage location of a_Position');
      return -1;
    }

    gl.vertexAttribPointer(a_Position, dim, WebGL.FLOAT, false, Float32List.bytesPerElement * 3, 0);
    gl.enableVertexAttribArray(a_Position);

    // Return number of vertices
    return vertices!.length ~/ dim;
  }

  bool initShaders(RenderingContext gl, String vs_source, String fs_source) {
    // Compile shaders
    final vertexShader = makeShader(gl, vs_source, WebGL.VERTEX_SHADER);
    final fragmentShader = makeShader(gl, fs_source, WebGL.FRAGMENT_SHADER);

    // Create program
    glProgram = gl.createProgram();

    // Attach and link shaders to the program
    gl.attachShader(glProgram, vertexShader);
    gl.attachShader(glProgram, fragmentShader);
    gl.linkProgram(glProgram);
    final _res = gl.getProgramParameter(glProgram, WebGL.LINK_STATUS);
    print(" initShaders LINK_STATUS _res: ${_res} ");
    if (_res == false || _res == 0) {
      print("Unable to initialize the shader program");
      return false;
    }

    // Use program
    gl.useProgram(glProgram);

    return true;
  }

  dynamic makeShader(RenderingContext gl, String src, int type) {
    dynamic shader = gl.createShader(type);
    gl.shaderSource(shader, src);
    gl.compileShader(shader);
    gl.shaderSource(shader, WebGL.COMPILE_STATUS.toString());
    // if (_res == 0 || _res == false) {
    //   print("Error compiling shader: ${gl.getShaderInfoLog(shader)}");
    //   return;
    // }
    return shader;
  }
}
16
likes
0
points
3.04k
downloads

Publisher

unverified uploader

Weekly Downloads

Flutters Almost Native Graphics Layer Engine is made by google to use OpenGL ES API calls to one of the hardware-supported APIs available for that platform.

Homepage
Repository (GitHub)
View/report issues

Topics

#opengl #angle #glsl

License

unknown (license)

Dependencies

dylib, ffi, flutter, logger, web

More

Packages that depend on flutter_angle

Packages that implement flutter_angle