flutter_gles2 0.0.1-alpha.3
flutter_gles2: ^0.0.1-alpha.3 copied to clipboard
A cross-platform OpenGL ES 2.0 widget for Flutter that provides access to the full OpenGL ES API.
example/lib/main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gles2/flutter_gles2.dart';
void main() {
runApp(const MyApp());
}
const String vertShaderSource = """
#version 100
attribute vec3 vertPos;
attribute vec2 uvIn;
uniform mat4 mvp;
varying vec2 uv;
void main() {
uv = uvIn;
gl_Position = mvp * vec4(vertPos, 1.0);
}
""";
const fragShaderSource = """
#version 100
precision mediump float;
uniform sampler2D texUnit;
varying vec2 uv;
void main() {
gl_FragColor = texture2D(texUnit, uv);
}
""";
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
// title of the application
title: 'OpenGL ES Demo',
// theme of the widget
theme: ThemeData(
primarySwatch: Colors.lightGreen,
),
// Inner UI of the application
home: MyHomePage(title: 'Home page'),
);
}
}
const double z = 0.0;
final vertices = GLBuffer.asFloatArray(<double>[
-1.0, -1.0, 1.0, 0.0, 0.0, // v0
1.0, -1.0, 1.0, 0.33, 0.0, // v1
-1.0, 1.0, 1.0, 0.0, 0.5, // v2
1.0, 1.0, 1.0, 0.33, 0.5, // v3
1.0, -1.0, 1.0, 0.0, 0.5, // v4
1.0, -1.0, -1.0, 0.33, 0.5, // v5
1.0, 1.0, 1.0, 0.0, 1.0, // v6
1.0, 1.0, -1.0, 0.33, 1.0, // v7
1.0, -1.0, -1.0, 0.66, 0.5, // v8
-1.0, -1.0, -1.0, 1.0, 0.5, // v9
1.0, 1.0, -1.0, 0.66, 1.0, // v10
-1.0, 1.0, -1.0, 1.0, 1.0, // v11
-1.0, -1.0, -1.0, 0.66, 0.0, // v12
-1.0, -1.0, 1.0, 1.0, 0.0, // v13
-1.0, 1.0, -1.0, 0.66, 0.5, // v14
-1.0, 1.0, 1.0, 1.0, 0.5, // v15
-1.0, -1.0, -1.0, 0.33, 0.0, // v16
1.0, -1.0, -1.0, 0.66, 0.0, // v17
-1.0, -1.0, 1.0, 0.33, 0.5, // v18
1.0, -1.0, 1.0, 0.66, 0.5, // v19
-1.0, 1.0, 1.0, 0.33, 0.5, // v20
1.0, 1.0, 1.0, 0.66, 0.5, // v21
-1.0, 1.0, -1.0, 0.33, 1.0, // v22
1.0, 1.0, -1.0, 0.66, 1.0, // v23
]);
final indices = GLBuffer.asShortArray([
0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0, v1, v2, v3)
4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4, v5, v6, v7)
8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8, v9, v10, v11)
12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15)
16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19)
20, 20, 21, 22, 23 // Face 5 - triangle strip (v20, v21, v22, v23)
]);
Matrix4 perspective(double fov, double aspect, double near, double far) {
final Matrix4 result = Matrix4.identity();
final double tanHalfFovy = tan(fov / 2.0);
result[0] = 1.0 / (aspect * tanHalfFovy);
result[5] = 1.0 / (tanHalfFovy);
result[10] = -(far + near) / (far - near);
result[11] = -1.0;
result[14] = -(2.0 * far * near) / (far - near);
result[15] = 0.0;
return result;
}
final projection = perspective(1.04, 640.0 / 480.0, 0.1, 100.0);
final view = Matrix4.identity()..translate(0.0, 0.0, -5.0);
/* This class is similar to MyApp instead it
returns Scaffold Widget */
class MyHomePage extends StatelessWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
int _program = 0;
int _mvp = 0;
int _sampler = 0;
Matrix4 model = Matrix4.identity();
GLuint texId = 0;
void _checkShader(GLuint shaderId) {
final compileSucceeded = <int>[];
glGetShaderiv(shaderId, GL_COMPILE_STATUS, compileSucceeded);
if (compileSucceeded.first == 0) {
final logLength = <int>[];
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, logLength);
final String log = glGetShaderInfoLog(
shaderId,
logLength.first,
);
debugPrint(log);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
// Sets the content to the
// center of the application page
body: Center(
// Sets the content of the Application
child: SizedBox(
width: 640,
height: 480,
child: OpenGLESWidget(
onInit: () async {
debugPrint("Init called");
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, [vertShaderSource]);
glCompileShader(vertShader);
_checkShader(vertShader);
assert(glGetError() == GL_NO_ERROR);
int fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, [fragShaderSource]);
glCompileShader(fragShader);
_checkShader(fragShader);
assert(glGetError() == GL_NO_ERROR);
_program = glCreateProgram();
glAttachShader(_program, vertShader);
glAttachShader(_program, fragShader);
glBindAttribLocation(_program, 0, "vertPos");
glBindAttribLocation(_program, 1, "uvIn");
glLinkProgram(_program);
assert(glGetError() == GL_NO_ERROR);
_mvp = glGetUniformLocation(_program, "mvp");
_sampler = glGetUniformLocation(_program, "texUnit");
final linked = <int>[];
glGetProgramiv(_program, GL_LINK_STATUS, linked);
assert(linked.first > 0);
glUseProgram(_program);
List<GLuint> texIds = [];
glGenTextures(1, texIds);
texId = texIds.first;
glBindTexture(GL_TEXTURE_2D, texId);
ImageMetaData meta = ImageMetaData();
final image = GLBuffer.fromImageByteData(
await rootBundle.load("assets/textures/crate.png"), meta);
assert(glGetError() == GL_NO_ERROR);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
meta.width,
meta.height,
0,
meta.format,
meta.type,
image,
);
int e = glGetError();
assert(e == GL_NO_ERROR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
assert(glGetError() == GL_NO_ERROR);
},
onResize: (w, h) {
glViewport(0, 0, w, h);
assert(glGetError() == GL_NO_ERROR);
},
onRender: () {
glViewport(0, 0, 640, 480);
glClearColor(1.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(_program);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
(5 * 4), // xyzuv
vertices,
);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
(5 * 4), // xyzuv
vertices.pointerOffset(3 * 4),
);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
model.multiply(Matrix4.rotationY(0.05)
.multiplied(Matrix4.rotationX(0.05)));
final modelview = view.multiplied(model);
final matrix = GLBuffer.asFloatArray(
projection.multiplied(modelview).storage.toList(),
);
glUniformMatrix4fv(_mvp, 1, GL_FALSE, matrix);
glUniform1i(_sampler, 0);
glBindTexture(GL_TEXTURE_2D, texId);
glDrawElements(
GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, indices);
int err = glGetError();
assert(err == GL_NO_ERROR);
},
))),
);
}
}