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

Reviving the Dream of the 90s with WebGL

Billy Roh
October 04, 2019

Reviving the Dream of the 90s with WebGL

See demos on billyroh.com/screensavers.

The 90s were an exuberant time for technology. This is an attempt to bring back some of that energy by recreating 90s screensavers with WebGL and other modern web technologies.

Billy Roh

October 04, 2019
Tweet

More Decks by Billy Roh

Other Decks in Technology

Transcript

  1. View Slide

  2. Washington University
    Computer Science
    2012
    Facebook
    Product designer
    2013 – 2014
    Opendoor
    Senior product designer
    2014 – 2019

    View Slide

  3. $40,000 raised for non-profits
    through WaffleJS
    I helped start a creative coding monthly
    meetup called WaffleJS. We just had our
    4-year anniversary!

    View Slide

  4. Grew up in the 90s in
    Vancouver, Canada

    View Slide

  5. View Slide

  6. (Irrational?)

    View Slide

  7. View Slide

  8. View Slide

  9. View Slide

  10. We have given up
    in exchange for .

    View Slide

  11. The transition between this and the
    thesis is a bit rough

    Beginning of modern computing
    (Windows)… 90s -> Windows =>
    screensavers
    Pipes and maze
    Windows 95 screensavers

    View Slide

  12. View Slide

  13. Recreated using WebGL, matrix math,
    asynchronous functions, HSL, SVG paths
    In-browser recreations

    View Slide

  14. View Slide

  15. Windows 95 original

    View Slide

  16. Avoid intersections
    Matrix math
    Sequential rendering
    Asynchronous functions
    Generative palette
    HSL, material
    Dissolve and reset
    SVG paths

    View Slide

  17. Avoid intersections
    Matrix math
    Sequential rendering
    Asynchronous functions
    Generative palette
    HSL, material
    Dissolve and reset
    SVG paths

    View Slide

  18. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    visitedMatrix
    pipePath
    0 0 0 0
    0 0 0 0
    0 0 0 0
    0 0 0 0

    View Slide

  19. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 0 0
    0 0 1 0
    0 0 0 0

    View Slide

  20. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 0 0
    0 0 1 0
    0 0 0 0

    View Slide

  21. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0

    View Slide

  22. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0
    1
    1
    1
    1
    1
    1

    View Slide

  23. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0
    1
    1
    1
    1
    1
    1
    1

    View Slide

  24. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0
    1
    1
    1
    1
    1
    1
    1

    View Slide

  25. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0
    1
    1
    1
    1
    1
    1
    1
    1

    View Slide

  26. 1. Generate matrix
    2. Seed starting position
    and mark
    3. Choose unoccupied
    position and mark
    4. Repeat
    pipeMatrix
    pipePath
    0 0 0 0
    0 0 1 0
    0 0 1 0
    0 0 0 0
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1

    View Slide

  27. Avoid intersections
    Matrix math
    Sequential rendering
    Asynchronous functions
    Generative palette
    HSL, material
    Dissolve and reset
    SVG paths

    View Slide

  28. View Slide

  29. Iterate through pipePathArray to
    render each pipe

    View Slide

  30. …which immediately renders all the
    pipes at once

    View Slide

  31. Synchronous
    Everything gets rendered at once

    View Slide

  32. Promise chaining
    Endless chaining oh no

    View Slide

  33. Await/async
    Simpler, easier to understand

    View Slide

  34. View Slide

  35. Wait between each drawPipe()
    Iterate through pipePath and wait
    until drawPath is complete in
    between each iteration

    View Slide

  36. Wait between each drawSegment()
    Iterate through pipePath and wait
    until drawPath is complete in
    between each iteration

    View Slide

  37. Draw and delay
    Draw a segment of the pipe and add
    a time delay

    View Slide

  38. Asynchronous
    Pipes get rendered sequentially

    View Slide

  39. Avoid intersections
    Matrix math
    Sequential rendering
    Asynchronous functions
    Generative palette
    HSL, material
    Dissolve and reset
    SVG paths

    View Slide

  40. Dynamically generate palette
    and use semi-shiny material
    Windows 95 original

    View Slide

  41. Teapot!

    View Slide

  42. Shiny material
    Material params
    Generative palette
    HSL
    Teapot
    External asset

    View Slide

  43. View Slide

  44. Generate random colour
    Cap it to reasonable saturation and
    lightness values

    View Slide

  45. View Slide

  46. Color
    Fog
    Metalness
    Opacity
    Texture
    Wireframe
    Emissive
    Roughness
    Material can affect dozens
    of things, such as…

    View Slide

  47. Default Metalness
    0.3
    Metalness
    1.0

    View Slide

  48. Audio
    A-frame can load and
    cache external assets.
    Images 3D models

    View Slide

  49. View Slide

  50. Load asset
    Set unique ID

    View Slide

  51. View Slide

  52. Ensure only one teapot
    is rendered

    View Slide

  53. Reference unique ID
    from

    View Slide

  54. View Slide

  55. Teapot!

    View Slide

  56. Avoid intersections
    Matrix math
    Sequential rendering
    Asynchronous functions
    Generative palette
    HSL, material
    Dissolve and reset
    SVG paths

    View Slide

  57. Fade out with small black
    squares then reset
    Windows 95 original

    View Slide

  58. 1. Create grid from viewport
    2. Randomly divide up grid into groups
    3. Render each group as an SVG

    View Slide

  59. 1. Create grid from viewport
    2. Randomly divide up grid into groups
    3. Render each group as an SVG
    2 1 3 4 1 1
    2 1 3 3 4 2
    1 2 1 2 1 4
    4 1 3 1 2 3

    View Slide

  60. 1. Create grid from viewport
    2. Randomly divide up grid into groups
    3. Render each group as an SVG
    2 1 3 4 1 1
    2 1 3 3 4 2
    1 2 1 2 1 4
    4 1 3 1 2 3

    View Slide

  61. Render 1,000s of squares individually
    Cumbersome, slow to render






    View Slide

  62. Render 100s of squares at once with
    Easier to manage, faster to render



    View Slide

  63. Move Horizontal
    Vertical Z (Cloze?)

    View Slide

  64. Instantiate a string

    View Slide

  65. Use `M` to set the starting point

    View Slide

  66. Use `H` to draw a horizontal line

    View Slide

  67. Use `V` to draw a vertical line

    View Slide

  68. Use `H` to draw a horizontal line

    View Slide

  69. Use `Z` to close the shape

    View Slide

  70. Repeat for all squares in the array

    View Slide

  71. In-browser recreation

    View Slide

  72. Q: How might we make this more fun?
    A: More colours, interaction and

    View Slide

  73. View Slide

  74. View Slide

  75. View Slide

  76. Windows 95 original

    View Slide

  77. Generate the maze
    Depth-first search
    Traverse the maze
    Depth-first search
    Dynamic entities
    A-frame look-at
    Dissolve and reset
    Animation params

    View Slide

  78. Generate the maze
    Depth-first search
    Traverse the maze
    Depth-first search
    Dynamic entities
    A-frame look-at
    Dissolve and reset
    Animation params

    View Slide

  79. Source: wolfesoftware.com/maze-generator/

    View Slide

  80. View Slide

  81. Generate the maze
    Depth-first search
    Traverse the maze
    Depth-first search
    Dynamic entities
    A-frame look-at
    Dissolve and reset
    Animation params

    View Slide

  82. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  83. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  84. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  85. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  86. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  87. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  88. 1. Pick random starting position
    2. Pick an accessible, unvisited position
    3. Else, step backward

    View Slide

  89. In-browser recreation

    View Slide

  90. Generate the maze
    Depth-first search
    Traverse the maze
    Depth-first search
    Dynamic entities
    A-frame look-at
    Dissolve and reset
    Animation params

    View Slide

  91. Smiley face
    Stationary
    Resets maze
    Rat
    Traverses maze
    Has no effect
    Start button
    Spawns near camera
    Has no effect

    View Slide

  92. View Slide

  93. Enumerate all positions in maze
    Shuffle array to randomize positions

    View Slide

  94. Pop a position off the array for
    each entity to prevent collisions

    View Slide

  95. In-browser recreation

    View Slide

  96. Notice how the start button faces you, no
    matter which way you face
    Windows 95 original

    View Slide

  97. aframe-look-at-component

    View Slide

  98. View Slide

  99. In-browser recreation

    View Slide

  100. Generate the maze
    Depth-first search
    Traverse the maze
    Depth-first search
    Dynamic entities
    A-frame look-at
    Dissolve and reset
    Animation params

    View Slide

  101. Scale walls, start button, and smiley face
    up/down at the start/end
    Windows 95 original

    View Slide


  102. View Slide

  103. Source: aframe.io/examples/showcase/animation/

    View Slide

  104. Property to animate
    e.g. position, scale, rotation
    Value to animate to
    Easing
    e.g. easeInOutQuad,
    easeInOutElastic
    Animation attribute
    Can add arbitrary characters
    after “animation”

    View Slide

  105. View Slide

  106. Wrapper for entire maze

    View Slide

  107. Wrapper for thing that need to
    scale up/down
    Walls, smiley face, start button

    View Slide

  108. View Slide

  109. Scale up wallWrapper along
    the y-axis

    View Slide

  110. View Slide

  111. Scale down wallWrapper along
    the y-axis

    View Slide

  112. In-browser recreation

    View Slide

  113. Q: How might we make this more fun?
    A:

    View Slide

  114. View Slide

  115. The Metropolitan Transportation Authority ran a six-
    month, $1 million trial of the “fertility management bait” in
    subways in 2013, and said in 2017 that it would expand to
    additional stations following “promising results.”

    View Slide

  116. View Slide

  117. Q: How might we make this more fun?
    A:

    View Slide

  118. View Slide

  119. View Slide

  120. View Slide

  121. View Slide

  122. View Slide

  123. (Irrational?)

    View Slide

  124. Reject the notion that
    must be bound to .

    View Slide

  125. View Slide

  126. View Slide