bjorn vor 7 Jahren
Ursprung
Commit
8295b71740
84 geänderte Dateien mit 2518 neuen und 865 gelöschten Zeilen
  1. 647 588
      api/init.lua
  2. 14 0
      api/lovr/callbacks/conf.lua
  3. 0 19
      api/lovr/filesystem/exists.lua
  4. 1 1
      api/lovr/filesystem/mount.lua
  5. 29 0
      api/lovr/graphics/Animator/getAlpha.lua
  6. 15 0
      api/lovr/graphics/Animator/getAnimationCount.lua
  7. 31 0
      api/lovr/graphics/Animator/getAnimationNames.lua
  8. 22 0
      api/lovr/graphics/Animator/getDuration.lua
  9. 33 0
      api/lovr/graphics/Animator/getPriority.lua
  10. 28 0
      api/lovr/graphics/Animator/getSpeed.lua
  11. 28 0
      api/lovr/graphics/Animator/init.lua
  12. 18 0
      api/lovr/graphics/Animator/isLooping.lua
  13. 18 0
      api/lovr/graphics/Animator/isPlaying.lua
  14. 19 0
      api/lovr/graphics/Animator/pause.lua
  15. 21 0
      api/lovr/graphics/Animator/play.lua
  16. 11 0
      api/lovr/graphics/Animator/reset.lua
  17. 21 0
      api/lovr/graphics/Animator/resume.lua
  18. 28 0
      api/lovr/graphics/Animator/seek.lua
  19. 28 0
      api/lovr/graphics/Animator/setAlpha.lua
  20. 17 0
      api/lovr/graphics/Animator/setLooping.lua
  21. 32 0
      api/lovr/graphics/Animator/setPriority.lua
  22. 27 0
      api/lovr/graphics/Animator/setSpeed.lua
  23. 20 0
      api/lovr/graphics/Animator/stop.lua
  24. 23 0
      api/lovr/graphics/Animator/tell.lua
  25. 12 0
      api/lovr/graphics/Animator/update.lua
  26. 20 0
      api/lovr/graphics/ArcMode.lua
  27. 42 0
      api/lovr/graphics/Material/getColor.lua
  28. 25 0
      api/lovr/graphics/Material/getTexture.lua
  29. 9 0
      api/lovr/graphics/Material/init.lua
  30. 47 0
      api/lovr/graphics/Material/setColor.lua
  31. 33 0
      api/lovr/graphics/Material/setTexture.lua
  32. 16 0
      api/lovr/graphics/MaterialColor.lua
  33. 20 0
      api/lovr/graphics/MaterialTexture.lua
  34. 76 0
      api/lovr/graphics/Mesh/drawInstanced.lua
  35. 12 0
      api/lovr/graphics/Mesh/getMaterial.lua
  36. 0 12
      api/lovr/graphics/Mesh/getTexture.lua
  37. 1 0
      api/lovr/graphics/Mesh/init.lua
  38. 15 0
      api/lovr/graphics/Mesh/setMaterial.lua
  39. 0 12
      api/lovr/graphics/Mesh/setTexture.lua
  40. 14 0
      api/lovr/graphics/MeshDrawMode.lua
  41. 75 0
      api/lovr/graphics/Model/drawInstanced.lua
  42. 18 0
      api/lovr/graphics/Model/getAnimator.lua
  43. 12 0
      api/lovr/graphics/Model/getMaterial.lua
  44. 15 0
      api/lovr/graphics/Model/getMesh.lua
  45. 0 12
      api/lovr/graphics/Model/getTexture.lua
  46. 2 1
      api/lovr/graphics/Model/init.lua
  47. 18 0
      api/lovr/graphics/Model/setAnimator.lua
  48. 17 0
      api/lovr/graphics/Model/setMaterial.lua
  49. 0 12
      api/lovr/graphics/Model/setTexture.lua
  50. 22 0
      api/lovr/graphics/Shader/hasUniform.lua
  51. 11 2
      api/lovr/graphics/Shader/init.lua
  52. 2 1
      api/lovr/graphics/Shader/send.lua
  53. 0 31
      api/lovr/graphics/Skybox/draw.lua
  54. 0 35
      api/lovr/graphics/Skybox/init.lua
  55. 2 2
      api/lovr/graphics/Texture/init.lua
  56. 121 0
      api/lovr/graphics/arc.lua
  57. 5 5
      api/lovr/graphics/box.lua
  58. 82 0
      api/lovr/graphics/circle.lua
  59. 5 5
      api/lovr/graphics/cube.lua
  60. 1 1
      api/lovr/graphics/getBackgroundColor.lua
  61. 2 2
      api/lovr/graphics/getColor.lua
  62. 24 0
      api/lovr/graphics/isGammaCorrect.lua
  63. 25 0
      api/lovr/graphics/newAnimator.lua
  64. 55 0
      api/lovr/graphics/newMaterial.lua
  65. 6 9
      api/lovr/graphics/newModel.lua
  66. 0 60
      api/lovr/graphics/newSkybox.lua
  67. 62 3
      api/lovr/graphics/newTexture.lua
  68. 7 3
      api/lovr/graphics/plane.lua
  69. 2 2
      api/lovr/graphics/setBackgroundColor.lua
  70. 3 3
      api/lovr/graphics/setColor.lua
  71. 56 0
      api/lovr/graphics/skybox.lua
  72. 24 20
      api/lovr/graphics/triangle.lua
  73. 71 0
      api/lovr/math/Transform/getMatrix.lua
  74. 86 0
      api/lovr/math/Transform/setMatrix.lua
  75. 64 0
      api/lovr/math/gammaToLinear.lua
  76. 64 0
      api/lovr/math/linearToGamma.lua
  77. 63 0
      api/lovr/math/orientationToDirection.lua
  78. 1 0
      examples/Lighting/conf.lua
  79. 0 1
      examples/Lighting/main.lua
  80. 2 2
      examples/Panorama/main.lua
  81. 3 3
      examples/Physics/main.lua
  82. 11 11
      examples/Primitives/main.lua
  83. 6 6
      guides/Callbacks_and_Modules.md
  84. 0 1
      guides/Libraries.md

Datei-Diff unterdrückt, da er zu groß ist
+ 647 - 588
api/init.lua


+ 14 - 0
api/lovr/callbacks/conf.lua

@@ -22,6 +22,11 @@ return {
           type = 'table',
           description = 'Configuration for the headset.',
           table = {
+            {
+              name = 'drivers',
+              type = 'table',
+              description = 'An ordered list of preferred headset drivers.'
+            },
             {
               name = 'mirrored',
               type = 'boolean',
@@ -83,6 +88,11 @@ return {
             }
           }
         },
+        {
+          name = 'gammacorrect',
+          type = 'boolean',
+          description = 'Whether colors are gamma corrected.'
+        },
         {
           name = 'window',
           type = 'table',
@@ -148,6 +158,7 @@ return {
           t.identity = 'default'
 
           -- Headset settings
+          t.headset.drivers = { 'openvr', 'webvr', 'fake' }
           t.headset.mirror = true
           t.headset.offset = 1.7
 
@@ -160,6 +171,9 @@ return {
           t.modules.physics = true
           t.modules.timer = true
 
+          -- Configure gamma correction
+          t.gammacorrect = false
+
           -- Configure the desktop window
           t.window.width = 800
           t.window.height = 600

+ 0 - 19
api/lovr/filesystem/exists.lua

@@ -1,19 +0,0 @@
-return {
-  summary = 'Check whether a file exists.',
-  description = 'Determine if a file exists.',
-  arguments = {
-    {
-      name = 'path',
-      type = 'string',
-      description = 'The path to check.'
-    }
-  },
-  returns = {
-    {
-      name = 'exists',
-      type = 'boolean',
-      description = 'Whether the path is a file or directory.'
-    }
-  },
-  notes = 'This function checks both the source directory and the save directory.'
-}

+ 1 - 1
api/lovr/filesystem/mount.lua

@@ -34,7 +34,7 @@ return {
     description = 'Mount `data.zip` with a file `images/background.png`:',
     code = [[
       lovr.filesystem.mount('data.zip', 'assets')
-      print(lovr.filesystem.exists('assets/images/background.png')) -- true
+      print(lovr.filesystem.isFile('assets/images/background.png')) -- true
     ]]
   },
   related = {

+ 29 - 0
api/lovr/graphics/Animator/getAlpha.lua

@@ -0,0 +1,29 @@
+return {
+  summary = 'Get the alpha (weight) of an animation.',
+  description = 'Returns the current alpha factor of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'alpha',
+      type = 'number',
+      description = 'The alpha of the animation.'
+    }
+  },
+  notes = [[
+    The alpha is a number between 0 and 1 indicating how the animation's pose is blended with other
+    animations.  An alpha of 1 means the animation's pose will completely overwrite the existing
+    pose, whereas an alpha of .5 would blend half of the animation's pose with half of the existing
+    pose.  This, combined with the animation's priority, allows for fine grained control over how
+    multiple playing animations get blended together.
+  ]],
+  related = {
+    'Animator:getPriority',
+    'Animator:setPriority'
+  }
+}

+ 15 - 0
api/lovr/graphics/Animator/getAnimationCount.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Get the number of animations the Animator can play.',
+  description = 'Returns the number of animations the Animator can play.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of animations.'
+    }
+  },
+  related = {
+    'Animator:getAnimationNames'
+  }
+}

+ 31 - 0
api/lovr/graphics/Animator/getAnimationNames.lua

@@ -0,0 +1,31 @@
+return {
+  summary = 'Get the a table containing all animation names.',
+  description = [[
+    Returns a table containing the names of all animations supported by this Animator.
+  ]],
+  arguments = {
+    t = {
+      type = 'table',
+      description = 'A table to fill with the animation names.'
+    }
+  },
+  returns = {
+    names = {
+      type = 'table',
+      description = 'The list of animation names as strings.'
+    }
+  },
+  variants = {
+    {
+      arguments = {},
+      returns = { 'names' }
+    },
+    {
+      arguments = { 't' },
+      returns = {}
+    }
+  },
+  related = {
+    'Animator:getAnimationCount'
+  }
+}

+ 22 - 0
api/lovr/graphics/Animator/getDuration.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get the duration of an animation.',
+  description = 'Returns the duration of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'duration',
+      type = 'number',
+      description = 'The duration of the animation at its normal speed, in seconds.'
+    }
+  },
+  related = {
+    'Animator:seek',
+    'Animator:tell'
+  }
+}

+ 33 - 0
api/lovr/graphics/Animator/getPriority.lua

@@ -0,0 +1,33 @@
+return {
+  summary = 'Get the priority of an animation, used for mixing.',
+  description = 'Returns the priority of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'priority',
+      type = 'number',
+      description = 'The priority of the animation.'
+    }
+  },
+  notes = [[
+    The priority controls the order that multiple playing animations get blended together.
+    Animations with a lower priority will get applied first, and animations with higher priority
+    will get layered on top afterwards.  If two or more animations have the same priority, they
+    could get applied in any order.  All animations start with a priority of 1.
+
+    You can use priority and alpha to control how different animations blend together.  For
+    instance, if you have a character with "throw" and "walk" animations and both of them key the
+    bones in the arm, you could have the character walk and throw at the same time by giving the
+    "throw" animation a higher priority and playing it over the walk animation.
+  ]],
+  related = {
+    'Animator:getAlpha',
+    'Animator:setAlpha'
+  }
+}

+ 28 - 0
api/lovr/graphics/Animator/getSpeed.lua

@@ -0,0 +1,28 @@
+return {
+  summary = 'Get the speed of an animation.',
+  description = 'Returns the speed factor for an animation or the Animator\'s global speed factor.',
+  arguments = {
+    name = {
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    speed = {
+      type = 'number',
+      description = 'The current speed multiplier.'
+    }
+  },
+  variants = {
+    {
+      description = 'Get the speed of a specific animation.',
+      arguments = { 'name' },
+      returns = { 'speed' }
+    },
+    {
+      description = 'Get the global speed multiplier for the Animator.',
+      arguments = {},
+      returns = { 'speed' }
+    }
+  }
+}

+ 28 - 0
api/lovr/graphics/Animator/init.lua

@@ -0,0 +1,28 @@
+return {
+  summary = 'An object that plays and mixes animations.',
+  description = [[
+    An animator is an object that controls the playback of skeletal animations.  Animators can be
+    attached to models using `Model:setAnimator`.  Once attached, the Model will render using the
+    animator's pose instead of the default pose.  Don't forget to update the animator in
+    `lovr.update` using `Animator:update`!
+  ]],
+  constructors = {
+    'lovr.graphics.newAnimator'
+  },
+  example = [[
+    function lovr.load()
+      model = lovr.graphics.newModel('model.fbx')
+      animator = lovr.graphics.newAnimator(model)
+      animator:play(animator:getAnimationNames()[1])
+      model:setAnimator(animator)
+    end
+
+    function lovr.update(dt)
+      animator:update(dt)
+    end
+
+    function lovr.draw()
+      model:draw()
+    end
+  ]]
+}

+ 18 - 0
api/lovr/graphics/Animator/isLooping.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Check if an animation is looping.',
+  description = 'Returns whether an animation is looping.',
+  arguments = {
+    {
+      name = 'animation',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'looping',
+      type = 'boolean',
+      description = 'Whether or not the animation is looping.'
+    }
+  }
+}

+ 18 - 0
api/lovr/graphics/Animator/isPlaying.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Check if an animation is playing.',
+  description = 'Returns whether an animation is currently playing.',
+  arguments = {
+    {
+      name = 'animation',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'playing',
+      type = 'boolean',
+      description = 'Whether or not the animation is playing.'
+    }
+  }
+}

+ 19 - 0
api/lovr/graphics/Animator/pause.lua

@@ -0,0 +1,19 @@
+return {
+  summary = 'Pause an animation.',
+  description = 'Pauses an animation.  This will stop the animation without resetting its time.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The animation to pause.'
+    }
+  },
+  returns = {},
+  related = {
+    'Animator:play',
+    'Animator:stop',
+    'Animator:resume',
+    'Animator:isPlaying',
+    'Animator:getAnimationNames'
+  }
+}

+ 21 - 0
api/lovr/graphics/Animator/play.lua

@@ -0,0 +1,21 @@
+return {
+  summary = 'Start playing an animation.',
+  description = [[
+    Plays an animation.  If the animation is already playing, it will start over at the beginning.
+  ]],
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation to play.'
+    }
+  },
+  returns = {},
+  related = {
+    'Animator:stop',
+    'Animator:pause',
+    'Animator:resume',
+    'Animator:isPlaying',
+    'Animator:getAnimationNames'
+  }
+}

+ 11 - 0
api/lovr/graphics/Animator/reset.lua

@@ -0,0 +1,11 @@
+return {
+  summary = 'Stop all animations.',
+  description = [[
+    Resets the Animator to its initial state. All animations will be stopped, their speed will be
+    reset to `1.0`, their looping state will be reset, and the Animator's global speed will be reset
+    to `1.0`.
+  ]],
+  arguments = {},
+  returns = {},
+  related = {}
+}

+ 21 - 0
api/lovr/graphics/Animator/resume.lua

@@ -0,0 +1,21 @@
+return {
+  summary = 'Resume a paused animation.',
+  description = [[
+    Resumes an animation. This will play an animation without starting it over at the beginning.
+  ]],
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The animation to resume.'
+    }
+  },
+  returns = {},
+  related = {
+    'Animator:pause',
+    'Animator:play',
+    'Animator:stop',
+    'Animator:isPlaying',
+    'Animator:getAnimationNames'
+  }
+}

+ 28 - 0
api/lovr/graphics/Animator/seek.lua

@@ -0,0 +1,28 @@
+return {
+  summary = 'Seek to a specific time in an animation.',
+  description = 'Seeks to a specific time in an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation to seek.'
+    },
+    {
+      name = 'time',
+      type = 'number',
+      description = 'The time to seek to, in seconds.'
+    }
+  },
+  returns = {},
+  notes = [[
+    If the time is greater than the duration of the animation, the animation will stop if it isn't
+    currently looping.  Negative time values are supported for animations (regardless of looping
+    state) and will seek backwards from the animation's end time.
+
+    Seeking an animation does not stop or play the animation.
+  ]],
+  related = {
+    'Animator:tell',
+    'Animator:getDuration'
+  }
+}

+ 28 - 0
api/lovr/graphics/Animator/setAlpha.lua

@@ -0,0 +1,28 @@
+return {
+  summary = 'Set the alpha (weight) of an animation.',
+  description = 'Sets the current alpha factor of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    },
+    {
+      name = 'alpha',
+      type = 'number',
+      description = 'The alpha of the animation.'
+    }
+  },
+  returns = {},
+  notes = [[
+    The alpha is a number between 0 and 1 indicating how the animation's pose is blended with other
+    animations.  An alpha of 1 means the animation's pose will completely overwrite the existing
+    pose, whereas an alpha of .5 would blend half of the animation's pose with half of the existing
+    pose.  This, combined with the animation's priority, allows for fine grained control over how
+    multiple playing animations get blended together.
+  ]],
+  related = {
+    'Animator:getPriority',
+    'Animator:setPriority'
+  }
+}

+ 17 - 0
api/lovr/graphics/Animator/setLooping.lua

@@ -0,0 +1,17 @@
+return {
+  summary = 'Set whether an animation should loop.',
+  description = 'Sets whether an animation loops.',
+  arguments = {
+    {
+      name = 'animation',
+      type = 'string',
+      description = 'The name of the animation.'
+    },
+    {
+      name = 'loop',
+      type = 'boolean',
+      description = 'Whether the animation should loop.'
+    }
+  },
+  returns = {}
+}

+ 32 - 0
api/lovr/graphics/Animator/setPriority.lua

@@ -0,0 +1,32 @@
+return {
+  summary = 'Set the priority of an animation, used for mixing.',
+  description = 'Sets the priority of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    },
+    {
+      name = 'priority',
+      type = 'number',
+      description = 'The new priority for the animation.'
+    }
+  },
+  returns = {},
+  notes = [[
+    The priority controls the order that multiple playing animations get blended together.
+    Animations with a lower priority will get applied first, and animations with higher priority
+    will get layered on top afterwards.  If two or more animations have the same priority, they
+    could get applied in any order.  All animations start with a priority of 1.
+
+    You can use priority and alpha to control how different animations blend together.  For
+    instance, if you have a character with "throw" and "walk" animations and both of them key the
+    bones in the arm, you could have the character walk and throw at the same time by giving the
+    "throw" animation a higher priority and playing it over the walk animation.
+  ]],
+  related = {
+    'Animator:getAlpha',
+    'Animator:setAlpha'
+  }
+}

+ 27 - 0
api/lovr/graphics/Animator/setSpeed.lua

@@ -0,0 +1,27 @@
+return {
+  summary = 'Set the speed of an animation.',
+  description = 'Sets the speed factor for an animation or the Animator\'s global speed factor.',
+  arguments = {
+    name = {
+      type = 'string',
+      description = 'The name of the animation.'
+    },
+    speed = {
+      type = 'number',
+      description = 'The new speed multiplier.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      description = 'Set the speed of a specific animation.',
+      arguments = { 'name', 'speed' },
+      returns = {}
+    },
+    {
+      description = 'Set the global speed multiplier for the Animator.',
+      arguments = { 'speed' },
+      returns = {}
+    }
+  }
+}

+ 20 - 0
api/lovr/graphics/Animator/stop.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Stop an animation.',
+  description = 'Stops an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The animation to stop.'
+    }
+  },
+  returns = {},
+  related = {
+    'Animator:play',
+    'Animator:reset',
+    'Animator:pause',
+    'Animator:resume',
+    'Animator:isPlaying',
+    'Animator:getAnimationNames'
+  }
+}

+ 23 - 0
api/lovr/graphics/Animator/tell.lua

@@ -0,0 +1,23 @@
+return {
+  summary = 'Get the current time of an animation.',
+  description = 'Returns the current playback time of an animation.',
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'time',
+      type = 'number',
+      description = 'The current time the animation is at, in seconds.'
+    }
+  },
+  notes = 'This will always be between 0 and the animation\'s duration.',
+  related = {
+    'Animator:seek',
+    'Animator:getDuration'
+  }
+}

+ 12 - 0
api/lovr/graphics/Animator/update.lua

@@ -0,0 +1,12 @@
+return {
+  summary = 'Advance the Animator\'s clock.',
+  description = 'Updates the Animator\'s clock, advancing all playing animations by the time step.',
+  arguments = {
+    {
+      name = 'dt',
+      type = 'number',
+      description = 'The amount of time to advance.'
+    }
+  },
+  returns = {}
+}

+ 20 - 0
api/lovr/graphics/ArcMode.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Different ways arcs can be drawn.',
+  description = 'Different ways arcs can be drawn with `lovr.graphics.arc`.',
+  values = {
+    {
+      name = 'pie',
+      description = [[
+        The arc is drawn with the center of its circle included in the list of points (default).
+      ]]
+    },
+    {
+      name = 'open',
+      description = 'The curve of the arc is drawn as a single line.'
+    },
+    {
+      name = 'closed',
+      description = 'The starting and ending points of the arc\'s curve are connected.'
+    }
+  }
+}

+ 42 - 0
api/lovr/graphics/Material/getColor.lua

@@ -0,0 +1,42 @@
+return {
+  summary = 'Get a color property of the Material.',
+  description = [[
+    Returns a color property for a Material.  Different types of colors are supported for different
+    lighting parameters.  Colors default to white and are gamma corrected as necessary, see
+    `lovr.graphics.isGammaCorrect` for more info on that.
+  ]],
+  arguments = {
+    {
+      name = 'colorType',
+      type = 'MaterialColor',
+      default = [['diffuse']],
+      description = 'The type of color to get.'
+    }
+  },
+  returns = {
+    {
+      name = 'r',
+      type = 'number',
+      description = 'The red component of the color.'
+    },
+    {
+      name = 'g',
+      type = 'number',
+      description = 'The green component of the color.'
+    },
+    {
+      name = 'b',
+      type = 'number',
+      description = 'The blue component of the color.'
+    },
+    {
+      name = 'a',
+      type = 'number',
+      description = 'The alpha component of the color.'
+    }
+  },
+  related = {
+    'MaterialColor',
+    'lovr.graphics.setColor'
+  }
+}

+ 25 - 0
api/lovr/graphics/Material/getTexture.lua

@@ -0,0 +1,25 @@
+return {
+  summary = 'Get a texture for the Material.',
+  description = [[
+    Returns a texture for a Material.  Different types of textures are supported for different
+    lighting parameters.  If unset, textures default to a blank white texture.
+  ]],
+  arguments = {
+    {
+      name = 'textureType',
+      type = 'MaterialTexture',
+      default = [['diffuse']],
+      description = 'The type of texture to get.'
+    }
+  },
+  returns = {
+    {
+      name = 'texture',
+      type = 'Texture',
+      description = 'The texture that is set, or nil if no texture is set.'
+    }
+  },
+  related = {
+    'MaterialTexture'
+  }
+}

+ 9 - 0
api/lovr/graphics/Material/init.lua

@@ -0,0 +1,9 @@
+return {
+  summary = 'An object that controls texturing and shading.',
+  description = [[
+    A Material is an object used to control how objects appear, through coloring, texturing, and
+    shading.  The Material itself holds sets of colors, textures, and other parameters that are made
+    available to Shaders.
+  ]],
+  constructor = 'lovr.graphics.newMaterial'
+}

+ 47 - 0
api/lovr/graphics/Material/setColor.lua

@@ -0,0 +1,47 @@
+return {
+  summary = 'Set a color property of the Material.',
+  description = [[
+    Sets a color property for a Material.  Different types of colors are supported for different
+    lighting parameters.  Color channels should be from 0.0 to 1.0. Colors default to white and are
+    gamma corrected as necessary, see `lovr.graphics.isGammaCorrect` for more info on that.
+  ]],
+  arguments = {
+    colorType = {
+      type = 'MaterialColor',
+      default = [['diffuse']],
+      description = 'The type of color to get.'
+    },
+    r = {
+      type = 'number',
+      description = 'The red component of the color.'
+    },
+    g = {
+      type = 'number',
+      description = 'The green component of the color.'
+    },
+    b = {
+      type = 'number',
+      description = 'The blue component of the color.'
+    },
+    a = {
+      type = 'number',
+      default = '1.0',
+      description = 'The alpha component of the color.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'colorType', 'r', 'g', 'b', 'a' },
+      returns = {}
+    },
+    {
+      arguments = { 'r', 'g', 'b', 'a' },
+      returns = {}
+    }
+  },
+  related = {
+    'MaterialColor',
+    'lovr.graphics.setColor'
+  }
+}

+ 33 - 0
api/lovr/graphics/Material/setTexture.lua

@@ -0,0 +1,33 @@
+return {
+  summary = 'Set a texture for the Material.',
+  description = [[
+    Sets a texture for a Material.  Different types of textures are supported for different
+    lighting parameters.  If set to `nil`, textures default to a blank white texture.
+  ]],
+  arguments = {
+    textureType = {
+      type = 'MaterialTexture',
+      default = [['diffuse']],
+      description = 'The type of texture to get.'
+    },
+    texture = {
+      type = 'Texture',
+      description = 'The texture to apply, or nil to use the default.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'textureType', 'texture' },
+      returns = {}
+    },
+    {
+      arguments = { 'texture' },
+      returns = {}
+    }
+  },
+  related = {
+    'MaterialTexture',
+    'lovr.graphics.newTexture'
+  }
+}

+ 16 - 0
api/lovr/graphics/MaterialColor.lua

@@ -0,0 +1,16 @@
+return {
+  summary = 'Different material color parameters.',
+  description = 'The different types of color parameters `Material`s can hold.',
+  values = {
+    {
+      name = 'diffuse',
+      description = 'The diffuse color.'
+    }
+  },
+  related = {
+    'Material:getColor',
+    'Material:setColor',
+    'MaterialTexture',
+    'Material'
+  }
+}

+ 20 - 0
api/lovr/graphics/MaterialTexture.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Different material texture parameters.',
+  description = 'The different types of texture parameters `Material`s can hold.',
+  values = {
+    {
+      name = 'diffuse',
+      description = 'The diffuse texture.'
+    },
+    {
+      name = 'environment',
+      description = 'The environment map, should be specified as a cubemap texture.'
+    }
+  },
+  related = {
+    'Material:getTexture',
+    'Material:setTexture',
+    'MaterialColor',
+    'Material'
+  }
+}

+ 76 - 0
api/lovr/graphics/Mesh/drawInstanced.lua

@@ -0,0 +1,76 @@
+return {
+  summary = 'Draw multiple copies of the Mesh in an optimized way.',
+  description = [[
+    Draw a Mesh multiple times.  This is much faster than calling `Mesh:draw` more than once.
+  ]],
+  arguments = {
+    instances = {
+      type = 'number',
+      default = '1',
+      description = 'The number of copies of the mesh to draw.'
+    },
+    x = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate to draw the Mesh at.'
+    },
+    y = {
+      type = 'number',
+      default = '0',
+      description = 'The y coordinate to draw the Mesh at.'
+    },
+    z = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate to draw the Mesh at.'
+    },
+    scale = {
+      type = 'number',
+      default = '1',
+      description = 'The scale to draw the Mesh at.'
+    },
+    angle = {
+      type = 'number',
+      default = '0',
+      description = 'The angle to rotate the Mesh around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      default = '0',
+      description = 'The x component of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      default = '1',
+      description = 'The y component of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      default = '0',
+      description = 'The z component of the axis of rotation.'
+    },
+    transform = {
+      type = 'Transform',
+      description = 'The transform to apply before drawing.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'instances', 'x', 'y', 'z', 'scale', 'angle', 'ax', 'ay', 'az' },
+      returns = {}
+    },
+    {
+      arguments = { 'instances', 'transform' },
+      returns = {}
+    }
+  },
+  notes = [[
+    By default, the Meshes will all be drawn on top of each other.  To get the drawn copies to
+    appear in different places, you can use the `gl_InstanceID` variable in a `Shader`.  The first
+    instance will pass 0 as the instance ID, the second instance will pass 1 as the instance ID,
+    etc.  You can use an array of mat4 variables and access the array using the supplied instance ID
+    to specify a list of positions to draw the instances at, or use custom logic to position each
+    instance.
+  ]]
+}

+ 12 - 0
api/lovr/graphics/Mesh/getMaterial.lua

@@ -0,0 +1,12 @@
+return {
+  summary = 'Get the Material applied to the Mesh.',
+  description = 'Get the Material applied to the Mesh.',
+  arguments = {},
+  returns = {
+    {
+      name = 'material',
+      type = 'Material',
+      description = 'The current material applied to the Mesh.'
+    }
+  }
+}

+ 0 - 12
api/lovr/graphics/Mesh/getTexture.lua

@@ -1,12 +0,0 @@
-return {
-  summary = 'Get the Texture applied to the Mesh.',
-  description = 'Get the Texture applied to the Mesh.',
-  arguments = {},
-  returns = {
-    {
-      name = 'texture',
-      type = 'Texture',
-      description = 'The current texture applied to the Mesh.'
-    }
-  }
-}

+ 1 - 0
api/lovr/graphics/Mesh/init.lua

@@ -38,6 +38,7 @@ return {
           { 'lovrPosition', 'float', 3 },
           { 'lovrNormal',   'float', 3 },
           { 'lovrTexCoord', 'float', 2 }
+          { 'lovrVertexColor', 'byte', 4 }
         }
 
     Great, so why do we go through the trouble of naming everything in our vertex and saying what

+ 15 - 0
api/lovr/graphics/Mesh/setMaterial.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Apply a Material to the Mesh.',
+  description = [[
+    Applies a Material to the Mesh.  This will cause it to use the Material's properties whenever it
+    is rendered.
+  ]],
+  arguments = {
+    {
+      name = 'material',
+      type = 'Material',
+      description = 'The Material to apply.'
+    }
+  },
+  returns = {}
+}

+ 0 - 12
api/lovr/graphics/Mesh/setTexture.lua

@@ -1,12 +0,0 @@
-return {
-  summary = 'Apply a Texture to the Mesh.',
-  description = 'Applies a Texture to the Mesh.',
-  arguments = {
-    {
-      name = 'texture',
-      type = 'Texture',
-      description = 'The new texture.'
-    }
-  },
-  returns = {}
-}

+ 14 - 0
api/lovr/graphics/MeshDrawMode.lua

@@ -9,6 +9,20 @@ return {
       name = 'points',
       description = 'Draw each vertex as a single point.'
     },
+    {
+      name = 'lines',
+      description = [[
+        The vertices represent a list of line segments. Each pair of vertices will have a line drawn
+        between them.
+      ]]
+    },
+    {
+      name = 'linestrip',
+      description = [[
+        The first two vertices have a line drawn between them, and each vertex after that will be
+        connected to the previous vertex with a line.
+      ]]
+    },
     {
       name = 'strip',
       description = [[

+ 75 - 0
api/lovr/graphics/Model/drawInstanced.lua

@@ -0,0 +1,75 @@
+return {
+  summary = 'Draw multiple copies of a Model in an optimized way.',
+  description = [[
+    Draws a model multiple times.  This is much faster than drawing `Model:draw` more than once.
+  ]],
+  arguments = {
+    instances = {
+      type = 'number',
+      default = '1',
+      description = 'The number of copies to draw.'
+    },
+    x = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate to draw the Model at.'
+    },
+    y = {
+      type = 'number',
+      default = '0',
+      description = 'The y coordinate to draw the Model at.'
+    },
+    z = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate to draw the Model at.'
+    },
+    scale = {
+      type = 'number',
+      default = '1',
+      description = 'The scale to draw the Model at.'
+    },
+    angle = {
+      type = 'number',
+      default = '0',
+      description = 'The angle to rotate the Model around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      default = '0',
+      description = 'The x component of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      default = '1',
+      description = 'The y component of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      default = '0',
+      description = 'The z component of the axis of rotation.'
+    },
+    transform = {
+      type = 'Transform',
+      description = 'The transform to apply before drawing.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'instances', 'x', 'y', 'z', 'scale', 'angle', 'ax', 'ay', 'az' },
+      returns = {}
+    },
+    {
+      arguments = { 'instances', 'transform' },
+      returns = {}
+    }
+  },
+  notes = [[
+    By default, the Models will all be drawn on top of each other.  To get the drawn copies to
+    appear in different places, you can use the `gl_InstanceID` variable in a `Shader`.  The first
+    instance will pass 0 as the instance ID, the second instance will pass 1 as the instance ID,
+    etc.  You can use an array of mat4 variables and access the array using the supplied instance ID
+    to specify a list of positions to draw the instances at.
+  ]]
+}

+ 18 - 0
api/lovr/graphics/Model/getAnimator.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Get the Animator attached to the Model.',
+  description = [[
+    Returns the `Animator` attached to the Model.  When attached, the animator will alter the pose
+    of the bones of the model based on the set of playing animations.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'animator',
+      type = 'Animator',
+      description = 'The Animator attached to the Model, or nil if none is set.'
+    }
+  },
+  related = {
+    'lovr.graphics.newAnimator'
+  }
+}

+ 12 - 0
api/lovr/graphics/Model/getMaterial.lua

@@ -0,0 +1,12 @@
+return {
+  summary = 'Get the Material applied to the Model.',
+  description = 'Returns the Material applied to the Model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'material',
+      type = 'Material',
+      description = 'The current material applied to the Model.'
+    }
+  }
+}

+ 15 - 0
api/lovr/graphics/Model/getMesh.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Get the Model\'s underlying Mesh object.',
+  description = 'Returns the underlying `Mesh` object for the Model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'mesh',
+      type = 'Mesh',
+      description = 'The Mesh object for the model, containing all of the raw vertex data.'
+    }
+  },
+  related = {
+    'Mesh'
+  }
+}

+ 0 - 12
api/lovr/graphics/Model/getTexture.lua

@@ -1,12 +0,0 @@
-return {
-  summary = 'Get the Texture applied to the Model.',
-  description = 'Get the Texture applied to the Model.',
-  arguments = {},
-  returns = {
-    {
-      name = 'texture',
-      type = 'Texture',
-      description = 'The current texture applied to the Model.'
-    }
-  }
-}

+ 2 - 1
api/lovr/graphics/Model/init.lua

@@ -2,7 +2,8 @@ return {
   summary = 'An asset imported from a 3D model file.',
   description = [[
     A Model is a drawable object loaded from a 3D file format.  The supported 3D file formats are
-    `obj`, `fbx`, and collada.  Models will use normals and texture coordinates, if provided.
+    `obj`, `fbx`, `gltf`, and collada.  Models will use normals and texture coordinates, if
+    provided.
 
     The following advanced features are not supported yet: animations, materials, and vertex colors.
   ]],

+ 18 - 0
api/lovr/graphics/Model/setAnimator.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Attach an Animator to the Model.',
+  description = [[
+    Attaches an `Animator` to the Model.  When attached, the animator will alter the pose of the bones
+    of the model based on the set of playing animations.
+  ]],
+  arguments = {
+    {
+      name = 'animator',
+      type = 'Animator',
+      description = 'The Animator to attach.'
+    }
+  },
+  returns = {},
+  related = {
+    'lovr.graphics.newAnimator'
+  }
+}

+ 17 - 0
api/lovr/graphics/Model/setMaterial.lua

@@ -0,0 +1,17 @@
+return {
+  summary = 'Apply a Material to the Model.',
+  description = 'Applies a Material to the Model.',
+  arguments = {
+    {
+      name = 'material',
+      type = 'Material',
+      description = 'The material to apply to the Model.'
+    }
+  },
+  returns = {},
+  notes = [[
+    A model's Material will be used when drawing every part of the model.  It will override any
+    materials included in the model file.  It isn't currently possible to apply multiple materials
+    to different pieces of the Model.
+  ]]
+}

+ 0 - 12
api/lovr/graphics/Model/setTexture.lua

@@ -1,12 +0,0 @@
-return {
-  summary = 'Apply a Texture to the Model.',
-  description = 'Apply a Texture to the Model.',
-  arguments = {
-    {
-      name = 'texture',
-      type = 'Texture',
-      description = 'The texture to apply to the Model.'
-    }
-  },
-  returns = {}
-}

+ 22 - 0
api/lovr/graphics/Shader/hasUniform.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Check if a Shader has a uniform variable.',
+  description = 'Returns whether a Shader has a particular uniform variable.',
+  arguments = {
+    {
+      name = 'uniform',
+      type = 'string',
+      description = 'The name of the uniform variable.'
+    }
+  },
+  returns = {
+    {
+      name = 'present',
+      type = 'boolean',
+      description = 'Whether the shader has the specified uniform.'
+    }
+  },
+  notes = [[
+    If a uniform variable is defined but unused in the shader, the shader compiler will optimize it
+    out and the uniform will not report itself as present.
+  ]]
+}

+ 11 - 2
api/lovr/graphics/Shader/init.lua

@@ -18,7 +18,7 @@ return {
     The default fragment shader:
 
         vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) {
-          return graphicsColor * texture(image, uv);
+          return graphicsColor * lovrDiffuseColor * vertexColor * texture(image, uv);
         }
 
     Additionally, the following headers are prepended to the shader source, giving you convenient
@@ -31,16 +31,25 @@ return {
         uniform mat4 lovrTransform;
         uniform mat4 lovrNormalMatrix;
         uniform mat4 lovrProjection;
+        uniform float lovrPointSize;
+        uniform mat4 lovrPose[48];
         in vec3 lovrPosition;
         in vec3 lovrNormal;
         in vec2 lovrTexCoord;
+        in vec4 lovrVertexColor;
+        in ivec4 lovrBones;
+        in vec4 lovrBoneWeights;
         out vec2 texCoord;
+        out vec4 vertexColor;
 
     Fragment shader header:
 
         uniform vec4 lovrColor;
-        uniform sampler2D lovrTexture;
+        uniform vec4 lovrDiffuseColor;
+        uniform sampler2D lovrDiffuseTexture;
+        uniform samplerCube lovrEnvironmentTexture;
         in vec2 texCoord;
+        in vec4 vertexColor;
         in vec4 gl_FragCoord;
         out vec4 lovrFragColor;
   ]],

+ 2 - 1
api/lovr/graphics/Shader/send.lua

@@ -17,7 +17,8 @@ return {
   notes = [[
     The shader does not need to be active to update its uniforms.  However, the types must match up.
     Uniform variables declared as `float`s must be sent a single number, whereas uniforms declared
-    as `vec4`s must be sent a table containing 4 numbers, etc.
+    as `vec4`s must be sent a table containing 4 numbers, etc.  Note that uniforms declared as mat4s
+    can be sent a `Transform` object.
 
     An error is thrown if the uniform does not exist or is not used in the shader.
   ]],

+ 0 - 31
api/lovr/graphics/Skybox/draw.lua

@@ -1,31 +0,0 @@
-return {
-  summary = 'Draw the Skybox.',
-  description = 'Draws the Skybox at a specified angle.',
-  arguments = {
-    {
-      name = 'angle',
-      type = 'number',
-      description = 'The number of radians to rotate the skybox around its axis of rotation'
-    },
-    {
-      name = 'ax',
-      type = 'number',
-      description = 'The x component of the axis of rotation.'
-    },
-    {
-      name = 'ay',
-      type = 'number',
-      description = 'The y component of the axis of rotation.'
-    },
-    {
-      name = 'az',
-      type = 'number',
-      description = 'The z component of the axis of rotation.'
-    }
-  },
-  returns = {},
-  notes = [[
-    To prevent problems with the depth test, make sure you draw Skyboxes before drawing other
-    things, or disable the depth test while drawing them.
-  ]]
-}

+ 0 - 35
api/lovr/graphics/Skybox/init.lua

@@ -1,35 +0,0 @@
-return {
-  summary = 'A cube wrapped around the camera, used as a 3D background.',
-  description = [[
-    A Skybox is a collection of six images used to apply a background to a three dimensional scene.
-    Each image is used to texture the face of a cube, and the cube is drawn around the camera,
-    giving an illusion of a 360-degree background.
-  ]],
-  constructor = 'lovr.graphics.newSkybox',
-  notes = [[
-    To prevent problems with the depth test, make sure you draw Skyboxes before drawing other
-    things, or disable the depth test while drawing them.
-  ]],
-  example = {
-    description = 'Drawing a Skybox in VR:',
-    code = [[
-      function lovr.load()
-        skybox = lovr.graphics.newSkybox({
-          '1.png',
-          '2.png',
-          '3.png',
-          '4.png',
-          '5.png',
-          '6.png'
-        })
-      end
-
-      function lovr.draw()
-        lovr.graphics.setColor(255, 255, 255)
-        skybox:draw(lovr.headset.getOrientation())
-
-        -- Draw everything else
-      end
-    ]]
-  }
-}

+ 2 - 2
api/lovr/graphics/Texture/init.lua

@@ -1,7 +1,7 @@
 return {
-  summary = 'An image that can be applied to Meshes and Models.',
+  summary = 'An image that can be applied to Materials.',
   description = [[
-    A Texture is an image that can be applied to `Model`s and `Mesh`s.  Supported file formats
+    A Texture is an image that can be applied to `Material`s.  Supported file formats
     include `.png`, `.jpg`, `.tga`, and `.bmp`.  Additionally, three compressed formats are
     supported: DXT1, DXT3, and DXT5 (all have the `.dds` extension).  Compressed textures are
     generally recommended as they use less video memory and usually improve performance.

+ 121 - 0
api/lovr/graphics/arc.lua

@@ -0,0 +1,121 @@
+return {
+  tag = 'graphicsPrimitives',
+  summary = 'Draw an arc.',
+  description = 'Draws an arc.',
+  arguments = {
+    mode = {
+      type = 'DrawMode',
+      description = 'Whether the arc is filled or outlined.'
+    },
+    arcmode = {
+      type = 'ArcMode',
+      default = [['pie']],
+      description = 'How to draw the arc.'
+    },
+    material = {
+      type = 'Material',
+      description = 'The Material to apply to the arc.'
+    },
+    transform = {
+      type = 'Transform',
+      description = 'The arc\'s transform.'
+    },
+    x = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate of the center of the arc.'
+    },
+    y = {
+      type = 'number',
+      default = '0',
+      description = 'The y coordinate of the center of the arc.'
+    },
+    z = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate of the center of the arc.'
+    },
+    radius = {
+      type = 'number',
+      default = '1',
+      description = 'The radius of the arc, in meters.'
+    },
+    angle = {
+      type = 'number',
+      default = '0',
+      description = 'The rotation of the arc around its rotation axis, in radians.'
+    },
+    ax = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate of the arc\'s axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      default = '1',
+      description = 'The y coordinate of the arc\'s axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate of the arc\'s axis of rotation.'
+    },
+    start = {
+      type = 'number',
+      default = '0',
+      description = 'The starting angle of the arc, in radians.'
+    },
+    ['end'] = {
+      type = 'number',
+      default = '2 * math.pi',
+      description = 'The ending angle of the arc, in radians.'
+    },
+    segments = {
+      type = 'number',
+      default = '32',
+      description = [[
+        The number of segments to use for the full circle. A smaller number of segments will be
+        used, depending on how long the arc is.
+      ]]
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'mode', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'mode', 'transform', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'transform', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'mode', 'arcmode', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'arcmode', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'mode', 'arcmode', 'transform', 'start', 'end', 'segments' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'arcmode', 'transform', 'start', 'end', 'segments' },
+      returns = {}
+    }
+  },
+  notes = 'The local normal vector of the circle is `(0, 0, 1)`.',
+  related = {
+    'lovr.graphics.arc'
+  }
+}

+ 5 - 5
api/lovr/graphics/box.lua

@@ -6,9 +6,9 @@ return {
     the width, height, and depth of the box.
   ]],
   arguments = {
-    texture = {
-      type = 'Texture',
-      description = 'The Texture to apply to the box.'
+    material = {
+      type = 'Material',
+      description = 'The Material to apply to the box.'
     },
     mode = {
       type = 'DrawMode',
@@ -76,7 +76,7 @@ return {
       returns = {}
     },
     {
-      arguments = { 'texture', 'x', 'y', 'z', 'width', 'height', 'depth', 'angle', 'ax', 'ay', 'az' },
+      arguments = { 'material', 'x', 'y', 'z', 'width', 'height', 'depth', 'angle', 'ax', 'ay', 'az' },
       returns = {}
     },
     {
@@ -84,7 +84,7 @@ return {
       returns = {}
     },
     {
-      arguments = { 'texture', 'transform' },
+      arguments = { 'material', 'transform' },
       returns = {}
     }
   }

+ 82 - 0
api/lovr/graphics/circle.lua

@@ -0,0 +1,82 @@
+return {
+  tag = 'graphicsPrimitives',
+  summary = 'Draw a 2D circle.',
+  description = 'Draws a 2D circle.',
+  arguments = {
+    mode = {
+      type = 'DrawMode',
+      description = 'Whether the circle is filled or outlined.'
+    },
+    material = {
+      type = 'Material',
+      description = 'The Material to apply to the circle.'
+    },
+    transform = {
+      type = 'Transform',
+      description = 'The circle\'s transform.'
+    },
+    x = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate of the center of the circle.'
+    },
+    y = {
+      type = 'number',
+      default = '0',
+      description = 'The y coordinate of the center of the circle.'
+    },
+    z = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate of the center of the circle.'
+    },
+    radius = {
+      type = 'number',
+      default = '1',
+      description = 'The radius of the circle, in meters.'
+    },
+    angle = {
+      type = 'number',
+      default = '0',
+      description = 'The rotation of the circle around its rotation axis, in radians.'
+    },
+    ax = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate of the circle\'s axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      default = '1',
+      description = 'The y coordinate of the circle\'s axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate of the circle\'s axis of rotation.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'mode', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'x', 'y', 'z', 'radius', 'angle', 'ax', 'ay', 'az' },
+      returns = {}
+    },
+    {
+      arguments = { 'mode', 'transform' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'transform' },
+      returns = {}
+    }
+  },
+  notes = 'The local normal vector of the circle is `(0, 0, 1)`.',
+  related = {
+    'lovr.graphics.arc'
+  }
+}

+ 5 - 5
api/lovr/graphics/cube.lua

@@ -3,9 +3,9 @@ return {
   summary = 'Draw a cube.',
   description = 'Draws a cube.',
   arguments = {
-    texture = {
-      type = 'Texture',
-      description = 'The Texture to apply to the cube faces.'
+    material = {
+      type = 'Material',
+      description = 'The Material to apply to the cube faces.'
     },
     mode = {
       type = 'DrawMode',
@@ -63,7 +63,7 @@ return {
       returns = {}
     },
     {
-      arguments = { 'texture', 'x', 'y', 'z', 'size', 'angle', 'ax', 'ay', 'az' },
+      arguments = { 'material', 'x', 'y', 'z', 'size', 'angle', 'ax', 'ay', 'az' },
       returns = {}
     },
     {
@@ -71,7 +71,7 @@ return {
       returns = {}
     },
     {
-      arguments = { 'texture', 'transform' },
+      arguments = { 'material', 'transform' },
       returns = {}
     }
   }

+ 1 - 1
api/lovr/graphics/getBackgroundColor.lua

@@ -2,7 +2,7 @@ return {
   tag = 'graphicsState',
   summary = 'Get the background color.',
   description = [[
-    Returns the current background color.  Color components are from 0 to 255.
+    Returns the current background color.  Color components are from 0.0 to 1.0.
   ]],
   arguments = {},
   returns = {

+ 2 - 2
api/lovr/graphics/getColor.lua

@@ -2,8 +2,8 @@ return {
   tag = 'graphicsState',
   summary = 'Get the global color factor.',
   description = [[
-    Returns the current global color factor.  Color components are from 0 to 255.  Every pixel drawn
-    will be multiplied (i.e. tinted) by this color.
+    Returns the current global color factor.  Color components are from 0.0 to 1.0.  Every pixel
+    drawn will be multiplied (i.e. tinted) by this color.
   ]],
   arguments = {},
   returns = {

+ 24 - 0
api/lovr/graphics/isGammaCorrect.lua

@@ -0,0 +1,24 @@
+return {
+  tag = 'graphicsState',
+  summary = 'Get whether wireframe mode is enabled.',
+  description = [[
+    Get whether or not gamma correct rendering is supported and enabled.  When enabled, lovr will
+    automatically perform gamma correction on colors set via `lovr.graphics.setColor`,
+    `lovr.graphics.setBackgroundColor`, `Material:setColor`, and textures created without the linear
+    flag set.  Gamma correction will subtly improve lighting quality, especially in darker regions.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'isGammaCorrect',
+      type = 'boolean',
+      description = 'Whether or not gamma correction is applied to colors.'
+    }
+  },
+  notes = 'Gamma correction must first be enabled in `lovr.conf`.',
+  related = {
+    'lovr.conf',
+    'lovr.math.gammaToLinear',
+    'lovr.math.linearToGamma'
+  }
+}

+ 25 - 0
api/lovr/graphics/newAnimator.lua

@@ -0,0 +1,25 @@
+return {
+  tag = 'graphicsObjects',
+  summary = 'Create a new Animator.',
+  description = 'Creates a new `Animator` by reading animations from a `Model`.',
+  arguments = {
+    {
+      name = 'model',
+      type = 'Model',
+      description = 'The model to read animations from.'
+    }
+  },
+  returns = {
+    {
+      name = 'animator',
+      type = 'Animator',
+      description = 'The new Animator.'
+    }
+  },
+  notes = [[
+    You can attach an animator to a Model with `Model:setAnimator`.
+  ]],
+  related = {
+    'Model:setAnimator'
+  }
+}

+ 55 - 0
api/lovr/graphics/newMaterial.lua

@@ -0,0 +1,55 @@
+return {
+  tag = 'graphicsObjects',
+  summary = 'Create a new Material.',
+  description = [[
+    Creates a new Material.  Materials are sets of colors, textures, and other parameters that
+    affect the appearance of objects.  They can be applied to `Model`s, `Mesh`es, and most graphics
+    primitives accept a Material as an optional first argument.
+  ]],
+  arguments = {
+    texture = {
+      type = 'Texture',
+      description = 'The diffuse texture.'
+    },
+    r = {
+      type = 'number',
+      default = '1',
+      description = 'The red component of the diffuse color.'
+    },
+    g = {
+      type = 'number',
+      default = '1',
+      description = 'The green component of the diffuse color.'
+    },
+    b = {
+      type = 'number',
+      default = '1',
+      description = 'The blue component of the diffuse color.'
+    },
+    a = {
+      type = 'number',
+      default = '1',
+      description = 'The alpha component of the diffuse color.'
+    }
+  },
+  returns = {
+    material = {
+      type = 'Material',
+      description = 'The new Material.'
+    }
+  },
+  variants = {
+    {
+      arguments = {},
+      returns = { 'material' }
+    },
+    {
+      arguments = { 'texture', 'r', 'g', 'b', 'a' },
+      returns = { 'material' }
+    },
+    {
+      arguments = { 'r', 'g', 'b', 'a' },
+      returns = { 'material' }
+    }
+  }
+}

+ 6 - 9
api/lovr/graphics/newModel.lua

@@ -2,8 +2,8 @@ return {
   tag = 'graphicsObjects',
   summary = 'Create a new Model.',
   description = [[
-    Creates a new Model from a file.  The supported 3D file formats are `obj`, `fbx`, and collada.
-    Models use normals and texture coordinates, if provided.
+    Creates a new Model from a file.  The supported 3D file formats are `obj`, `fbx`, `gltf`, and
+    collada.  Models use normals and texture coordinates, if provided.
 
     The following features are not supported yet: animations, materials, vertex colors.
   ]],
@@ -12,12 +12,6 @@ return {
       name = 'filename',
       type = 'string',
       description = 'The filename of the model to load.'
-    },
-    {
-      name = 'texture',
-      type = 'string',
-      default = 'nil',
-      description = 'A filename for a texture to apply to the Model, or `nil` for no texture.'
     }
   },
   returns = {
@@ -26,5 +20,8 @@ return {
       type = 'Model',
       description = 'The new Model.'
     }
-  }
+  },
+  notes = [[
+    Models loaded from glTF files do not currently import animations properly.
+  ]]
 }

+ 0 - 60
api/lovr/graphics/newSkybox.lua

@@ -1,60 +0,0 @@
-return {
-  tag = 'graphicsObjects',
-  summary = 'Create a new Skybox.',
-  description = 'Creates a new Skybox from a set of 6 images.',
-  arguments = {
-    right = {
-      type = 'string',
-      description = 'The filename of the image for the right face of the skybox.'
-    },
-    left = {
-      type = 'string',
-      description = 'The filename of the image for the left face of the skybox.'
-    },
-    top = {
-      type = 'string',
-      description = 'The filename of the image for the top face of the skybox.'
-    },
-    bottom = {
-      type = 'string',
-      description = 'The filename of the image for the bottom face of the skybox.'
-    },
-    back = {
-      type = 'string',
-      description = 'The filename of the image for the back face of the skybox.'
-    },
-    front = {
-      type = 'string',
-      description = 'The filename of the image for the front face of the skybox.'
-    },
-    images = {
-      type = 'table',
-      description = 'A table containing 6 images, as described above.'
-    },
-    image = {
-      type = 'string',
-      description = 'A filename for an equirectangular image to load.'
-    }
-  },
-  returns = {
-    skybox = {
-      type = 'Skybox',
-      description = 'The new Skybox.'
-    }
-  },
-  variants = {
-    {
-      arguments = { 'right', 'left', 'top', 'bottom', 'back', 'front' },
-      returns = { 'skybox' }
-    },
-    {
-      arguments = { 'images' },
-      returns = { 'skybox' }
-    },
-    {
-      description = 'Creates a Skybox from a single equirectangular image.',
-      arguments = { 'image' },
-      returns = { 'skybox' }
-    }
-  }
-}

+ 62 - 3
api/lovr/graphics/newTexture.lua

@@ -7,6 +7,47 @@ return {
       type = 'string',
       description = 'The filename of the image to load.'
     },
+    right = {
+      type = 'string',
+      description = 'The filename of the image for the positive x direction.'
+    },
+    left = {
+      type = 'string',
+      description = 'The filename of the image for the negative x direction.'
+    },
+    top = {
+      type = 'string',
+      description = 'The filename of the image for the positive y direction.'
+    },
+    bottom = {
+      type = 'string',
+      description = 'The filename of the image for the negative y direction.'
+    },
+    back = {
+      type = 'string',
+      description = 'The filename of the image for the positive z direction.'
+    },
+    front = {
+      type = 'string',
+      description = 'The filename of the image for the negative z direction.'
+    },
+    images = {
+      type = 'table',
+      description = 'The table of image filenames.  Either 1 or 6 can be provided, as above.'
+    },
+    flags = {
+      type = 'table',
+      default = '{}',
+      description = 'Optional settings for the texture.',
+      table = {
+        {
+          name = 'linear',
+          type = 'boolean',
+          default = 'false',
+          description = 'Whether the texture is in linear color space instead of sRGB.'
+        }
+      }
+    },
     width = {
       type = 'number',
       description = 'The width of the Texture, in pixels.'
@@ -21,7 +62,6 @@ return {
     },
     msaa = {
       type = 'number',
-      default = '0',
       description = 'The number of samples to use for multisample antialiasing.'
     }
   },
@@ -34,12 +74,31 @@ return {
   },
   variants = {
     {
-      arguments = { 'filename' },
+      arguments = { 'filename', 'flags' },
+      returns = { 'texture' }
+    },
+    {
+      description = [[
+        Creates a new cubemap texture from 6 images.  It can be used as a skybox using
+        `lovr.graphics.skybox`.
+      ]],
+      arguments = { 'right', 'left', 'top', 'bottom', 'back', 'front', 'flags' },
       returns = { 'texture' }
     },
     {
+      description = 'Create a new texture from a table of images.',
+      arguments = { 'images', 'flags' },
+      returns = { 'texture' }
+    },
+    {
+      description = 'Create a render texture (also called a "framebuffer" or a "canvas").',
       arguments = { 'width', 'height', 'projection', 'msaa' },
       returns = { 'texture' }
     }
-  }
+  },
+  notes = [[
+    The "linear" flag should be set to true for textures that don't contain color information, such
+    as normal maps.  It is ignored if gamma correct rendering is disabled.  See
+    `lovr.graphics.isGammaCorrect` for more info.
+  ]]
 }

+ 7 - 3
api/lovr/graphics/plane.lua

@@ -5,7 +5,11 @@ return {
   arguments = {
     texture = {
       type = 'Texture',
-      description = 'The texture to apply to the plane.'
+      description = 'The texture to use.'
+    },
+    material = {
+      type = 'Material',
+      description = 'The material to apply to the plane.'
     },
     mode = {
       type = 'DrawMode',
@@ -60,8 +64,8 @@ return {
       returns = {}
     },
     {
-      description = 'Draw a textured plane.',
-      arguments = { 'texture', 'x', 'y', 'z', 'size', 'angle', 'ax', 'ay', 'az' },
+      description = 'Draw a plane with a custom material.',
+      arguments = { 'material', 'x', 'y', 'z', 'size', 'angle', 'ax', 'ay', 'az' },
       returns = {}
     },
     {

+ 2 - 2
api/lovr/graphics/setBackgroundColor.lua

@@ -2,7 +2,7 @@ return {
   tag = 'graphicsState',
   summary = 'Set the background color.',
   description = [[
-    Sets the background color used to clear the screen.  Color components are from 0 to 255.
+    Sets the background color used to clear the screen.  Color components are from 0.0 to 1.0.
   ]],
   arguments = {
     {
@@ -23,7 +23,7 @@ return {
     {
       name = 'a',
       type = 'number',
-      default = '255',
+      default = '1.0',
       description = 'The alpha component of the background color.'
     }
   },

+ 3 - 3
api/lovr/graphics/setColor.lua

@@ -2,7 +2,7 @@ return {
   tag = 'graphicsState',
   summary = 'Set the global color factor.',
   description = [[
-    Sets the color used for drawing objects.  Color components are from 0 to 255.  Every pixel drawn
+    Sets the color used for drawing objects.  Color components are from 0.0 to 1.0.  Every pixel drawn
     will be multiplied (i.e. tinted) by this color.  This is a global setting, so it will affect all
     subsequent drawing operations.
   ]],
@@ -21,7 +21,7 @@ return {
     },
     a = {
       type = 'number',
-      default = '255',
+      default = '1.0',
       description = 'The alpha component of the color.'
     },
     color = {
@@ -45,7 +45,7 @@ return {
     description = 'Draw a red cube.',
     code = [[
       function lovr.draw()
-        lovr.graphics.setColor(255, 0, 0)
+        lovr.graphics.setColor(1.0, 0, 0)
         lovr.graphics.cube('fill', 0, 1.7, -1, .5, lovr.timer.getTime())
       end
     ]]

+ 56 - 0
api/lovr/graphics/skybox.lua

@@ -0,0 +1,56 @@
+return {
+  tag = 'graphicsPrimitives',
+  summary = 'Render a skybox.',
+  description = [[
+    Render a skybox from a texture.  Two common kinds of skybox textures are supported: A rectangular
+    texture with an equirectangular projection can be used, or a "cubemap" texture created from 6
+    images.
+  ]],
+  arguments = {
+    {
+      name = 'texture',
+      type = 'Texture',
+      description = 'The texture to use.'
+    },
+    angle = {
+      type = 'number',
+      default = '0',
+      description = 'How much to rotate the skybox around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      default = '0',
+      description = 'The x coordinate of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      default = '1',
+      description = 'The y coordinate of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      default = '0',
+      description = 'The z coordinate of the axis of rotation.'
+    }
+  },
+  returns = {},
+  example = [[
+    function lovr.load()
+      skybox = lovr.graphics.newTexture(
+        'right.png',
+        'left.png',
+        'up.png',
+        'down.png',
+        'back.png',
+        'front.png'
+      )
+
+      -- or skybox = lovr.graphics.newTexture('equirectangular.png')
+    end
+
+    function lovr.draw()
+      local angle, ax, ay, az = lovr.headset.getOrientation()
+      lovr.graphics.skybox(skybox, -angle, ax, ay, az)
+    end
+  ]]
+}

+ 24 - 20
api/lovr/graphics/triangle.lua

@@ -3,57 +3,61 @@ return {
   summary = 'Draw a triangle.',
   description = 'Draws a triangle from three points.',
   arguments = {
-    {
-      name = 'mode',
+    mode = {
       type = 'DrawMode',
       description = 'How to draw the triangle.'
     },
-    {
-      name = 'x1',
+    material = {
+      type = 'Material',
+      description = 'The Material to apply.'
+    },
+    x1 = {
       type = 'number',
       description = 'The x coordinate of the first point.'
     },
-    {
-      name = 'y1',
+    y1 = {
       type = 'number',
       description = 'The y coordinate of the first point.'
     },
-    {
-      name = 'z1',
+    z1 = {
       type = 'number',
       description = 'The z coordinate of the first point.'
     },
-    {
-      name = 'x2',
+    x2 = {
       type = 'number',
       description = 'The x coordinate of the second point.'
     },
-    {
-      name = 'y2',
+    y2 = {
       type = 'number',
       description = 'The y coordinate of the second point.'
     },
-    {
-      name = 'z2',
+    z2 = {
       type = 'number',
       description = 'The z coordinate of the second point.'
     },
-    {
-      name = 'x3',
+    x3 = {
       type = 'number',
       description = 'The x coordinate of the third point.'
     },
-    {
-      name = 'y3',
+    y3 = {
       type = 'number',
       description = 'The y coordinate of the third point.'
     },
-    {
-      name = 'z3',
+    z3 = {
       type = 'number',
       description = 'The z coordinate of the third point.'
     }
   },
   returns = {},
+  variants = {
+    {
+      arguments = { 'mode', 'x1', 'y1', 'z1', 'x2', 'y2', 'z2', 'x3', 'y3', 'z3' },
+      returns = {}
+    },
+    {
+      arguments = { 'material', 'x1', 'y1', 'z1', 'x2', 'y2', 'z2', 'x3', 'y3', 'z3' },
+      returns = {}
+    }
+  },
   notes = 'Unlike some of the other primitives, exactly 3 points are required here.'
 }

+ 71 - 0
api/lovr/math/Transform/getMatrix.lua

@@ -0,0 +1,71 @@
+return {
+  summary = 'Get the Transform\'s matrix.',
+  description = 'Returns the individual matrix components of a Transform, in column-major order.',
+  arguments = {},
+  returns = {
+    {
+      name = 'm11',
+      type = 'number'
+    },
+    {
+      name = 'm21',
+      type = 'number'
+    },
+    {
+      name = 'm31',
+      type = 'number'
+    },
+    {
+      name = 'm41',
+      type = 'number'
+    },
+    {
+      name = 'm12',
+      type = 'number'
+    },
+    {
+      name = 'm22',
+      type = 'number'
+    },
+    {
+      name = 'm32',
+      type = 'number'
+    },
+    {
+      name = 'm42',
+      type = 'number'
+    },
+    {
+      name = 'm13',
+      type = 'number'
+    },
+    {
+      name = 'm23',
+      type = 'number'
+    },
+    {
+      name = 'm33',
+      type = 'number'
+    },
+    {
+      name = 'm43',
+      type = 'number'
+    },
+    {
+      name = 'm14',
+      type = 'number'
+    },
+    {
+      name = 'm24',
+      type = 'number'
+    },
+    {
+      name = 'm34',
+      type = 'number'
+    },
+    {
+      name = 'm44',
+      type = 'number'
+    }
+  }
+}

+ 86 - 0
api/lovr/math/Transform/setMatrix.lua

@@ -0,0 +1,86 @@
+return {
+  summary = 'Set the Transform\'s matrix.',
+  description = 'Sets the individual matrix components of a Transform, in column-major order.',
+  arguments = {
+    m11 = {
+      type = 'number'
+    },
+    m21 = {
+      type = 'number'
+    },
+    m31 = {
+      type = 'number'
+    },
+    m41 = {
+      type = 'number'
+    },
+    m12 = {
+      type = 'number'
+    },
+    m22 = {
+      type = 'number'
+    },
+    m32 = {
+      type = 'number'
+    },
+    m42 = {
+      type = 'number'
+    },
+    m13 = {
+      type = 'number'
+    },
+    m23 = {
+      type = 'number'
+    },
+    m33 = {
+      type = 'number'
+    },
+    m43 = {
+      type = 'number'
+    },
+    m14 = {
+      type = 'number'
+    },
+    m24 = {
+      type = 'number'
+    },
+    m34 = {
+      type = 'number'
+    },
+    m44 = {
+      type = 'number'
+    },
+    m = {
+      type = 'table',
+      description = 'A table containing the matrix values, as above.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = {
+        'm11',
+        'm21',
+        'm31',
+        'm41',
+        'm12',
+        'm22',
+        'm32',
+        'm42',
+        'm13',
+        'm23',
+        'm33',
+        'm43',
+        'm14',
+        'm24',
+        'm34',
+        'm44'
+      },
+      returns = {}
+    },
+    {
+      arguments = { 'm' },
+      returns = {}
+    }
+  }
+}

+ 64 - 0
api/lovr/math/gammaToLinear.lua

@@ -0,0 +1,64 @@
+return {
+  summary = '	Convert a color from gamma space to linear space.',
+  description = 'Converts a color from gamma space to linear space.',
+  arguments = {
+    gr = {
+      type = 'number',
+      description = 'The red component of the gamma-space color.'
+    },
+    gg = {
+      type = 'number',
+      description = 'The green component of the gamma-space color.'
+    },
+    gb = {
+      type = 'number',
+      description = 'The blue component of the gamma-space color.'
+    },
+    color = {
+      type = 'table',
+      description = 'A table containing the components of a gamma-space color.'
+    },
+    x = {
+      type = 'number',
+      description = 'The color channel to convert.'
+    }
+  },
+  returns = {
+    lr = {
+      type = 'number',
+      description = 'The red component of the resulting linear-space color.'
+    },
+    lg = {
+      type = 'number',
+      description = 'The green component of the resulting linear-space color.'
+    },
+    lb = {
+      type = 'number',
+      description = 'The blue component of the resulting linear-space color.'
+    },
+    y = {
+      type = 'number',
+      description = 'The converted color channel.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'gr', 'gg', 'gb' },
+      returns = { 'lr', 'lg', 'lb' }
+    },
+    {
+      description = 'A table can also be used.',
+      arguments = { 'color' },
+      returns = { 'lr', 'lg', 'lb' }
+    },
+    {
+      description = 'Convert a single color channel.',
+      arguments = { 'x' },
+      returns = { 'y' }
+    }
+  },
+  related = {
+    'lovr.math.linearToGamma',
+    'lovr.graphics.isGammaCorrect'
+  }
+}

+ 64 - 0
api/lovr/math/linearToGamma.lua

@@ -0,0 +1,64 @@
+return {
+  summary = '	Convert a color from linear space to gamma space.',
+  description = 'Converts a color from linear space to gamma space.',
+  arguments = {
+    lr = {
+      type = 'number',
+      description = 'The red component of the linear-space color.'
+    },
+    lg = {
+      type = 'number',
+      description = 'The green component of the linear-space color.'
+    },
+    lb = {
+      type = 'number',
+      description = 'The blue component of the linear-space color.'
+    },
+    color = {
+      type = 'table',
+      description = 'A table containing the components of a linear-space color.'
+    },
+    x = {
+      type = 'number',
+      description = 'The color channel to convert.'
+    }
+  },
+  returns = {
+    gr = {
+      type = 'number',
+      description = 'The red component of the resulting gamma-space color.'
+    },
+    gg = {
+      type = 'number',
+      description = 'The green component of the resulting gamma-space color.'
+    },
+    gb = {
+      type = 'number',
+      description = 'The blue component of the resulting gamma-space color.'
+    },
+    y = {
+      type = 'number',
+      description = 'The converted color channel.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'lr', 'lg', 'lb' },
+      returns = { 'gr', 'gg', 'gb' }
+    },
+    {
+      description = 'A table can also be used.',
+      arguments = { 'color' },
+      returns = { 'gr', 'gg', 'gb' }
+    },
+    {
+      description = 'Convert a single color channel.',
+      arguments = { 'x' },
+      returns = { 'y' }
+    }
+  },
+  related = {
+    'lovr.math.gammaToLinear',
+    'lovr.graphics.isGammaCorrect'
+  }
+}

+ 63 - 0
api/lovr/math/orientationToDirection.lua

@@ -0,0 +1,63 @@
+return {
+  summary = 'Convert an angle/axis orientation to a direction vector.',
+  description = 'Converts a rotation in angle/axis representation into a direction vector.',
+  arguments = {
+    {
+      name = 'angle',
+      type = 'number',
+      description = 'The angle (in radians).'
+    },
+    {
+      name = 'ax',
+      type = 'number',
+      default = '0',
+      description = 'The x component of the axis of rotation.'
+    },
+    {
+      name = 'ay',
+      type = 'number',
+      default = '1',
+      description = 'The y component of the axis of rotation.'
+    },
+    {
+      name = 'az',
+      type = 'number',
+      default = '0',
+      description = 'The z component of the axis of rotation.'
+    }
+  },
+  returns = {
+    {
+      name = 'x',
+      type = 'number',
+      description = 'The x component of the direction vector.'
+    },
+    {
+      name = 'y',
+      type = 'number',
+      description = 'The y component of the direction vector.'
+    },
+    {
+      name = 'z',
+      type = 'number',
+      description = 'The z component of the direction vector.'
+    }
+  },
+  example = {
+    description = 'Give Controllers laser beams.',
+    code = [[
+      function lovr.draw()
+        for i, controller in ipairs(lovr.headset.getControllers()) do
+          local x, y, z = controller:getPosition()
+          local angle, ax, ay, az = controller:getOrientation()
+          local dx, dy, dz = lovr.math.orientationToDirection(angle, ax, ay, az)
+          local length = 2
+          lovr.graphics.line(x, y, z, x + dx * length, y + dy * length, z + dz * length)
+        end
+      end
+    ]]
+  },
+  related = {
+    'lovr.math.lookAt'
+  }
+}

+ 1 - 0
examples/Lighting/conf.lua

@@ -1,3 +1,4 @@
 function lovr.conf(t)
   t.window.msaa = 4
+  t.gammacorrect = true
 end

+ 0 - 1
examples/Lighting/main.lua

@@ -36,7 +36,6 @@ function lovr.load()
 
       vec3 cFinal = vec3(diffuse) * cDiffuse + vec3(specular) * cSpecular;
       cFinal = clamp(cFinal, cAmbient, vec3(1.));
-      cFinal = pow(cFinal, vec3(.4545));
       return vec4(cFinal, 1.) * graphicsColor * texture(image, uv);
     }
   ]])

+ 2 - 2
examples/Panorama/main.lua

@@ -1,10 +1,10 @@
 local skybox
 
 function lovr.load()
-  skybox = lovr.graphics.newSkybox('equirectangular.jpg')
+  skybox = lovr.graphics.newTexture('equirectangular.jpg')
 end
 
 function lovr.draw()
   local angle, x, y, z = lovr.headset.getOrientation()
-  skybox:draw(-angle, x, y, z)
+  lovr.graphics.skybox(skybox, -angle, x, y, z)
 end

+ 3 - 3
examples/Physics/main.lua

@@ -39,15 +39,15 @@ function drawBox(box)
 end
 
 function lovr.draw()
-  lovr.graphics.setBackgroundColor(200, 200, 200)
+  lovr.graphics.setBackgroundColor(.8, .8, .8)
   lovr.graphics.setShader(shader)
 
-  lovr.graphics.setColor(255, 0, 0)
+  lovr.graphics.setColor(1, 0, 0)
   for i, box in ipairs(boxes) do
     drawBox(box)
   end
 
-  lovr.graphics.setColor(0, 0, 255)
+  lovr.graphics.setColor(0, 0, 1)
   for i, box in ipairs(controllerBoxes) do
     drawBox(box)
   end

+ 11 - 11
examples/Primitives/main.lua

@@ -1,12 +1,12 @@
 shader = require 'shader'
 
 local function drawLabel(str, x, y, z)
-  lovr.graphics.setColor(255, 255, 255)
+  lovr.graphics.setColor(1, 1, 1)
   lovr.graphics.print(str, x, y, z, .1)
 end
 
 function lovr.draw()
-  lovr.graphics.setBackgroundColor(30, 30, 30)
+  lovr.graphics.setBackgroundColor(.1, .1, .1)
   lovr.graphics.setShader(shader)
 
   local hx, hy, hz = lovr.headset.getPosition()
@@ -15,7 +15,7 @@ function lovr.draw()
   -- Point
   x, y, z = -.6, 1.1, -1
   lovr.graphics.setPointSize(5)
-  lovr.graphics.setColor(255, 255, 255)
+  lovr.graphics.setColor(1, 1, 1)
   lovr.graphics.points(x, y, z)
 
   -- Line
@@ -24,7 +24,7 @@ function lovr.draw()
     x - .1, y, z,
     x + .1, y, z
   }
-  lovr.graphics.setColor(255, 255, 255)
+  lovr.graphics.setColor(1, 1, 1)
   lovr.graphics.line(points)
 
   -- Triangle
@@ -32,37 +32,37 @@ function lovr.draw()
   local p1 = { x, y + .2, z }
   local p2 = { x - .2, y - .2, z }
   local p3 = { x + .2, y - .2, z }
-  lovr.graphics.setColor(92, 107, 192)
+  lovr.graphics.setColor(.36, .41, .75)
   lovr.graphics.triangle('fill', p1[1], p1[2], p1[3], p2[1], p2[2], p2[3], p3[1], p3[2], p3[3])
 
   -- Plane
   local x, y, z = -.6, 1.7, -1.5
-  lovr.graphics.setColor(239, 83, 80)
+  lovr.graphics.setColor(.94, .33, .31)
   lovr.graphics.plane('fill', x, y, z, .4, lovr.timer.getTime())
 
   -- Cube
   local x, y, z = 0, 1.7, -1.5
-  lovr.graphics.setColor(126, 87, 194)
+  lovr.graphics.setColor(.49, .34, .76)
   lovr.graphics.cube('fill', x, y, z, .3, lovr.timer.getTime())
 
   -- Box
   local x, y, z = .6, 1.7, -1.5
-  lovr.graphics.setColor(255, 167, 45)
+  lovr.graphics.setColor(1, .65, .18)
   lovr.graphics.box('fill', x, y, z, .4, .2, .3, lovr.timer.getTime())
 
   -- Cylinder
   local x, y, z = -.6, 2.4, -2
-  lovr.graphics.setColor(102, 187, 106)
+  lovr.graphics.setColor(.4, .73, .42)
   lovr.graphics.cylinder(x - .2, y, z, x + .2, y, z, .1, .1)
 
   -- Cone
   local x, y, z = 0, 2.4, -2
-  lovr.graphics.setColor(255, 241, 118)
+  lovr.graphics.setColor(1, .95, .46)
   lovr.graphics.cylinder(x, y + .2, z, x, y - .2, z, 0, .18)
 
   -- Sphere
   local x, y, z = .6, 2.4, -2
-  lovr.graphics.setColor(77, 208, 255)
+  lovr.graphics.setColor(.3, .82, 1)
   lovr.graphics.sphere(x, y, z, .2)
 
   lovr.graphics.setShader()

+ 6 - 6
guides/Callbacks_and_Modules.md

@@ -79,7 +79,7 @@ The graphics module is the most exciting module, and is also the largest.  Most
 These can be used to quickly prototype a scene without needing to create or load assets.
 
 There are lots of different rendering-related objects that can be created using `lovr.graphics`,
-such as `Model`, `Texture`, `Font`, `Shader`, `Skybox`, and more.  Every function to create a new
+such as `Model`, `Texture`, `Font`, `Shader`, and more.  Every function to create a new
 object is prefixed with `new`, so to create a 3D model object you can use `lovr.graphics.newModel`.
 
 > Note: Creating graphics objects uses memory and can slow things down if done every frame.  For
@@ -107,14 +107,14 @@ end
 
 function lovr.draw()
   -- Use a dark grey background
-  lovr.graphics.setBackgroundColor(50, 50, 50)
+  lovr.graphics.setBackgroundColor(.2, .2, .2)
 
   -- Draw the model
-  lovr.graphics.setColor(255, 255, 255)
+  lovr.graphics.setColor(1.0, 1.0, 1.0)
   model:draw(-.5, 1, -3)
 
   -- Draw a red cube using the "cube" primitive
-  lovr.graphics.setColor(255, 0, 0)
+  lovr.graphics.setColor(1.0, 0, 0)
   lovr.graphics.cube('fill', .5, 1, -3, .5, lovr.timer.getTime())
 end
 ```
@@ -229,12 +229,12 @@ function drawBox(box)
 end
 
 function lovr.draw()
-  lovr.graphics.setColor(255, 0, 0)
+  lovr.graphics.setColor(1.0, 0, 0)
   for i, box in ipairs(boxes) do
     drawBox(box)
   end
 
-  lovr.graphics.setColor(0, 0, 255)
+  lovr.graphics.setColor(0, 0, 1.0)
   for i, box in ipairs(controllerBoxes) do
     drawBox(box)
   end

+ 0 - 1
guides/Libraries.md

@@ -26,7 +26,6 @@ List of Libraries
 - [flux](https://github.com/rxi/flux) - A tweening library for Lua.
 - [handy](https://github.com/bjornbytes/handy) - Helper utilities for managing controllers.
 - [knife](https://github.com/airstruck/knife) - A collection of useful micromodules for Lua.
-- [lovr-circle](https://github.com/bjornbytes/lovr-circle) - Create circle geometry.
 - [lovr-icosphere](https://github.com/bjornbytes/lovr-icosphere) - A library to create icospheres.
 - [lovr-grid](https://github.com/bjornbytes/lovr-grid) - A library for drawing grids.
 - [lovr-lighting](https://github.com/bjornbytes/lovr-lighting) - Simple lighting shaders to add to

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.