You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求基于顶点UV/颜色的Flutter着色器示例

Flutter 顶点UV/颜色着色器示例(结合Canvas.drawVertices)

下面是一个完整的示例,展示如何通过Canvas.drawVertices()将顶点UV、颜色数据直接传入着色器,摆脱对全局uSize变量的依赖,实现多区域独立渲染:

1. GLSL 着色器代码

顶点着色器(vertex_shader.glsl)

uniform mat4 uViewProjectionMatrix;

attribute vec2 aPosition;
attribute vec2 aTexCoord;
attribute vec4 aColor;

varying vec2 vTexCoord;
varying vec4 vColor;

void main() {
  gl_Position = uViewProjectionMatrix * vec4(aPosition, 0.0, 1.0);
  vTexCoord = aTexCoord;
  vColor = aColor;
}

片元着色器(fragment_shader.glsl)

precision mediump float;

varying vec2 vTexCoord;
varying vec4 vColor;

void main() {
  // 基于UV实现棋盘格效果,同时叠加顶点颜色
  float checker = step(0.5, mod(vTexCoord.x + vTexCoord.y, 1.0));
  vec3 checkerColor = mix(vec3(0.2), vec3(0.8), checker);
  gl_FragColor = vec4(checkerColor * vColor.rgb, vColor.a);
}

2. Flutter Dart 代码实现

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class VertexShaderDemo extends StatefulWidget {
  const VertexShaderDemo({super.key});

  @override
  State<VertexShaderDemo> createState() => _VertexShaderDemoState();
}

class _VertexShaderDemoState extends State<VertexShaderDemo> {
  FragmentProgram? _program;

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

  Future<void> _loadShader() async {
    final vertexShader = await rootBundle.loadString('shaders/vertex_shader.glsl');
    final fragmentShader = await rootBundle.loadString('shaders/fragment_shader.glsl');
    _program = await FragmentProgram.fromAsset(
      'shaders/fragment_shader.glsl',
      vertexShader: vertexShader,
    );
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        painter: _VertexPainter(program: _program),
        size: Size.infinite,
      ),
    );
  }
}

class _VertexPainter extends CustomPainter {
  final FragmentProgram? program;

  _VertexPainter({this.program});

  @override
  void paint(Canvas canvas, Size size) {
    if (program == null) return;

    final shader = program!.fragmentShader();

    // 定义两个独立矩形的顶点数据(每个矩形由2个三角形组成)
    final vertices = Vertices(
      VertexMode.triangles,
      [
        // 左上矩形顶点
        Offset(50, 50), Offset(250, 50), Offset(250, 250),
        Offset(50, 50), Offset(250, 250), Offset(50, 250),
        // 右下矩形顶点
        Offset(300, 300), Offset(500, 300), Offset(500, 500),
        Offset(300, 300), Offset(500, 500), Offset(300, 500),
      ],
      uv: [
        // 左上矩形UV(0-1范围)
        const Offset(0, 0), const Offset(1, 0), const Offset(1, 1),
        const Offset(0, 0), const Offset(1, 1), const Offset(0, 1),
        // 右下矩形UV(0-2范围,实现棋盘格重复)
        const Offset(0, 0), const Offset(2, 0), const Offset(2, 2),
        const Offset(0, 0), const Offset(2, 2), const Offset(0, 2),
      ],
      colors: [
        // 左上矩形顶点颜色(蓝色系渐变)
        Colors.blue.withOpacity(0.8), Colors.lightBlue.withOpacity(0.8),
        Colors.cyan.withOpacity(0.8), Colors.blue.withOpacity(0.8),
        Colors.cyan.withOpacity(0.8), Colors.lightBlue.withOpacity(0.8),
        // 右下矩形顶点颜色(红色系渐变)
        Colors.red.withOpacity(0.8), Colors.orange.withOpacity(0.8),
        Colors.yellow.withOpacity(0.8), Colors.red.withOpacity(0.8),
        Colors.yellow.withOpacity(0.8), Colors.orange.withOpacity(0.8),
      ],
    );

    // 设置视图投影矩阵,将画布坐标转为GL标准化设备坐标
    shader.setFloatMatrix4(0, Float64List.fromList([
      2 / size.width, 0, 0, 0,
      0, -2 / size.height, 0, 0,
      0, 0, 1, 0,
      -1, 1, 0, 1,
    ]));

    canvas.drawVertices(vertices, BlendMode.srcOver, Paint()..shader = shader);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

关键说明

  • 顶点属性映射:Flutter 内置了顶点属性绑定,Vertices的positions对应着色器aPosition,uv对应aTexCoord,colors对应aColor,无需手动绑定。
  • 多区域独立渲染:示例中两个矩形的UV范围、颜色完全独立,着色器直接基于每个顶点的UV和颜色计算像素,不需要全局uSize统一控制。
  • 坐标转换:通过uViewProjectionMatrix将Flutter画布坐标转换为GL的标准化设备坐标,确保顶点位置正确显示在屏幕上。

内容的提问来源于stack exchange,提问作者Andrey Falkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:40:21