Creating Custom Shaders with Fragment Programs in Flutter

Summary
Summary
Summary
Summary

Learn how to write GLSL-like shaders, compile them into SKSL assets, and integrate FragmentProgram in Flutter for GPU-accelerated effects, plus performance tips for mobile development.

Learn how to write GLSL-like shaders, compile them into SKSL assets, and integrate FragmentProgram in Flutter for GPU-accelerated effects, plus performance tips for mobile development.

Learn how to write GLSL-like shaders, compile them into SKSL assets, and integrate FragmentProgram in Flutter for GPU-accelerated effects, plus performance tips for mobile development.

Learn how to write GLSL-like shaders, compile them into SKSL assets, and integrate FragmentProgram in Flutter for GPU-accelerated effects, plus performance tips for mobile development.

Key insights:
Key insights:
Key insights:
Key insights:
  • Understanding Fragment Programs: Load compiled SKSL assets with FragmentProgram.load to run shaders on the GPU.

  • Writing GLSL Shaders: Define a mainImage function and uniforms in a .frag file, then list it under flutter.shaders.

  • Integrating Shaders in Flutter: Use program.shader() in CustomPainter to bind uniforms and draw with Canvas.

  • Optimizing Shader Performance: Reduce uniform updates and texture lookups, reuse program instances to maintain frame rates.

Introduction

Flutter’s rendering pipeline has evolved to support custom GPU-accelerated effects via FragmentProgram. This capability empowers mobile development teams to write GLSL-like shaders, compile them at build time, and invoke them directly from Dart. In this tutorial, you’ll learn how to create, compile, and integrate fragment shaders into a Flutter app using the FragmentProgram API.

Understanding Fragment Programs

A FragmentProgram in Flutter wraps a compiled shader binary (SKSL) for execution on the GPU. You author a shader in GLSL syntax, then compile it with flutter tooling into a .spirv or .sksl asset. At runtime, FragmentProgram.load reads this compiled asset and returns a FragmentProgram instance. You can then call fragmentProgram.shader() to produce a FragmentShader, which you use in a CustomPainter or ShaderMask.

Key steps:

  • Write GLSL-like code in a .frag file.

  • Add it as an asset in pubspec.yaml under shaders.

  • Run flutter build bundle to compile to SKSL.

Writing GLSL Shaders

Your shader file targets an entry function—typically void mainImage(out vec4 fragColor, in vec2 fragCoord). The coordinate system runs from (0,0) at the bottom-left to (width,height) at the top-right. You can declare uniform variables for values passed from Dart (floats, vectors, textures).

Example shader (circle.frag):

precision highp float;
uniform vec2 u_resolution;
uniform vec2 u_center;
uniform float u_radius;
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = fragCoord / u_resolution;
  float dist = distance(uv * u_resolution, u_center);
  float alpha = smoothstep(u_radius, u_radius - 5.0, dist);
  fragColor = vec4(vec3(1.0), alpha);
}

Configure pubspec.yaml:

flutter:
  shaders

After building, the shader asset will be available to FragmentProgram.load.

Integrating Shaders in Flutter

Once you have a compiled shader asset, you load and execute it in a CustomPainter:

import 'dart:ui' as ui;
import 'package:flutter/services.dart';

class CirclePainter extends CustomPainter {
  final ui.FragmentProgram program;
  CirclePainter(this.program);

  @override
  void paint(Canvas canvas, Size size) {
    final shader = program.shader(
      floatUniforms: Float32List.fromList([
        size.width, size.height, // u_resolution
        size.width/2, size.height/2, // u_center
        50.0, // u_radius
      ]),
    );
    final paint = Paint()..shader = shader;
    canvas.drawRect(Offset.zero & size, paint);
  }

  @override bool shouldRepaint(covariant CustomPainter old) => false;
}

Load the program in a StatefulWidget:

late final ui.FragmentProgram _program;

@override
void initState() {
  super.initState();
  ui.FragmentProgram.load(
    asset: 'shaders/circle.frag',
  ).then((prog) => setState(() => _program = prog));
}

Optimizing Shader Performance

Shaders run per pixel on the GPU, so efficiency is crucial in mobile development. To optimize:

• Minimize the number of uniforms and texture lookups.

• Keep shader code simple—avoid loops with dynamic bounds.

