Flutter自定义着色器插件shaderify的使用

Flutter自定义着色器插件shaderify的使用

授权与限制

我不允许你使用此插件或使用你在此找到的任何内容,如果你从事以下领域的工作:

  • 保险
  • 区块链
  • 国防
  • 银行(除非你不涉及利息)
  • 欺骗客户
  • 让人们浪费时间
  • 酒精或反刍动物
  • 艺术(音乐、表现人脸/人类/动物等)
  • 任何邪恶的事物

如有疑问,请通过电子邮件联系我,我会尽快回复(dev@fodil.org)。

功能

开始使用

只需添加插件 flutter pub add shaderify

使用方法

就像一个普通的 widget 一样使用它:

ShaderWidget(shaderPath: "shaders/myshader.frag");

路径必须在 pubspec.yaml 文件中声明,位于 "flutter" 子句下。例如:

flutter:
    -- your configuration...

    shaders:
      - shaders/myshader.frag

大多数着色器只需要添加以下内容:

#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;

void main() {
    vec2 fragCoord = FlutterFragCoord().xy;
	// ...
}

以下是一个来自 shadertoy 的着色器示例:

#define iterations 17
#define formuparam 0.53

#define volsteps 20
#define stepsize 0.1

#define zoom   0.800
#define tile   0.850
#define speed  0.010 

#define brightness 0.0015
#define darkmatter 0.300
#define distfading 0.730
#define saturation 0.850

#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;

void main()
{
    vec2 fragCoord = FlutterFragCoord().xy;
	//get coords and direction
	vec2 uv=fragCoord.xy/iResolution.xy-.5;
	uv.y*=iResolution.y/iResolution.x;
	vec3 dir=vec3(uv*zoom,1.);
	float time=iTime*speed+.25;

	//mouse rotation
	float a1 = .5;
	float a2 = .8;

	mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));
	mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));
	dir.xz*=rot1;
	dir.xy*=rot2;
	vec3 from=vec3(1.,.5,0.5);
	from+=vec3(time*2.,time,-2.);
	from.xz*=rot1;
	from.xy*=rot2;
	
	//volumetric rendering
	float s=0.1,fade=1.;
	vec3 v=vec3(0.);
	for (int r=0; r&lt;volsteps; r++) {
		vec3 p=from+s*dir*.5;
		p = abs(vec3(tile)-mod(p,vec3(tile*2.))); // tiling fold
		float pa,a=pa=0.;
		for (int i=0; i&lt;iterations; i++) { 
			p=abs(p)/dot(p,p)-formuparam; // the magic formula
			a+=abs(length(p)-pa); // absolute sum of average change
			pa=length(p);
		}
		float dm=max(0.,darkmatter-a*a*.001); //dark matter
		a*=a*a; // add contrast
		if (r&gt;6) fade*=1.-dm; // dark matter, don't render near
		//v+=vec3(dm,dm*.5,0.);
		v+=fade;
		v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade; // coloring based on distance
		fade*=distfading; // distance fading
		s+=stepsize;
	}
	v=mix(vec3(length(v)),v,saturation); //color adjust
	fragColor = vec4(v*.01,1.);	
}

你可以使用传递给着色器的值。

完整示例

以下是一个完整的示例,展示了如何在 Flutter 应用程序中使用 ShaderWidget 插件。

项目结构

example/
├── lib/
│   ├── main.dart
├── shaders/
│   └── myshader.frag
└── pubspec.yaml

pubspec.yaml

name: example
description: A new Flutter project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  shaderify: ^1.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

  # 添加自定义着色器路径
  shaders:
    - shaders/myshader.frag

shaders/myshader.frag

#define iterations 17
#define formuparam 0.53

#define volsteps 20
#define stepsize 0.1

#define zoom   0.800
#define tile   0.850
#define speed  0.010 

#define brightness 0.0015
#define darkmatter 0.300
#define distfading 0.730
#define saturation 0.850

#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;

void main()
{
    vec2 fragCoord = FlutterFragCoord().xy;
	//get coords and direction
	vec2 uv=fragCoord.xy/iResolution.xy-.5;
	uv.y*=iResolution.y/iResolution.x;
	vec3 dir=vec3(uv*zoom,1.);
	float time=iTime*speed+.25;

	//mouse rotation
	float a1 = .5;
	float a2 = .8;

	mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));
	mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));
	dir.xz*=rot1;
	dir.xy*=rot2;
	vec3 from=vec3(1.,.5,0.5);
	from+=vec3(time*2.,time,-2.);
	from.xz*=rot1;
	from.xy*=rot2;
	
	//volumetric rendering
	float s=0.1,fade=1.;
	vec3 v=vec3(0.);
	for (int r=0; r&lt;volsteps; r++) {
		vec3 p=from+s*dir*.5;
		p = abs(vec3(tile)-mod(p,vec3(tile*2.))); // tiling fold
		float pa,a=pa=0.;
		for (int i=0; i&lt;iterations; i++) { 
			p=abs(p)/dot(p,p)-formuparam; // the magic formula
			a+=abs(length(p)-pa); // absolute sum of average change
			pa=length(p);
		}
		float dm=max(0.,darkmatter-a*a*.001); //dark matter
		a*=a*a; // add contrast
		if (r&gt;6) fade*=1.-dm; // dark matter, don't render near
		//v+=vec3(dm,dm*.5,0.);
		v+=fade;
		v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade; // coloring based on distance
		fade*=distfading; // distance fading
		s+=stepsize;
	}
	v=mix(vec3(length(v)),v,saturation); //color adjust
	fragColor = vec4(v*.01,1.);	
}

