Skip to content

Cobe Problem #46

@taipower

Description

@taipower

My Code
`
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_gl/flutter_gl.dart';
import 'package:flutter_gl/openGL/opengl/opengl_es_bindings/opengl_es_bindings.dart';
import 'package:vector_math/vector_math.dart' as math;

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

class _MyAppState extends State {
late FlutterGlPlugin flutterGlPlugin;

int? fboId;
num dpr = 1.0;
late double width;
late double height;

ui.Size? screenSize;

dynamic glProgram;
dynamic _vao;
dynamic _ebo;
dynamic _texture1;
dynamic _texture2;

dynamic sourceTexture;

dynamic defaultFramebuffer;
dynamic defaultFramebufferTexture;

int n = 0;

int t = DateTime.now().millisecondsSinceEpoch;

@OverRide
void initState() {
super.initState();

print(" init state..... ");

}

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

flutterGlPlugin = FlutterGlPlugin();

Map<String, dynamic> _options = {
  "antialias": true,
  "alpha": false,
  "width": width.toInt(),
  "height": height.toInt(),
  "dpr": dpr
};

await flutterGlPlugin.initialize(options: _options);

print(" flutterGlPlugin: textureid: ${flutterGlPlugin.textureId} ");

setState(() {});

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

}

setup() async {
// web no need use fbo
if (!kIsWeb) {
await flutterGlPlugin.prepareContext();

  setupDefaultFBO();
  sourceTexture = defaultFramebufferTexture;
}

prepare();

}

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(
appBar: AppBar(
title: const Text('Example app'),
),
body: Builder(
builder: (BuildContext context) {
initSize(context);
return SingleChildScrollView(child: _build(context));
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
clickRender();
},
child: Text("Render"),
),
),
);
}

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

setupDefaultFBO() {
final _gl = flutterGlPlugin.gl;
int glWidth = (width * dpr).toInt();
int glHeight = (height * dpr).toInt();

print("glWidth: ${glWidth} glHeight: ${glHeight} ");

defaultFramebuffer = _gl.createFramebuffer();
defaultFramebufferTexture = _gl.createTexture();
_gl.activeTexture(_gl.TEXTURE0);

_gl.bindTexture(_gl.TEXTURE_2D, defaultFramebufferTexture);
_gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA, glWidth, glHeight, 0, _gl.RGBA,
    _gl.UNSIGNED_BYTE, null);
_gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR);
_gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR);

_gl.bindFramebuffer(_gl.FRAMEBUFFER, defaultFramebuffer);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0,
    _gl.TEXTURE_2D, defaultFramebufferTexture, 0);

}

clickRender() {
print(" click render ... ");
render();
}

render() {
final _gl = flutterGlPlugin.gl;

_gl.viewport(0, 0, (width * dpr).toInt(), (height * dpr).toInt());

// Clear canvas
_gl.clearColor(0.2, 0.3, 0.3, 1.0);
_gl.clear(_gl.COLOR_BUFFER_BIT|_gl.DEPTH_BUFFER_BIT);

_gl.drawArrays(_gl.TRIANGLES, 0, 36);

print(" render n: $n ");

_gl.finish();

if (!kIsWeb) {
  flutterGlPlugin.updateTexture(sourceTexture);
}

}

prepare() {
final _gl = flutterGlPlugin.gl;

String _version = "300 es";

if(!kIsWeb) {
  if (Platform.isMacOS || Platform.isWindows) {
    _version = "150";
  }
}

var vs = """#version ${_version}

precision mediump float; // add a precision qualifier

layout (location = 0) in vec3 a_Position;
layout (location = 1) in vec2 a_TexCoord;

out vec2 TexCoord;

uniform mat4 mvp;

void main() {
gl_Position = mvp * vec4(a_Position, 1.0);
TexCoord = vec2(a_TexCoord.x,a_TexCoord.y);
}
""";

var fs = """#version ${_version}

precision mediump float;

out vec4 pc_fragColor;
#define gl_FragColor pc_fragColor

in vec2 TexCoord;

uniform sampler2D texture1;
uniform sampler2D texture2;

void main() {
gl_FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
""";

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;
}

}

initVertexBuffers(gl) {
// Vertices
var dim = 3;

gl.enable(GL_DEPTH_TEST);

var vertices = Float32Array.fromList([
  // position       // texture coords
  -0.5, -0.5, -0.5,  0.0, 0.0,
  0.5, -0.5, -0.5,  1.0, 0.0,
  0.5,  0.5, -0.5,  1.0, 1.0,
  0.5,  0.5, -0.5,  1.0, 1.0,
  -0.5,  0.5, -0.5,  0.0, 1.0,
  -0.5, -0.5, -0.5,  0.0, 0.0,
  -0.5, -0.5,  0.5,  0.0, 0.0,
  0.5, -0.5,  0.5,  1.0, 0.0,
  0.5,  0.5,  0.5,  1.0, 1.0,
  0.5,  0.5,  0.5,  1.0, 1.0,
  -0.5,  0.5,  0.5,  0.0, 1.0,
  -0.5, -0.5,  0.5,  0.0, 0.0,
  -0.5,  0.5,  0.5,  1.0, 0.0,
  -0.5,  0.5, -0.5,  1.0, 1.0,
  -0.5, -0.5, -0.5,  0.0, 1.0,
  -0.5, -0.5, -0.5,  0.0, 1.0,
  -0.5, -0.5,  0.5,  0.0, 0.0,
  -0.5,  0.5,  0.5,  1.0, 0.0,
  0.5,  0.5,  0.5,  1.0, 0.0,
  0.5,  0.5, -0.5,  1.0, 1.0,
  0.5, -0.5, -0.5,  0.0, 1.0,
  0.5, -0.5, -0.5,  0.0, 1.0,
  0.5, -0.5,  0.5,  0.0, 0.0,
  0.5,  0.5,  0.5,  1.0, 0.0,
  -0.5, -0.5, -0.5,  0.0, 1.0,
  0.5, -0.5, -0.5,  1.0, 1.0,
  0.5, -0.5,  0.5,  1.0, 0.0,
  0.5, -0.5,  0.5,  1.0, 0.0,
  -0.5, -0.5,  0.5,  0.0, 0.0,
  -0.5, -0.5, -0.5,  0.0, 1.0,
  -0.5,  0.5, -0.5,  0.0, 1.0,
  0.5,  0.5, -0.5,  1.0, 1.0,
  0.5,  0.5,  0.5,  1.0, 0.0,
  0.5,  0.5,  0.5,  1.0, 0.0,
  -0.5,  0.5,  0.5,  0.0, 0.0,
  -0.5,  0.5, -0.5,  0.0, 1.0,
]);

_vao = gl.createVertexArray();
gl.bindVertexArray(_vao);

// Create a buffer object
var vertexBuffer = gl.createBuffer();
if (vertexBuffer == null) {
  print('Failed to create the buffer object');
  return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

if(kIsWeb) {
  gl.bufferData(gl.ARRAY_BUFFER, vertices.length, vertices, gl.STATIC_DRAW);
} else {
  gl.bufferData(gl.ARRAY_BUFFER, vertices.lengthInBytes, vertices, gl.STATIC_DRAW);
}

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

var c_Position = gl.getAttribLocation(glProgram, 'a_TexCoord');
if(c_Position < 0){
  print('Failed to get the storage location of a_TexCoord');
  return -1;
}

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

gl.vertexAttribPointer(
    c_Position, 2, gl.FLOAT, false, Float32List.bytesPerElement * 5, Float32List.bytesPerElement * 3);
gl.enableVertexAttribArray(c_Position);

_texture1 = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(GL_TEXTURE_2D, _texture1);
// set the texture wrapping parameters
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl.uniform1i(gl.getUniformLocation(glProgram,'texture1'),0);

// load image, create texture and generate mipmaps
loadImage('assets/images/flutter540.jpg').then((bytes) {
  gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 540, 540, 0, GL_RGBA, GL_UNSIGNED_BYTE, Uint8Array.from(bytes.toList()));
  gl.generateMipmap(GL_TEXTURE_2D);

  _texture2 = gl.createTexture();
  gl.activeTexture(gl.TEXTURE1);
  gl.bindTexture(GL_TEXTURE_2D, _texture2);
  // set the texture wrapping parameters
  gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  // set texture filtering parameters
  gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  gl.uniform1i(gl.getUniformLocation(glProgram,'texture2'),1);

  // load image, create texture and generate mipmaps
  loadImage('assets/images/awesomeface.png').then((bytes) {
    gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 476, 476, 0, GL_RGBA, GL_UNSIGNED_BYTE, Uint8Array.from(bytes.toList()));
    gl.generateMipmap(GL_TEXTURE_2D);
  });
});

int _current = DateTime.now().millisecondsSinceEpoch;
math.Vector3 axis = math.Vector3(0.5, 1.0, 0.0);
final model = math.Matrix4.identity()..rotate(axis, _current.toDouble());
final view = math.Matrix4.identity()..translate(math.Vector3(0.0,0.0,-3.0));
math.Matrix4 projection = math.makePerspectiveMatrix(45.0,1.0, 0.1, 100.0);
math.Matrix4 MVP = projection * view * model;

var mvpPosition = gl.getUniformLocation(glProgram, 'mvp');
if(mvpPosition < 0){
  print('Failed to get the storage location of MVP');
  return -1;
}
gl.uniformMatrix4fv(mvpPosition, true, MVP.storage);

// Return number of vertices
return (vertices.length / dim).toInt();

}

initShaders(gl, vs_source, fs_source) {
// Compile shaders
var vertexShader = makeShader(gl, vs_source, gl.VERTEX_SHADER);
var fragmentShader = makeShader(gl, fs_source, gl.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);
var _res = gl.getProgramParameter(glProgram, gl.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;

}

makeShader(gl, src, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
var _res = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (_res == 0 || _res == false) {
print("Error compiling shader: ${gl.getShaderInfoLog(shader)}");
return;
}
return shader;
}

Future loadImage(String imgPath) async{
final ByteData imageData = await rootBundle.load(imgPath);
final Uint8List bytes = imageData.buffer.asUint8List();

// Decode the image
final ui.Codec codec = await ui.instantiateImageCodec(bytes);
final ui.Image image = (await codec.getNextFrame()).image;

// Flip the image vertically
final Uint8List pixelData = await _flipImageVertically(image);

return pixelData;

}

Future _flipImageVertically(ui.Image image) async {
final int width = image.width;
final int height = image.height;

final ByteData? byteData = await image.toByteData();
final Uint8List pixels = Uint8List.fromList(byteData?.buffer.asUint8List() ?? []);

for (int y = 0; y < height ~/ 2; y++) {
  final int topOffset = y * width * 4;
  final int bottomOffset = (height - y - 1) * width * 4;
  for (int x = 0; x < width; x++) {
    final int topIndex = topOffset + x * 4;
    final int bottomIndex = bottomOffset + x * 4;
    final int r = pixels[topIndex];
    final int g = pixels[topIndex + 1];
    final int b = pixels[topIndex + 2];
    final int a = pixels[topIndex + 3];
    pixels[topIndex] = pixels[bottomIndex];
    pixels[topIndex + 1] = pixels[bottomIndex + 1];
    pixels[topIndex + 2] = pixels[bottomIndex + 2];
    pixels[topIndex + 3] = pixels[bottomIndex + 3];
    pixels[bottomIndex] = r;
    pixels[bottomIndex + 1] = g;
    pixels[bottomIndex + 2] = b;
    pixels[bottomIndex + 3] = a;
  }
}

return pixels;

}
}
`
When I render on Android mobile. It's not showing as a 3D cube, but as a 2D square.
Screenshot_20230330_143643
My image
flutter540

awesomeface
Can anyone help guide me?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions