ios visual f/x using glsl
DESCRIPTION
Original Presentation: http://bit.ly/JdJt0v Tweets: @dugla Email: [email protected]TRANSCRIPT
iOS Visual F/X
Douglass TurnerElastic Image Softwareemail: [email protected] tweets: @duglacell: 781 775 3708
• Cocoa Touch Limitations• Visual f/x Idioms• Show and Tell
Cocoa Touch and its realization in Objective-C is about:
Abstraction. Pattern. Messaging. Generality. Simplicity.
Containers: NSArray. NSDictionary. NSSet.
Data:NSData. NSString. CoreData.
Patterns:MVC. Target/Action. Delegation.
The Objective-C Runtime is Powerful:
NSClassFromString | NSStringFromClass.
When it comes to visual expressive power the limitations of Cocoa Touch become apparent.
UIView lives in flatland ...
// UIViewstruct CGRect { CGPoint origin; CGSize size; };struct CGPoint { CGFloat x; CGFloat y; };
struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty;};
@property(nonatomic) CGRect frame;@property(nonatomic) CGRect bounds; @property(nonatomic) CGPoint center; @property(nonatomic) CGAffineTransform transform;
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
... but relies on CALayer which lives in 3D.
struct CATransform3D{ CGFloat m11, m12, m13, m14; CGFloat m21, m22, m23, m24; CGFloat m31, m32, m33, m34; CGFloat m41, m42, m43, m44;};
// CALayer@property CGFloat zPosition;@property CGFloat anchorPointZ;@property CATransform3D transform;
iOS would prefer you ignore pixels and think about resolution independent points instead
The level of visual abstraction is the asset:
Image. Video. Audio.
As long as you are willing to remain at this high level of abstraction you can get a lot done using UIViewAnimation, CIImage, etc.
But perhaps you are interested in going a bit deeper ...
Hello OpenGL
You take the red pill – you stay in Wonderland and I show you how deep the rabbit-hole goes." -Morpheus
OpenGL Cocoa
OpenGL is old school
You are flipping levers on a large state machine.
OpenGL is a dragster. Not a Prius. Just buckle up ...
... and enjoy the ride, baby!
OpenGL websites are a bit different than the Cocoa websites/blogs you are familiar with ...
Isn’t that sweet ...
Um... WTF?
Can you feel the love?
Dude. I think my eyes are bleeding.
Our focus is GLSL the OpenGL Shading Language
The Shader Backstory
• Pixar creates Reyes (Render Everything You Ever Saw)• Pixar creates RenderMan: C-like language for describing a 3D look at the sample (pixel) level.• Boom! Everything changes.• GLSL created in the spirit of RenderMan.
Shaders allow us to ignore the rest of a software system, freeing us to focus on achieving a specific look.
EISParticleSystemhttp://github.com/turner/EISParticleSystem
Texture Atlas Hacks
http://github.com/turner/EISParticleSystem
s
t
Texture Space
s
t
Texture Space
Accelerometer Hacks
http://github.com/turner/EISParticleSystem
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
Initialize model state
Evolve model state
Clean up model state
Demo
GLSL. Think C-lite.
varying!vec2 v_st;
uniform sampler2D hero;
void main() {!! gl_FragColor =
(heroChannels == 1) ? vec4(texture2D(hero, v_st).a) : texture2D(hero, v_st);!}
varying!vec2 v_st;
uniform sampler2D hero;
void main() {!! gl_FragColor = (heroChannels == 1) ? vec4(texture2D(hero, v_st).a) : texture2D(hero, v_st);!}
TextureMapShader
InvertColorShader
vec2 v_st;
uniform int heroChannels;uniform sampler2D hero;
void main() {! ! vec3 rgb; rgb = (heroChannels == 1) ? 1.0 - vec3(raw.a) : 1.0 - raw.rgb; !
gl_FragColor = vec4(rgb, raw.a);!}
LuminanceShader
varying vec2 v_st;
uniform int heroChannels;uniform sampler2D hero;
void main() {! vec4 raw = (heroChannels == 1) ? vec4(texture2D(hero, v_st).a) : texture2D(hero, v_st);
! vec3 rgb;! if (heroChannels == 1) {!! ! rgb = vec3(texture2D(hero, v_st).a);! !! } else {!! ! vec3 luminance_weights = vec3(0.30, 0.59, 0.11);!!! ! rgb = vec3( dot( luminance_weights, texture2D(hero, v_st).rgb ) );! }!! gl_FragColor = vec4(rgb, raw.a);
}
MixShader
varying!vec2 v_st;
uniform vec3 overRGB;!uniform vec3 underRGB;
uniform int heroChannels;uniform sampler2D hero;
void main() {
! float mixer;!! mixer = (heroChannels == 1) ? texture2D(hero, v_st).a : texture2D(hero, v_st).g;!! gl_FragColor = vec4(mix(underRGB, overRGB, mixer), texture2D(hero, v_st).a);!}
varying!vec2 v_st;
uniform vec3 overRGB;!uniform vec3 underRGB;
uniform int heroChannels;uniform sampler2D hero;
void main() {
! float mixer;!! mixer = (heroChannels == 1) ? texture2D(hero, v_st).a : texture2D(hero, v_st).g;!! gl_FragColor = vec4(mix(underRGB, overRGB, mixer), texture2D(hero, v_st).a);!}
The GPU is a parallel processing beast. It uses a SIMD architecture (Single Instruction Multiple Data) to achieve massive processing power.
A GLSL shader is a SIMD program. The GPU takes a shader and evaluates it simultaneously - but with different data - at every sample (pixel) in parallel:
On iPad that is:2048 x 1536 * 30 fps = 94,371,840 shader evaluations per sec.
What is exciting about this level of performance on an iOS device is the ability to take tasks previously thought of as desktop tasks done with Photoshop, Final Cut, etc. and do them live in a handheld device equipped with camera, mic, and other sensors.
Demo. GLSL Powered Apps
• Beautiful Panoramas. App Store: http://bit.ly/9KJBLA• BMW Interior. Panoramic hotspots prototype.• RadPad. iPad radiology prototype.
Shader Idioms
To fully “get” the power of shaders and their style of use it helpsknow the idioms guiding their use:
• Multiple Passes• Iteration aka Ping/Pong• Buffers/Channels• Indirection/Remapping
Shader Idioms
These idioms derive directly from Hollywood film production workflows and practices that enable: • complex problem decomposition. Tractability.• rapid turnaround.• maximum flexibility and tweek-ability.• responsiveness to director’s whims
Demo. ElasticImage.
ElasticImage highlights.
• Rapid shader creation & deployment• Shaders and gesture declared in plist• Cocoa Touch for gestures & the usual.• C++ for 3D glue code.
Shader Example: ColourLovers
I selected interesting palettes and created a texture.
Horizontal axis is the color palette. Vertical axis selects between color palettes.
At runtime this palette texture is loaded and attached to the ColourLoverShader.
EISColourLoversShader.fsh
varying!mediump vec2 v_st;
// Palette selectoruniform float paletteDial;
// Contribution of remapped coloruniform float strengthDial;
// Palettes are ganged together into a single texture.// A specific palette is selected with the paletteDialuniform sampler2D colourLoversPalettes;
// herouniform int heroChannels;uniform sampler2D hero;
void main() {!! vec4 raw = (heroChannels == 1) ? vec4(texture2D(hero, v_st).a) : texture2D(hero, v_st);!! vec3 cooked;! cooked.r = texture2D(colourLoversPalettes, vec2(raw.r, paletteDial)).r;! cooked.g = texture2D(colourLoversPalettes, vec2(raw.g, paletteDial)).g;! cooked.b = texture2D(colourLoversPalettes, vec2(raw.b, paletteDial)).b;!! gl_FragColor = vec4(mix(raw.rgb, cooked, strengthDial), raw.a);}
EISColourLoversShader.fsh
varying!mediump vec2 v_st;
// Palette selectoruniform float paletteDial;
// Contribution of remapped coloruniform float strengthDial;
// Palettes are ganged together into a single texture.// A specific palette is selected with the paletteDialuniform sampler2D colourLoversPalettes;
// herouniform int heroChannels;uniform sampler2D hero;
void main() {!! vec4 raw = (heroChannels == 1) ? vec4(texture2D(hero, v_st).a) : texture2D(hero, v_st);!! vec3 cooked;! cooked.r = texture2D(colourLoversPalettes, vec2(raw.r, paletteDial)).r;! cooked.g = texture2D(colourLoversPalettes, vec2(raw.g, paletteDial)).g;! cooked.b = texture2D(colourLoversPalettes, vec2(raw.b, paletteDial)).b;!! gl_FragColor = vec4(mix(raw.rgb, cooked, strengthDial), raw.a);}
Demo ColourLovers Shader
Hue Shift Shader
RGB HSB
Conceptually simple idea. Use one channel of a photo to select the hue of a resultant image.
Demo Hue Shift Shader
Quantize ST Shader
Beyond Photography - The Digital Darkroom by Gerard J. Holzmann
Sampling a texture at a low rate results in quantization.
Beyond Photography - The Digital Darkroom by Gerard J. Holzmann
Sampling in polar coordinates rather then cartesian is a bit more interesting.
Demo Quantize ST Shader
BurnShader
red channel = drop shadow green channel = cut out
final rgb texture
Demo BurnShader
Links
A previous meetup talk I gave on iOS OpenGL
• iOS OpenGL - http://slidesha.re/Y1MW8
Github - code• HelloGLSL - http://bit.ly/JCcMju
• EISRenderHelpful. Helpful 3D rendering glue code - http://bit.ly/JZ4HW3
Github - people to follow
• Philip Rideout - https://github.com/prideout
• Raphael Sebbe - https://github.com/rsebbe
• Brad Larson - https://github.com/BradLarson
• Jeff LaMarche - https://github.com/jlamarche
Elsewhere:
• Martins Upitis - http://devlog-martinsh.blogspot.com/• Ole Begemann - http://bit.ly/srlCBV
• Daniel Rakos - http://bit.ly/a3QATn
Thank You!
Copyright © Douglass Turner
Douglass TurnerElastic Image Softwareemail: [email protected] tweets: @duglacell: 781 775 3708