Skip to content

[Impeller] Texture sampling seems to behave differently between Skia and Impeller (iOS) #115039

@jonahwilliams

Description

@jonahwilliams

Besides the issue with the texture background sometimes being black, the child appears distored under impeller differently than it would be under Skia:

Skia:

Impeller:

main.dart

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

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

final transform = Matrix4.identity().storage;

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


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: RepaintBoundary(
          child: ShaderBuilder(
            (BuildContext context, FragmentShader shader, Widget? child) {
              return AnimatedSampler(
                (ui.Image image, Size size, Offset offset, ui.Canvas canvas) {
                  canvas.translate(offset.dx, offset.dy);
                  var sampler = ImageShader(image, TileMode.clamp, TileMode.clamp, transform);
                  shader.setFloat(0, size.width);
                  shader.setFloat(1, size.height);
                  shader.setSampler(0, sampler);
                  canvas.translate(offset.dx, offset.dy);
                  canvas.drawRect(Offset.zero & size, Paint()..shader = shader);
                },
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      const Text(
                        'You have pushed the button this many times:',
                      ),
                      Text(
                        '$_counter',
                        style: Theme.of(context).textTheme.headlineMedium,
                      ),
                    ],
                  ),
                );
            },
            assetKey: 'shaders/blur.frag',
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

shaders/sampler.frag

precision highp float;

#include <flutter/runtime_effect.glsl>

const float PI = 3.14159;

layout(location = 0) uniform float width;
layout(location = 1) uniform float height;
layout(location = 2) uniform sampler2D tInput;

out vec4 fragColor;

float random(vec3 xyz){
    return fract(sin(dot(xyz, vec3(12.9898, 78.233, 151.7182))) * 43758.5453);
}

vec4 fragment(vec2 uv, vec2 fragCoord) {
    vec4 color = vec4(0.0);
    float total = 0.0;
    vec2 tDelta = 50 * vec2(cos(PI), sin(PI));
    float offset = random(vec3(fragCoord, 1000.0));

    for (float t = -30.0; t <= 30.0; t += 5){
        float percent = (t + offset - 0.5) / 30.0;
        float weight = 1.0 - abs(percent);
        color += texture(tInput, uv + tDelta * percent) * weight;
        total += weight;
    }

    if (total == 0.0) {
        total = 1.0;
    }
    return color / total;
}

void main() {
  vec2 pos = FlutterFragCoord();
  vec2 uv = pos / vec2(width, height);
  fragColor = fragment(uv, pos);
}

pubspec.yaml

name: foo_bar_shaders
description: A new Flutter project.

environment:
  sdk: '>=2.19.0-374.0.dev <3.0.0'

dependencies:
  flutter:
    sdk: flutter
  flutter_shaders: ^0.0.1
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  shaders:
    - shaders/blur.frag
    - shaders/sampler.frag

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions