Flutter高性能图形渲染插件flutter_gpu_shaders的使用
Flutter高性能图形渲染插件flutter_gpu_shaders的使用
flutter_gpu_shaders
是一个用于Flutter GPU着色器捆绑包/库的构建工具。通过这个插件,你可以使用原生资产构建钩子来导入Flutter GPU着色器资产。下面是一个完整的示例,展示了如何使用 flutter_gpu_shaders
插件进行高性能图形渲染。
功能
- 使用原生资产构建钩子导入Flutter GPU着色器资产。
开始使用
1. 启用实验性功能
该插件需要启用实验性的“原生资产”功能。你可以通过以下命令启用它:
flutter config --enable-native-assets
2. 添加着色器文件
将一些Flutter GPU着色器文件添加到你的项目中。例如,我们假设存在两个着色器文件:shaders/my_cool_shader.vert
和 shaders/my_cool_shader.frag
。
3. 创建着色器捆绑包清单文件
在项目中创建一个着色器捆绑包清单文件,文件名必须以 .shaderbundle.json
结尾。例如,我们将以下内容保存为 my_cool_bundle.shaderbundle.json
:
{
"CoolVertex": {
"type": "vertex",
"file": "shaders/my_cool_shader.vert"
},
"CoolFragment": {
"type": "fragment",
"file": "shaders/my_cool_shader.frag"
}
}
4. 定义构建钩子
接下来,在项目中定义一个构建钩子,使用 buildShaderBundleJson
构建着色器捆绑包。构建钩子必须命名为 hook/build.dart
,当启用了“原生资产”功能时,Flutter会自动调用此脚本:
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:flutter_gpu_shaders/build.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
await buildShaderBundleJson(
buildConfig: config,
buildOutput: output,
manifestFileName: 'my_cool_bundle.shaderbundle.json');
});
}
5. 更新 pubspec.yaml
在项目的 pubspec.yaml
文件中,添加一个资产导入规则,以打包构建的着色器捆绑包(一旦“原生资产”支持 DataAsset
,这将在未来的Flutter版本中变得不再必要):
flutter:
assets:
- build/shaderbundles/*.shaderbundle.json
6. 导入并使用着色器库
现在你可以在项目中使用 gpu.ShaderLibrary.fromAsset
导入构建的着色器捆绑包作为库。例如:
import 'package:flutter_gpu/gpu.dart' as gpu;
final String _kBaseShaderBundlePath =
'packages/my_project/build/shaderbundles/my_cool_bundle.shaderbundle';
gpu.ShaderLibrary? _baseShaderLibrary = null;
gpu.ShaderLibrary get baseShaderLibrary {
if (_baseShaderLibrary != null) {
return _baseShaderLibrary!;
}
_baseShaderLibrary = gpu.ShaderLibrary.fromAsset(_kBaseShaderBundlePath);
if (_baseShaderLibrary != null) {
return _baseShaderLibrary!;
}
throw Exception("Failed to load base shader bundle! ($_kBaseShaderBundlePath)");
}
完整示例代码
以下是一个完整的示例项目,展示了如何使用 flutter_gpu_shaders
插件进行高性能图形渲染。
项目结构
my_project/
├── lib/
│ └── main.dart
├── shaders/
│ ├── my_cool_shader.vert
│ └── my_cool_shader.frag
├── hook/
│ └── build.dart
├── build/
│ └── shaderbundles/
│ └── my_cool_bundle.shaderbundle.json
└── pubspec.yaml
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_gpu/gpu.dart' as gpu;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('GPU Shaders Example')),
body: Center(
child: ShaderWidget(),
),
),
);
}
}
class ShaderWidget extends StatefulWidget {
@override
_ShaderWidgetState createState() => _ShaderWidgetState();
}
class _ShaderWidgetState extends State<ShaderWidget> {
final String _kBaseShaderBundlePath =
'packages/my_project/build/shaderbundles/my_cool_bundle.shaderbundle';
gpu.ShaderLibrary? _baseShaderLibrary;
@override
void initState() {
super.initState();
_loadShaderLibrary();
}
Future<void> _loadShaderLibrary() async {
try {
_baseShaderLibrary = await gpu.ShaderLibrary.fromAsset(_kBaseShaderBundlePath);
setState(() {});
} catch (e) {
print('Failed to load shader library: $e');
}
}
@override
Widget build(BuildContext context) {
if (_baseShaderLibrary == null) {
return CircularProgressIndicator();
}
return CustomPaint(
painter: ShaderPainter(_baseShaderLibrary!),
size: Size.infinite,
);
}
}
class ShaderPainter extends CustomPainter {
final gpu.ShaderLibrary shaderLibrary;
ShaderPainter(this.shaderLibrary);
@override
void paint(Canvas canvas, Size size) {
// Use the shader library to draw something on the canvas
// For example, you can create a custom shader and apply it to a rectangle
final Paint paint = Paint()
..shader = shaderLibrary.getShader('CoolFragment').createShader(Rect.fromLTWH(0, 0, size.width, size.height));
canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
shaders/my_cool_shader.vert
#version 300 es
layout(location = 0) in vec4 aPosition;
layout(location = 1) in vec2 aTextureCoord;
out vec2 vTextureCoord;
void main() {
gl_Position = aPosition;
vTextureCoord = aTextureCoord;
}
shaders/my_cool_shader.frag
#version 300 es
precision mediump float;
in vec2 vTextureCoord;
out vec4 fragColor;
void main() {
fragColor = vec4(vTextureCoord, 0.0, 1.0);
}
hook/build.dart
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:flutter_gpu_shaders/build.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
await buildShaderBundleJson(
buildConfig: config,
buildOutput: output,
manifestFileName: 'my_cool_bundle.shaderbundle.json');
});
}
pubspec.yaml
name: my_project
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_gpu: ^0.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
assets:
- build/shaderbundles/*.shaderbundle.json
更多关于Flutter高性能图形渲染插件flutter_gpu_shaders的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter高性能图形渲染插件flutter_gpu_shaders的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于如何在Flutter中使用flutter_gpu_shaders
来实现高性能图形渲染,下面是一个简单的代码示例。flutter_gpu_shaders
允许你在Flutter应用中编写自定义的GLSL(OpenGL Shading Language)着色器,从而实现对图形渲染的精细控制。
首先,确保你已经将flutter_gpu_shaders
添加到你的pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
flutter_gpu_shaders: ^x.y.z # 替换为最新版本号
然后,运行flutter pub get
来获取包。
1. 编写GLSL着色器
创建一个文件shaders/simple_shader.glsl
,并添加以下GLSL代码:
// simple_shader.glsl
precision mediump float;
uniform sampler2D uTexture;
uniform vec4 uColor;
in vec2 vTexCoord;
out vec4 fragColor;
void main() {
vec4 textureColor = texture(uTexture, vTexCoord);
fragColor = uColor * textureColor;
}
这个简单的着色器只是将纹理的颜色与一个均匀颜色相乘。
2. 在Flutter中使用着色器
接下来,在你的Flutter应用中加载并使用这个着色器。创建一个新的Widget,例如CustomShaderWidget
:
import 'package:flutter/material.dart';
import 'package:flutter_gpu_shaders/flutter_gpu_shaders.dart';
import 'dart:ui' as ui;
import 'dart:typed_data';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter GPU Shaders Example'),
),
body: CustomShaderWidget(),
),
);
}
}
class CustomShaderWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ShaderMask(
shaderCallback: (bounds) {
return createSimpleShader(bounds.size);
},
blendMode: BlendMode.modulate,
child: Image.asset(
'assets/your_image.png', // 确保你有这个资源文件
fit: BoxFit.cover,
),
);
}
ui.Shader createSimpleShader(Size size) {
final String source = """
// 插入你的GLSL代码
$simpleShaderSource
""";
final Map<String, dynamic> uniforms = <String, dynamic>{
'uTexture': 0,
'uColor': [1.0, 1.0, 1.0, 1.0], // 白色,你可以根据需要调整
};
final FlutterShaderBuilder builder = FlutterShaderBuilder(source)
..addUniform('uTexture', FlutterShaderUniformType.sampler2D)
..addUniform('uColor', FlutterShaderUniformType.vec4)
..setUniforms(uniforms);
return builder.createShader();
}
// 加载GLSL源代码
String get simpleShaderSource {
return rootBundle.loadString('shaders/simple_shader.glsl').then((String source) {
return source;
}) ?? '';
}
}
注意:上面的代码片段中,simpleShaderSource
的获取方式需要异步处理,但在示例中直接返回了一个静态值。在实际应用中,你需要处理异步加载着色器源代码的情况。一个常见的做法是使用FutureBuilder或StatefulWidget来管理异步状态。
3. 异步加载GLSL源代码
为了正确处理异步加载,你可以将CustomShaderWidget
转换为一个StatefulWidget
,并在initState
中加载着色器源代码。
class CustomShaderWidget extends StatefulWidget {
@override
_CustomShaderWidgetState createState() => _CustomShaderWidgetState();
}
class _CustomShaderWidgetState extends State<CustomShaderWidget> {
String? _shaderSource;
@override
void initState() {
super.initState();
_loadShaderSource();
}
Future<void> _loadShaderSource() async {
final String source = await rootBundle.loadString('shaders/simple_shader.glsl');
setState(() {
_shaderSource = source;
});
}
@override
Widget build(BuildContext context) {
if (_shaderSource == null) {
return Center(child: CircularProgressIndicator());
}
return ShaderMask(
shaderCallback: (bounds) {
return createSimpleShader(bounds.size, _shaderSource!);
},
blendMode: BlendMode.modulate,
child: Image.asset(
'assets/your_image.png',
fit: BoxFit.cover,
),
);
}
ui.Shader createSimpleShader(Size size, String source) {
final Map<String, dynamic> uniforms = <String, dynamic>{
'uTexture': 0,
'uColor': [1.0, 1.0, 1.0, 1.0],
};
final FlutterShaderBuilder builder = FlutterShaderBuilder(source)
..addUniform('uTexture', FlutterShaderUniformType.sampler2D)
..addUniform('uColor', FlutterShaderUniformType.vec4)
..setUniforms(uniforms);
return builder.createShader();
}
}
这个示例展示了如何在Flutter中使用flutter_gpu_shaders
加载和应用自定义GLSL着色器。你可以根据需要进一步扩展和修改这个示例,以实现更复杂的图形渲染效果。