Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS Visual F/X

iOS Visual F/X

A brief introduction to the visual manipulation power of the GPU on iPhone and iPad. A peak at OpenGL, GLSL, and all that funky 3D graphics goodness.

Douglass Turner

May 23, 2012
Tweet

More Decks by Douglass Turner

Other Decks in Technology

Transcript

  1. Cocoa Touch and its realization in Objective-C is about: Abstraction.

    Pattern. Messaging. Generality. Simplicity.
  2. UIView lives in flatland ... // UIView struct 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;
  3. ... 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;
  4. As long as you are willing to remain at this

    high level of abstraction you can get a lot done using UIViewAnimation, CIImage, etc.
  5. Hello OpenGL You take the red pill – you stay

    in Wonderland and I show you how deep the rabbit-hole goes." -Morpheus
  6. 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.
  7. Shaders allow us to ignore the rest of a software

    system, freeing us to focus on achieving a specific look.
  8. 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
  9. 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);! }
  10. 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); }
  11. 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); ! }
  12. 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.
  13. 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.
  14. Demo. GLSL Powered Apps • Beautiful Panoramas. App Store: http://bit.ly/9KJBLA

    • BMW Interior. Panoramic hotspots prototype. • RadPad. iPad radiology prototype.
  15. Shader Idioms To fully “get” the power of shaders and

    their style of use it helps know the idioms guiding their use: • Multiple Passes • Iteration aka Ping/Pong • Buffers/Channels • Indirection/Remapping
  16. 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
  17. ElasticImage highlights. • Rapid shader creation & deployment • Shaders

    and gesture declared in plist • Cocoa Touch for gestures & the usual. • C++ for 3D glue code.
  18. 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.
  19. EISColourLoversShader.fsh varying! mediump vec2 v_st; // Palette selector uniform float

    paletteDial; // Contribution of remapped color uniform float strengthDial; // Palettes are ganged together into a single texture. // A specific palette is selected with the paletteDial uniform sampler2D colourLoversPalettes; // hero uniform 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); }
  20. EISColourLoversShader.fsh varying! mediump vec2 v_st; // Palette selector uniform float

    paletteDial; // Contribution of remapped color uniform float strengthDial; // Palettes are ganged together into a single texture. // A specific palette is selected with the paletteDial uniform sampler2D colourLoversPalettes; // hero uniform 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); }
  21. Conceptually simple idea. Use one channel of a photo to

    select the hue of a resultant image.
  22. Beyond Photography - The Digital Darkroom by Gerard J. Holzmann

    Sampling a texture at a low rate results in quantization.
  23. Beyond Photography - The Digital Darkroom by Gerard J. Holzmann

    Sampling in polar coordinates rather then cartesian is a bit more interesting.
  24. 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