lib/main.dart

import 'package:flutter/widgets.dart';
import 'package:shaderify/shaderify.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const Directionality(
      textDirection: TextDirection.ltr,
      child: ShaderWidget(shaderPath: "shaders/myshader.frag"),
    );
  }
}

运行应用

确保你已经安装了 Flutter SDK,并且你的设备已连接到电脑。然后在项目根目录下运行以下命令:

flutter run

更多关于Flutter自定义着色器插件shaderify的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义着色器插件shaderify的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter自定义着色器插件Shaderify的示例代码。这个示例将展示如何在Flutter中创建一个简单的自定义着色器,并使用Shaderify将其应用到画布上。

首先,确保你已经在你的pubspec.yaml文件中添加了Shaderify依赖:

dependencies:
  flutter:
    sdk: flutter
  shaderify: ^最新版本号  # 替换为实际发布的最新版本号

然后运行flutter pub get来安装依赖。

接下来,我们将创建一个简单的自定义着色器,并在Flutter中使用它。

1. 创建一个自定义着色器文件(simple_shader.glsl

在你的项目资源目录中创建一个名为simple_shader.glsl的文件,并添加以下GLSL代码:

precision mediump float;

uniform sampler2D u_texture;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    vec4 color = texture(u_texture, uv);
    
    // 简单的颜色变换示例:将红色通道值增加
    color.r += sin(u_time) * 0.5;
    
    gl_FragColor = color;
}

2. 在Flutter中使用Shaderify加载和应用着色器

在你的Flutter项目中,创建一个新的Dart文件(例如shader_example.dart),并添加以下代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ShaderExample(),
    );
  }
}

class ShaderExample extends StatefulWidget {
  @override
  _ShaderExampleState createState() => _ShaderExampleState();
}

class _ShaderExampleState extends State<ShaderExample> with SingleTickerProviderStateMixin {
  late ShaderifyController _shaderifyController;
  late AnimationController _animationController;

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

    // 初始化动画控制器
    _animationController = AnimationController(
      duration: const Duration(seconds: 5),
      vsync: this,
    )..repeat(reverse: true);

    // 初始化Shaderify控制器
    _shaderifyController = ShaderifyController(
      shader: Shaderify.fromGLSL(
        vertexShader: """
        attribute vec4 a_position;
        attribute vec2 a_texCoord;
        uniform mat4 u_matrix;
        varying vec2 v_texCoord;
        void main() {
          gl_Position = u_matrix * a_position;
          v_texCoord = a_texCoord;
        }
        """,
        fragmentShader: Shaderify.loadFromAsset('simple_shader.glsl'),  // 加载自定义着色器
      ),
      uniforms: {
        'u_time': _animationController.value,
      },
      size: Size(800, 600),  // 设置画布大小
    );

    // 监听动画值变化并更新着色器uniform
    _animationController.addListener(() {
      setState(() {
        _shaderifyController.setUniform('u_time', _animationController.value);
      });
    });
  }

  @override
  void dispose() {
    _animationController.dispose();
    _shaderifyController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Shaderify Example'),
      ),
      body: CustomPaint(
        size: _shaderifyController.size,
        painter: _ShaderPaint(_shaderifyController),
      ),
    );
  }
}

class _ShaderPaint extends CustomPainter {
  final ShaderifyController shaderifyController;

  _ShaderPaint(this.shaderifyController);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..shader = shaderifyController.shader
      ..isAntiAlias = true;

    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

3. 在pubspec.yaml中指定着色器文件

确保在pubspec.yaml中的flutter部分下的assets字段中指定了着色器文件路径:

flutter:
  assets:
    - assets/simple_shader.glsl  # 确保路径正确

4. 运行应用

现在,你可以运行你的Flutter应用,并看到一个使用自定义着色器渲染的画布。着色器会根据时间的变化动态更新红色通道的值,产生颜色变换效果。

这个示例展示了如何在Flutter中使用Shaderify来加载和应用自定义GLSL着色器。你可以根据需要进一步扩展和修改着色器代码以实现更复杂的视觉效果。

回到顶部