In the first two weeks of September (2015) I created an app to view and run shaders of Shadertoy on my iPhone. After finishing the first version of this app I was very pleased that Pol Jeremias and Iñigo Quílez wanted to replace their official Shadertoy App with the app I made.
Please download the Shadertoy app from the App Store and let me know what you think.
Previews and caching
My primary goal was to create a stable and fast app that you can use to easily view the shaders of Shadertoy on your iPhone.
Getting the shaders to run on my phone was easy. I use the Shadertoy API to get a list of all shaders (that is, shaders published using the “Public + API” option) and I use the same API to get the source of each shader. In app, I create an OpenGLES ES2 context which has (almost) the same shader-language syntax as WebGL (version 1). So most shaders of Shadertoy will compile on your phone without any modifications.
It really surprised me how fast the GPU of an iPhone is. I developed the app using an iPhone 5s and on that device almost all shaders run at 20fps. I currently have an iPhone 6s and this phone is really fast: almost all shaders are running fluidly full screen.
High quality image export of “Abandoned base”.
To get the browsing experience as fast as possible, I use a lot of caching and I use images to show a preview of each shader.
1. Caching. All data is cached locally. This is why you will almost immediately see the list of shaders after opening the app and why you are even able to run the shaders that you have viewed before when offline.
I have tried to implement a more or less smart system to invalidate the cache of shaders (to reduce download bandwidth). Every time you view a shader, the cache of this shader is invalidated so a next time you view this same shader, the source code is probably refreshed. The cache of shaders will also be invalidated automatically after some time. New shaders are invalidated more often, ‘old’ shaders only once a year. Unfortunately, this cache system is not perfect: it is quite possible that you will not directly see changes made to an old shader.
2. Using previews of the shaders. Shadertoy already has a feature to display ‘previews’ instead of compiling and running the shaders when browsing on the site. I use these existing images, scale them down and cache them locally. When searching and browsing through shaders in the app, I use these images to create one long list with previews of all shaders.
Over the past year I have occasionally added some additional functionality to the app and the app is now almost ‘complete’. Which means: almost all shaders run the same in app as on the Shadertoy site. The app now supports:
- Multipass. Some shaders use multiple passes and combine different buffers for their final output image.
- VR. A shader can implement the mainVR function:
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir );
If this function is implemented, the shader can be viewed using webVR. I’ve added support for these shaders in app, by rendering the output of this function to a stereo view, crossed eye view, a mono fullscreen view or an anaglyph (cyan/red) view. When you choose the stereo view and use the rotation of your iPhone to control the camera used for the shader, you can view a VR shader using a Google cardboard.
- GPU Sound. Shaders can generate sound (or music) by using a second shader that returns a vec2 for a given time. This vec2 will be interpreted as the left and right value of a stereo audio wave. I wanted low latency playback of this sound in order to get the sound in sync with the shader. To get low latency on an iPhone, I used Apple’s Audio Component Services. The source of the sound playback can be found here.
- Image export. You can export a shader as a high quality image or as an animated gif.
- I have added some basic keyboard input (for arrow keys and space) and Soundcloud support.
Animated gif export of “Flames”.
Full source code
You can find the full source code of the Shadertoy iOS app on GitHub.