[HTML5] Shader animation freezes

Shader animation freezes during short period of time. But If you minimize and maximize window again, it plays again and freezes once again

package;

import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.display.DisplayObjectShader;
import openfl.display.FPS;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.text.TextFormat;

class Main extends Sprite
{
	public function new()
	{
		super();

		stage.color = 0;

		var stats:FPS = new FPS(10, 10, 0xffcc00);
		var tf:TextFormat = new TextFormat();
		tf.size = 30;
		stats.width = 200;
		stats.height = 200;
		stats.defaultTextFormat = tf;
		stage.addChild(stats);

		var s:Sprite = new Sprite();
		s.graphics.beginFill(0xff0000);
		s.graphics.drawRect(0, 0, 800, 600);
		s.graphics.endFill();
		var bd:BitmapData = new BitmapData(Std.int(s.width), Std.int(s.height), false);
		bd.draw(s);
		s.graphics.clear();
		s.addChild(new Bitmap(bd));

		var shader:S = new S();
		s.shader = shader;
		addChild(s);

		var t:Float = 1.0;

		addEventListener(Event.ENTER_FRAME, e -> {
			t += 0.05;
			shader.time.value = [t];
		});
	}
}

class S extends DisplayObjectShader
{
	@:glFragmentSource("
		#pragma header

		// Author: Vatroslav Vrbanic, Cream markting creations GmbH
		// Website: https://cream.gmbh
		// Title: colored fog
		// Comment: forked 'smoke', see http://shaderfrog.com/view/2459

		precision highp float;

		uniform float time;

		// generates pseudo-randam based on screen position
		float random(vec2 pos)
		{
			return fract(sin(dot(pos.xy, vec2(12.9898, 78.233))) * 43758.5453123);
		}

		// perlin noise
		float noise(vec2 pos)
		{
			vec2 i = floor(pos);
			vec2 f = fract(pos);
			float a = random(i + vec2(0.0, 0.0));
			float b = random(i + vec2(1.0, 0.0));
			float c = random(i + vec2(0.0, 1.0));
			float d = random(i + vec2(1.0, 1.0));
			vec2 u = f * f * (3.0 - 2.0 * f);
			return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
		}

		// fractional brownian motion
		float fbm(vec2 pos)
		{
			float v = 0.0;
			float a = 0.5;
			vec2 shift = vec2(70);
			for (int i=0; i<16; i++)
			{
				v = (sin(v*1.1)) + (a * noise(pos*shift*0.15));
				pos = /*rot* **/ pos * 2.0 + shift;
				a *= 0.5;
			}
			return v;
		}

		void main(void)
		{
			float speed = 2.5;
			vec2 resolution = vec2(800, 600);
			vec2 p = (gl_FragCoord.xy * 2.0 - resolution.xy) / min(resolution.x, resolution.y);
			float time2 = (speed) * time / 1.25;

			vec2 q = vec2(0.0);
			q.x = fbm(p + 0.00 * time2);
			q.y = fbm(p + vec2(1.0));
			vec2 r = vec2(-1.0);
			r.x = fbm(p + 1.0 * q + vec2(1.7, 9.2) + 0.15 * time2);
			r.y = fbm(p + 1.0 * q + vec2(8.3, 2.8) + 0.126 * time2);
			float f = fbm(p + r);

			vec4 color = mix(
				vec4(0,0,0,1.0),
				vec4(1.5, 1.5, 1.5,1.0),
				clamp(length(r.x), 0.0, 1.0)
			);

			color = (f *f * f + 0.6 * f * f + 0.5 * f) * color;

			gl_FragColor = vec4(color);
		}
	")

	public function new()
	{
		super();
	}
}

But if I add s.x += 0.1; to ENTER_FRAME handler, it doesn’t freeze

I think your cacheasbitmap is not getting invalidated when it should.

You can try add and then substract to X if I am correct…

You need to call invalidate.

2 Likes

OpenFL stops rendering when the screen is detected to not be dirty but calling invalidate() on the object should break the cache