+void write_ppm(const char *filename, const uint8_t *rgba, unsigned width, unsigned height)
+{
+ unique_ptr<uint8_t[]> rgb_line(new uint8_t[width * 3 + 1]);
+
+ FILE *fp = fopen(filename, "wb");
+ fprintf(fp, "P6\n%d %d\n255\n", width, height);
+ for (unsigned y = 0; y < height; ++y) {
+ unsigned y2 = height - 1 - y;
+ for (size_t x = 0; x < width; ++x) {
+ memcpy(&rgb_line[x * 3], &rgba[(y2 * width + x) * 4], 4);
+ }
+ fwrite(rgb_line.get(), width * 3, 1, fp);
+ }
+ fclose(fp);
+}
+
+struct FlowType {
+ using type = float;
+ static constexpr GLenum gl_format = GL_RG;
+ static constexpr GLenum gl_type = GL_FLOAT;
+ static constexpr int num_channels = 2;
+};
+
+struct RGBAType {
+ using type = uint8_t;
+ static constexpr GLenum gl_format = GL_RGBA;
+ static constexpr GLenum gl_type = GL_UNSIGNED_BYTE;
+ static constexpr int num_channels = 4;
+};
+
+template <class Type>