One of the advantages to the Fist of the Forgotten art style is that there is no color data necessary for textures. This allowed me to explore some creative uses of the RGB channels. Another advantage is that the camera is at a fixed angle due to the game being a 2.5D platformer. Here’s a clever solution to getting detailed tree silhouettes with (hopefully) less performance cost than traditional 3D tree models.
Here's a breakdown of how it works. First, I draw a tree in 3 layers on an atlas texture in Krita: Blue = background, Red = medium height, Green = max height. I chose these colors simply because of the order of brightness (originally went with RGB, but it was difficult to see blue on top of everything):

Next, I make a simple mesh in Blender and use the vertex colors to determine how much parallax (and wind sway) to apply to each vertex on the mesh. The parallax is in UV coordinates, so it needs to be scaled relative to the size of the mesh in relation to the size of the texture. Setting the scale per-vertex also lets me do things like taper the amount of parallax near the top or bottom of the tree.

Finally, in a shader, I generate offset uv's for the red and green channels. Then I do texture lookups for those colors with the offset UV's and use them as an alpha mask. The color is generated the same way as my normal shader (a simple curve based on z-depth for the fog fading from black to light blue). To make it simpler to see the effect, I've modified the shader to show the original colors:
When it's all said and done, it should add a little more dimensionality to the background scenes without the performance cost of full 3D trees, though I haven't actually done any performance tests to verify this. It just sounded like a good idea at the time. The player will likely never know that it's all smoke and mirrors and completely breaks down when viewed from the side:
Special thanks to badcodebot who had an alternative approach to applying the parallax effect that did not require a matrix inverse. My original shader was something like:
// Original implementation
world_coordinates = (WORLD_MATRIX * vec4(VERTEX, 1.0)).xyz;
camera_location = CAMERA_MATRIX[3].xyz;
float parallax_scale = 0.0625 * COLOR.r;
vec3 view_dir = normalize(camera_location - world_coordinates);
mat3 magic;
// Not 100% sure on this
// just tried different combinations until it worked.
magic[0] = TANGENT;
magic[1] = -BINORMAL;
magic[2] = NORMAL;
magic = transpose(magic);
// TODO, unsupported in GLES2:
view_dir = (inverse(WORLD_MATRIX) * vec4(view_dir, 0.0)).xyz;
vec2 parallax = (view_dir.xy * vec2(1.0, -1.0)) / view_dir.z;
parallax_uv = UV + parallax * parallax_scale * 0.5;
parallax_uv2 = UV + parallax * parallax_scale;`
Badcodebot suggested something like:
// badcodebot suggestion
vec4 w = WORLD_MATRIX * vec4(VERTEX, 1);
vec4 c = CAMERA_MATRIX * vec4(0, 0, 0, 1);
vec3 d = c.xyz - w.xyz; vec3 v = normalize(d);
vec2 o = vec2(dot((WORLD_MATRIX * vec4(TANGENT, 0.0)).xyz, v),
dot((WORLD_MATRIX * vec4(BINORMAL, 0.0)).xyz, v));
parallax_uv = UV + o * parallax_scale * 0.5;
parallax_uv2 = UV + o * parallax_scale;
I've translated it into something with more human-readable variables here:
// badcodebot->human translation
vec3 view_dir = normalize(camera_location - world_coordinates);
vec2 offset = vec2(
dot((WORLD_MATRIX * vec4(TANGENT, 0.0)).xyz, view_dir),
dot((WORLD_MATRIX * vec4(BINORMAL, 0.0)).xyz, view_dir));
parallax_uv = UV + offset * parallax_scale * 0.5;
parallax_uv2 = UV + offset * parallax_scale;
The advantage to this method, aside from not requiring the matrix inverse, is that it also clamps the amount of UV sliding that happens, so at extreme angles, the texture does not slide completely off of the polygon.