• Reuse FragmentProgram instances rather than loading repeatedly.

• Profile on target devices with Flutter’s performance overlay.

By carefully structuring your shaders and data flows, you can achieve high frame rates while enriching your UI with complex effects.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

FragmentProgram in Flutter unlocks advanced GPU-driven visuals for mobile development. By writing SKSL-compliant GLSL shaders, compiling them into assets, and integrating via CustomPainter, you can craft bespoke effects that run smoothly on iOS and Android. Optimize your uniforms and minimize state changes to maintain performance. With this foundation, you’re ready to explore post-processing, procedural textures, and more custom GPU work in Flutter.

Introduction

Flutter’s rendering pipeline has evolved to support custom GPU-accelerated effects via FragmentProgram. This capability empowers mobile development teams to write GLSL-like shaders, compile them at build time, and invoke them directly from Dart. In this tutorial, you’ll learn how to create, compile, and integrate fragment shaders into a Flutter app using the FragmentProgram API.

Understanding Fragment Programs

A FragmentProgram in Flutter wraps a compiled shader binary (SKSL) for execution on the GPU. You author a shader in GLSL syntax, then compile it with flutter tooling into a .spirv or .sksl asset. At runtime, FragmentProgram.load reads this compiled asset and returns a FragmentProgram instance. You can then call fragmentProgram.shader() to produce a FragmentShader, which you use in a CustomPainter or ShaderMask.

Key steps:

  • Write GLSL-like code in a .frag file.

  • Add it as an asset in pubspec.yaml under shaders.

  • Run flutter build bundle to compile to SKSL.

Writing GLSL Shaders

Your shader file targets an entry function—typically void mainImage(out vec4 fragColor, in vec2 fragCoord). The coordinate system runs from (0,0) at the bottom-left to (width,height) at the top-right. You can declare uniform variables for values passed from Dart (floats, vectors, textures).

Example shader (circle.frag):

precision highp float;
uniform vec2 u_resolution;
uniform vec2 u_center;
uniform float u_radius;
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = fragCoord / u_resolution;
  float dist = distance(uv * u_resolution, u_center);
  float alpha = smoothstep(u_radius, u_radius - 5.0, dist);
  fragColor = vec4(vec3(1.0), alpha);
}

Configure pubspec.yaml:

flutter:
  shaders

After building, the shader asset will be available to FragmentProgram.load.

Integrating Shaders in Flutter

Once you have a compiled shader asset, you load and execute it in a CustomPainter:

import 'dart:ui' as ui;
import 'package:flutter/services.dart';

class CirclePainter extends CustomPainter {
  final ui.FragmentProgram program;
  CirclePainter(this.program);

  @override
  void paint(Canvas canvas, Size size) {
    final shader = program.shader(
      floatUniforms: Float32List.fromList([
        size.width, size.height, // u_resolution
        size.width/2, size.height/2, // u_center
        50.0, // u_radius
      ]),
    );
    final paint = Paint()..shader = shader;
    canvas.drawRect(Offset.zero & size, paint);
  }

  @override bool shouldRepaint(covariant CustomPainter old) => false;
}

Load the program in a StatefulWidget:

late final ui.FragmentProgram _program;

@override
void initState() {
  super.initState();
  ui.FragmentProgram.load(
    asset: 'shaders/circle.frag',
  ).then((prog) => setState(() => _program = prog));
}

Optimizing Shader Performance

Shaders run per pixel on the GPU, so efficiency is crucial in mobile development. To optimize:

• Minimize the number of uniforms and texture lookups.

• Keep shader code simple—avoid loops with dynamic bounds.

• Reuse FragmentProgram instances rather than loading repeatedly.

• Profile on target devices with Flutter’s performance overlay.

By carefully structuring your shaders and data flows, you can achieve high frame rates while enriching your UI with complex effects.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

FragmentProgram in Flutter unlocks advanced GPU-driven visuals for mobile development. By writing SKSL-compliant GLSL shaders, compiling them into assets, and integrating via CustomPainter, you can craft bespoke effects that run smoothly on iOS and Android. Optimize your uniforms and minimize state changes to maintain performance. With this foundation, you’re ready to explore post-processing, procedural textures, and more custom GPU work in Flutter.

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Other Insights

Other Insights

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025