Skip to content

Instantly share code, notes, and snippets.

@ykmnkmi
Last active Sep 25, 2020
Embed
What would you like to do?
gl vertex math dart:ui
import 'dart:async';
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui';
import 'package:vector_math/vector_math.dart';
typedef Renderer = void Function(Canvas canvas, Rect paintBounds);
Renderer render;
const black = const Color(0xFF000000);
const red = const Color(0xFFFF0000);
const white = const Color(0xFFFFFFFF);
void main() {
final canvasHalf = Size(480.0, 320.0).center(Offset.zero);
final cameraPosition = Vector3(0.0, 0.0, 300.0);
final cameraFocusPosition = Vector3(0.0, 0.0, 0.0);
final upDirection = Vector3(0.0, 1.0, 0.0);
List<Offset> positions;
final view = Matrix4.identity();
final projection = Matrix4.identity();
final position = Vector3.zero();
var rotation = Quaternion.euler(radians(0.0), radians(0.0), radians(0.0));
final scale = Vector3.all(1.0);
final vertexPoints = <Vector3>[
position + Vector3(-100.0, 0, -100.0),
position + Vector3(100.0, 0, -100.0),
position + Vector3(100.0, 0, 100.0),
position + Vector3(-100.0, 0, 100.0),
];
final colors = const <Color>[red, red, red, red];
final length = vertexPoints.length;
positions = List<Offset>(length);
final paint = Paint();
paint.color = red;
render = (Canvas canvas, Rect paintBounds) {
final size = paintBounds.size;
final mid = size.center(Offset.zero);
setViewMatrix(view, cameraPosition, cameraFocusPosition, upDirection);
final fov = 70.0;
final near = 1.0;
final far = 1000.0;
final zoom = 1.0;
final aspectRatio = size.aspectRatio;
final top = near * math.tan(radians(fov) / 2.0) / zoom;
final bottom = -top;
final right = top * aspectRatio;
final left = -right;
// setFrustumMatrix(projection, left, right, bottom, top, near, far);
setPerspectiveMatrix(projection, fov, aspectRatio, near, far);
final model = Matrix4.compose(position, rotation, scale);
final mvp = projection * view * model;
for (int i = 0; i < length; i++) {
final position3 = vertexPoints[i];
final position4 = Vector4(position3.x, position3.y, position3.z, 1.0);
position4.applyMatrix4(mvp);
final dx = position4.x / position4.w;
final dy = -position4.y / position4.w;
positions[i] = mid + canvasHalf.scale(dx, dy);
}
canvas.drawColor(white, BlendMode.srcOver);
// vertex
final vertices = Vertices(VertexMode.triangleFan, positions, colors: colors);
canvas.drawVertices(vertices, BlendMode.src, paint);
};
window.onBeginFrame = beginFrame;
window.scheduleFrame();
var waiting = true;
Timer.periodic(Duration(milliseconds: 1000 ~/ 60), (Timer timer) {
if (waiting) {
waiting = false;
rotation = Quaternion.euler(radians(timer.tick.toDouble()), radians(0.0), radians(0.0));
cameraPosition.y = math.sin(radians(timer.tick.toDouble() * 0.8)) * 200.0;
window.scheduleFrame();
waiting = true;
}
});
}
void beginFrame(Duration timeStamp) {
final paintBounds = Offset.zero & (window.physicalSize / window.devicePixelRatio);
final picture = paint(paintBounds);
final scene = composite(picture, paintBounds);
window.render(scene);
}
Scene composite(Picture picture, Rect paintBounds) {
final devicePixelRatio = window.devicePixelRatio;
final deviceTransform = Float64List(16)
..[0] = devicePixelRatio
..[5] = devicePixelRatio
..[10] = 1.0
..[15] = 1.0;
final sceneBuilder = SceneBuilder()
..pushTransform(deviceTransform)
..addPicture(Offset.zero, picture)
..pop();
return sceneBuilder.build();
}
Picture paint(Rect paintBounds) {
final recorder = PictureRecorder();
final canvas = Canvas(recorder, paintBounds);
render(canvas, paintBounds);
return recorder.endRecording();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment