wrap_Graphics.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. R"luastring"--(
  2. -- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
  3. -- There is a matching delimiter at the bottom of the file.
  4. --[[
  5. Copyright (c) 2006-2016 LOVE Development Team
  6. This software is provided 'as-is', without any express or implied
  7. warranty. In no event will the authors be held liable for any damages
  8. arising from the use of this software.
  9. Permission is granted to anyone to use this software for any purpose,
  10. including commercial applications, and to alter it and redistribute it
  11. freely, subject to the following restrictions:
  12. 1. The origin of this software must not be misrepresented; you must not
  13. claim that you wrote the original software. If you use this software
  14. in a product, an acknowledgment in the product documentation would be
  15. appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be
  17. misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source distribution.
  19. --]]
  20. local table_concat = table.concat
  21. local ipairs = ipairs
  22. -- SHADERS
  23. local GLSL = {}
  24. GLSL.VERSION = "#version 120"
  25. GLSL.VERSION_ES = "#version 100"
  26. GLSL.SYNTAX = [[
  27. #ifndef GL_ES
  28. #define lowp
  29. #define mediump
  30. #define highp
  31. #endif
  32. #define number float
  33. #define Image sampler2D
  34. #define extern uniform
  35. #define Texel texture2D
  36. #pragma optionNV(strict on)]]
  37. -- Uniforms shared by the vertex and pixel shader stages.
  38. GLSL.UNIFORMS = [[
  39. #ifdef GL_ES
  40. // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
  41. // but we can't guarantee that highp is always supported in fragment shaders...
  42. // We *really* don't want to use mediump for these in vertex shaders though.
  43. #if defined(VERTEX) || defined(GL_FRAGMENT_PRECISION_HIGH)
  44. #define LOVE_UNIFORM_PRECISION highp
  45. #else
  46. #define LOVE_UNIFORM_PRECISION mediump
  47. #endif
  48. uniform LOVE_UNIFORM_PRECISION mat4 TransformMatrix;
  49. uniform LOVE_UNIFORM_PRECISION mat4 ProjectionMatrix;
  50. uniform LOVE_UNIFORM_PRECISION mat4 TransformProjectionMatrix;
  51. uniform LOVE_UNIFORM_PRECISION mat3 NormalMatrix;
  52. #else
  53. #define TransformMatrix gl_ModelViewMatrix
  54. #define ProjectionMatrix gl_ProjectionMatrix
  55. #define TransformProjectionMatrix gl_ModelViewProjectionMatrix
  56. #define NormalMatrix gl_NormalMatrix
  57. #endif
  58. uniform mediump vec4 love_ScreenSize;]]
  59. GLSL.FUNCTIONS = [[
  60. float gammaToLinearPrecise(float c) {
  61. return c <= 0.04045 ? c * 0.077399380804954 : pow((c + 0.055) * 0.9478672985782, 2.4);
  62. }
  63. vec3 gammaToLinearPrecise(vec3 c) {
  64. bvec3 leq = lessThanEqual(c, vec3(0.04045));
  65. c.r = leq.r ? c.r * 0.077399380804954 : pow((c.r + 0.055) * 0.9478672985782, 2.4);
  66. c.g = leq.g ? c.g * 0.077399380804954 : pow((c.g + 0.055) * 0.9478672985782, 2.4);
  67. c.b = leq.b ? c.b * 0.077399380804954 : pow((c.b + 0.055) * 0.9478672985782, 2.4);
  68. return c;
  69. }
  70. vec4 gammaToLinearPrecise(vec4 c) { return vec4(gammaToLinearPrecise(c.rgb), c.a); }
  71. float linearToGammaPrecise(float c) {
  72. return c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;
  73. }
  74. vec3 linearToGammaPrecise(vec3 c) {
  75. bvec3 lt = lessThanEqual(c, vec3(0.0031308));
  76. c.r = lt.r ? c.r * 12.92 : 1.055 * pow(c.r, 1.0 / 2.4) - 0.055;
  77. c.g = lt.g ? c.g * 12.92 : 1.055 * pow(c.g, 1.0 / 2.4) - 0.055;
  78. c.b = lt.b ? c.b * 12.92 : 1.055 * pow(c.b, 1.0 / 2.4) - 0.055;
  79. return c;
  80. }
  81. vec4 linearToGammaPrecise(vec4 c) { return vec4(linearToGammaPrecise(c.rgb), c.a); }
  82. // pow(x, 2.2) isn't an amazing approximation, but at least it's efficient...
  83. mediump float gammaToLinearFast(mediump float c) { return pow(max(c, 0.0), 2.2); }
  84. mediump vec3 gammaToLinearFast(mediump vec3 c) { return pow(max(c, vec3(0.0)), vec3(2.2)); }
  85. mediump vec4 gammaToLinearFast(mediump vec4 c) { return vec4(gammaToLinearFast(c.rgb), c.a); }
  86. mediump float linearToGammaFast(mediump float c) { return pow(max(c, 0.0), 1.0 / 2.2); }
  87. mediump vec3 linearToGammaFast(mediump vec3 c) { return pow(max(c, vec3(0.0)), vec3(1.0 / 2.2)); }
  88. mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c.rgb), c.a); }
  89. #ifdef LOVE_PRECISE_GAMMA
  90. #define gammaToLinear gammaToLinearPrecise
  91. #define linearToGamma linearToGammaPrecise
  92. #else
  93. #define gammaToLinear gammaToLinearFast
  94. #define linearToGamma linearToGammaFast
  95. #endif
  96. #ifdef LOVE_GAMMA_CORRECT
  97. #define gammaCorrectColor gammaToLinear
  98. #define unGammaCorrectColor linearToGamma
  99. #define gammaCorrectColorPrecise gammaToLinearPrecise
  100. #define unGammaCorrectColorPrecise linearToGammaPrecise
  101. #define gammaCorrectColorFast gammaToLinearFast
  102. #define unGammaCorrectColorFast linearToGammaFast
  103. #else
  104. #define gammaCorrectColor
  105. #define unGammaCorrectColor
  106. #define gammaCorrectColorPrecise
  107. #define unGammaCorrectColorPrecise
  108. #define gammaCorrectColorFast
  109. #define unGammaCorrectColorFast
  110. #endif]]
  111. GLSL.VERTEX = {
  112. HEADER = [[
  113. #define VERTEX
  114. #define LOVE_PRECISE_GAMMA
  115. attribute vec4 VertexPosition;
  116. attribute vec4 VertexTexCoord;
  117. attribute vec4 VertexColor;
  118. attribute vec4 ConstantColor;
  119. varying vec4 VaryingTexCoord;
  120. varying vec4 VaryingColor;
  121. #ifdef GL_ES
  122. uniform mediump float love_PointSize;
  123. #endif]],
  124. FUNCTIONS = "",
  125. FOOTER = [[
  126. void main() {
  127. VaryingTexCoord = VertexTexCoord;
  128. VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor;
  129. #ifdef GL_ES
  130. gl_PointSize = love_PointSize;
  131. #endif
  132. gl_Position = position(TransformProjectionMatrix, VertexPosition);
  133. }]],
  134. }
  135. GLSL.PIXEL = {
  136. HEADER = [[
  137. #define PIXEL
  138. #ifdef GL_ES
  139. precision mediump float;
  140. #endif
  141. varying mediump vec4 VaryingTexCoord;
  142. varying mediump vec4 VaryingColor;
  143. #define love_Canvases gl_FragData
  144. uniform sampler2D _tex0_;]],
  145. FUNCTIONS = [[
  146. uniform sampler2D love_VideoYChannel;
  147. uniform sampler2D love_VideoCbChannel;
  148. uniform sampler2D love_VideoCrChannel;
  149. vec4 VideoTexel(vec2 texcoords)
  150. {
  151. vec3 yuv;
  152. yuv[0] = Texel(love_VideoYChannel, texcoords).r;
  153. yuv[1] = Texel(love_VideoCbChannel, texcoords).r;
  154. yuv[2] = Texel(love_VideoCrChannel, texcoords).r;
  155. yuv += vec3(-0.0627451017, -0.501960814, -0.501960814);
  156. vec4 color;
  157. color.r = dot(yuv, vec3(1.164, 0.000, 1.596));
  158. color.g = dot(yuv, vec3(1.164, -0.391, -0.813));
  159. color.b = dot(yuv, vec3(1.164, 2.018, 0.000));
  160. color.a = 1.0;
  161. return gammaCorrectColor(color);
  162. }]],
  163. FOOTER = [[
  164. void main() {
  165. // fix crashing issue in OSX when _tex0_ is unused within effect()
  166. float dummy = Texel(_tex0_, vec2(.5)).r;
  167. // See Shader::checkSetScreenParams in Shader.cpp.
  168. vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w);
  169. gl_FragColor = effect(VaryingColor, _tex0_, VaryingTexCoord.st, pixelcoord);
  170. }]],
  171. FOOTER_MULTI_CANVAS = [[
  172. void main() {
  173. // fix crashing issue in OSX when _tex0_ is unused within effect()
  174. float dummy = Texel(_tex0_, vec2(.5)).r;
  175. // See Shader::checkSetScreenParams in Shader.cpp.
  176. vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w);
  177. effects(VaryingColor, _tex0_, VaryingTexCoord.st, pixelcoord);
  178. }]],
  179. }
  180. local function createShaderStageCode(stage, code, lang, gammacorrect, multicanvas)
  181. stage = stage:upper()
  182. local lines = {
  183. lang == "glsles" and GLSL.VERSION_ES or GLSL.VERSION,
  184. GLSL.SYNTAX,
  185. gammacorrect and "#define LOVE_GAMMA_CORRECT 1" or "",
  186. GLSL[stage].HEADER,
  187. GLSL.UNIFORMS,
  188. GLSL.FUNCTIONS,
  189. GLSL[stage].FUNCTIONS,
  190. lang == "glsles" and "#line 1" or "#line 0",
  191. code,
  192. multicanvas and GLSL[stage].FOOTER_MULTI_CANVAS or GLSL[stage].FOOTER,
  193. }
  194. return table_concat(lines, "\n")
  195. end
  196. local function isVertexCode(code)
  197. return code:match("vec4%s+position%s*%(") ~= nil
  198. end
  199. local function isPixelCode(code)
  200. if code:match("vec4%s+effect%s*%(") then
  201. return true
  202. elseif code:match("void%s+effects%s*%(") then
  203. -- function for rendering to multiple canvases simultaneously
  204. return true, true
  205. else
  206. return false
  207. end
  208. end
  209. function love.graphics._shaderCodeToGLSL(arg1, arg2)
  210. local vertexcode, pixelcode
  211. local is_multicanvas = false -- whether pixel code has "effects" function instead of "effect"
  212. if arg1 then
  213. if isVertexCode(arg1) then
  214. vertexcode = arg1 -- first arg contains vertex shader code
  215. end
  216. local ispixel, isMultiCanvas = isPixelCode(arg1)
  217. if ispixel then
  218. pixelcode = arg1 -- first arg contains pixel shader code
  219. is_multicanvas = isMultiCanvas
  220. end
  221. end
  222. if arg2 then
  223. if isVertexCode(arg2) then
  224. vertexcode = arg2 -- second arg contains vertex shader code
  225. end
  226. local ispixel, isMultiCanvas = isPixelCode(arg2)
  227. if ispixel then
  228. pixelcode = arg2 -- second arg contains pixel shader code
  229. is_multicanvas = isMultiCanvas
  230. end
  231. end
  232. local lang = "glsl"
  233. if love.graphics.getRendererInfo() == "OpenGL ES" then
  234. lang = "glsles"
  235. end
  236. local gammacorrect = love.graphics.isGammaCorrect()
  237. if vertexcode then
  238. vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gammacorrect)
  239. end
  240. if pixelcode then
  241. pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gammacorrect, is_multicanvas)
  242. end
  243. return vertexcode, pixelcode
  244. end
  245. function love.graphics._transformGLSLErrorMessages(message)
  246. local shadertype = message:match("Cannot compile (%a+) shader code")
  247. if not shadertype then return message end
  248. local lines = {"Cannot compile "..shadertype.." shader code:"}
  249. for l in message:gmatch("[^\n]+") do
  250. -- nvidia compiler message:
  251. -- 0(<linenumber>) : error/warning [NUMBER]: <error message>
  252. local linenumber, what, message = l:match("^0%((%d+)%)%s*:%s*(%w+)[^:]+:%s*(.+)$")
  253. if not linenumber then
  254. -- ati compiler message:
  255. -- ERROR 0:<linenumber>: error/warning(#[NUMBER]) [ERRORNAME]: <errormessage>
  256. linenumber, what, message = l:match("^%w+: 0:(%d+):%s*(%w+)%([^%)]+%)%s*(.+)$")
  257. if not linenumber then
  258. -- OSX compiler message (?):
  259. -- ERROR: 0:<linenumber>: <errormessage>
  260. what, linenumber, message = l:match("^(%w+): %d+:(%d+): (.+)$")
  261. end
  262. end
  263. if linenumber and what and message then
  264. lines[#lines+1] = ("Line %d: %s: %s"):format(linenumber, what, message)
  265. end
  266. end
  267. -- did not match any known error messages
  268. if #lines == 1 then return message end
  269. return table_concat(lines, "\n")
  270. end
  271. local defaultcode = {
  272. vertex = [[
  273. vec4 position(mat4 transform_proj, vec4 vertpos) {
  274. return transform_proj * vertpos;
  275. }]],
  276. pixel = [[
  277. vec4 effect(mediump vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
  278. return Texel(tex, texcoord) * vcolor;
  279. }]],
  280. videopixel = [[
  281. vec4 effect(mediump vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
  282. return VideoTexel(texcoord) * vcolor;
  283. }]],
  284. }
  285. local defaults = {}
  286. local defaults_gammacorrect = {}
  287. for _, lang in ipairs{"glsl", "glsles"} do
  288. for _, gammacorrect in ipairs{false, true} do
  289. local t = gammacorrect and defaults_gammacorrect or defaults
  290. t[lang] = {
  291. vertex = createShaderStageCode("VERTEX", defaultcode.vertex, lang, gammacorrect),
  292. pixel = createShaderStageCode("PIXEL", defaultcode.pixel, lang, gammacorrect, false),
  293. videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, lang, gammacorrect, false),
  294. }
  295. end
  296. end
  297. love.graphics._setDefaultShaderCode(defaults, defaults_gammacorrect)
  298. function love.graphics.newVideo(file, loadaudio)
  299. local video = love.graphics._newVideo(file)
  300. local source, success
  301. if loadaudio ~= false then
  302. success, source = pcall(love.audio.newSource, video:getStream():getFilename())
  303. end
  304. if success then
  305. video:setSource(source)
  306. elseif loadaudio == true then
  307. error("Video had no audio track", 2)
  308. else
  309. video:getStream():setSync()
  310. end
  311. return video
  312. end
  313. -- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
  314. --)luastring"--"