wrap_GraphicsShader.lua 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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-2020 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_insert = table.concat, table.insert
  21. local ipairs = ipairs
  22. local GLSL = {}
  23. GLSL.VERSION = { -- index using [target][gles]
  24. glsl1 = {[false]="#version 120", [true]="#version 100"},
  25. glsl3 = {[false]="#version 330 core", [true]="#version 300 es"},
  26. glsl4 = {[false]="#version 430 core", [true]="#version 310 es"},
  27. }
  28. GLSL.SYNTAX = [[
  29. #if !defined(GL_ES) && __VERSION__ < 140
  30. #define lowp
  31. #define mediump
  32. #define highp
  33. #endif
  34. #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
  35. #define LOVE_HIGHP_OR_MEDIUMP highp
  36. #else
  37. #define LOVE_HIGHP_OR_MEDIUMP mediump
  38. #endif
  39. #if __VERSION__ >= 300
  40. #define LOVE_IO_LOCATION(x) layout (location = x)
  41. #else
  42. #define LOVE_IO_LOCATION(x)
  43. #endif
  44. #define number float
  45. #define Image sampler2D
  46. #define ArrayImage sampler2DArray
  47. #define CubeImage samplerCube
  48. #define VolumeImage sampler3D
  49. #if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
  50. #define DepthImage sampler2DShadow
  51. #define DepthArrayImage sampler2DArrayShadow
  52. #define DepthCubeImage samplerCubeShadow
  53. #endif
  54. #define extern uniform
  55. #ifdef GL_EXT_texture_array
  56. #extension GL_EXT_texture_array : enable
  57. #endif
  58. #ifdef GL_OES_texture_3D
  59. #extension GL_OES_texture_3D : enable
  60. #endif
  61. #ifdef GL_OES_standard_derivatives
  62. #extension GL_OES_standard_derivatives : enable
  63. #endif
  64. ]]
  65. -- Uniforms shared by the vertex and pixel shader stages.
  66. GLSL.UNIFORMS = [[
  67. // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
  68. // but we can't guarantee that highp is always supported in fragment shaders...
  69. // We *really* don't want to use mediump for these in vertex shaders though.
  70. #ifdef LOVE_USE_UNIFORM_BUFFERS
  71. layout (std140) uniform love_UniformsPerDrawBuffer {
  72. highp vec4 love_UniformsPerDraw[13];
  73. };
  74. #else
  75. uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
  76. #endif
  77. // These are initialized in love_initializeBuiltinUniforms below. GLSL ES can't
  78. // do it as an initializer.
  79. LOVE_HIGHP_OR_MEDIUMP mat4 TransformMatrix;
  80. LOVE_HIGHP_OR_MEDIUMP mat4 ProjectionMatrix;
  81. LOVE_HIGHP_OR_MEDIUMP mat3 NormalMatrix;
  82. LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize;
  83. LOVE_HIGHP_OR_MEDIUMP vec4 ConstantColor;
  84. #define TransformProjectionMatrix (ProjectionMatrix * TransformMatrix)
  85. // Alternate names
  86. #define ViewSpaceFromLocal TransformMatrix
  87. #define ClipSpaceFromView ProjectionMatrix
  88. #define ClipSpaceFromLocal TransformProjectionMatrix
  89. #define ViewNormalFromLocal NormalMatrix
  90. void love_initializeBuiltinUniforms() {
  91. TransformMatrix = mat4(
  92. love_UniformsPerDraw[0],
  93. love_UniformsPerDraw[1],
  94. love_UniformsPerDraw[2],
  95. love_UniformsPerDraw[3]
  96. );
  97. ProjectionMatrix = mat4(
  98. love_UniformsPerDraw[4],
  99. love_UniformsPerDraw[5],
  100. love_UniformsPerDraw[6],
  101. love_UniformsPerDraw[7]
  102. );
  103. NormalMatrix = mat3(
  104. love_UniformsPerDraw[8].xyz,
  105. love_UniformsPerDraw[9].xyz,
  106. love_UniformsPerDraw[10].xyz
  107. );
  108. love_ScreenSize = love_UniformsPerDraw[11];
  109. ConstantColor = love_UniformsPerDraw[12];
  110. }
  111. ]]
  112. GLSL.FUNCTIONS = [[
  113. #ifdef GL_ES
  114. #if __VERSION__ >= 300 || defined(GL_EXT_texture_array)
  115. precision lowp sampler2DArray;
  116. #endif
  117. #if __VERSION__ >= 300 || defined(GL_OES_texture_3D)
  118. precision lowp sampler3D;
  119. #endif
  120. #if __VERSION__ >= 300
  121. precision lowp sampler2DShadow;
  122. precision lowp samplerCubeShadow;
  123. precision lowp sampler2DArrayShadow;
  124. #endif
  125. #endif
  126. #if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3)
  127. #define Texel texture
  128. #else
  129. #if __VERSION__ >= 130
  130. #define texture2D Texel
  131. #define texture3D Texel
  132. #define textureCube Texel
  133. #define texture2DArray Texel
  134. #define love_texture2D texture
  135. #define love_texture3D texture
  136. #define love_textureCube texture
  137. #define love_texture2DArray texture
  138. #else
  139. #define love_texture2D texture2D
  140. #define love_texture3D texture3D
  141. #define love_textureCube textureCube
  142. #define love_texture2DArray texture2DArray
  143. #endif
  144. vec4 Texel(sampler2D s, vec2 c) { return love_texture2D(s, c); }
  145. vec4 Texel(samplerCube s, vec3 c) { return love_textureCube(s, c); }
  146. #if __VERSION__ > 100 || defined(GL_OES_texture_3D)
  147. vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); }
  148. #endif
  149. #if __VERSION__ >= 130 || defined(GL_EXT_texture_array)
  150. vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); }
  151. #endif
  152. #ifdef PIXEL
  153. vec4 Texel(sampler2D s, vec2 c, float b) { return love_texture2D(s, c, b); }
  154. vec4 Texel(samplerCube s, vec3 c, float b) { return love_textureCube(s, c, b); }
  155. #if __VERSION__ > 100 || defined(GL_OES_texture_3D)
  156. vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); }
  157. #endif
  158. #if __VERSION__ >= 130 || defined(GL_EXT_texture_array)
  159. vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); }
  160. #endif
  161. #endif
  162. #define texture love_texture
  163. #endif
  164. float gammaToLinearPrecise(float c) {
  165. return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
  166. }
  167. vec3 gammaToLinearPrecise(vec3 c) {
  168. bvec3 leq = lessThanEqual(c, vec3(0.04045));
  169. c.r = leq.r ? c.r / 12.92 : pow((c.r + 0.055) / 1.055, 2.4);
  170. c.g = leq.g ? c.g / 12.92 : pow((c.g + 0.055) / 1.055, 2.4);
  171. c.b = leq.b ? c.b / 12.92 : pow((c.b + 0.055) / 1.055, 2.4);
  172. return c;
  173. }
  174. vec4 gammaToLinearPrecise(vec4 c) { return vec4(gammaToLinearPrecise(c.rgb), c.a); }
  175. float linearToGammaPrecise(float c) {
  176. return c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;
  177. }
  178. vec3 linearToGammaPrecise(vec3 c) {
  179. bvec3 lt = lessThanEqual(c, vec3(0.0031308));
  180. c.r = lt.r ? c.r * 12.92 : 1.055 * pow(c.r, 1.0 / 2.4) - 0.055;
  181. c.g = lt.g ? c.g * 12.92 : 1.055 * pow(c.g, 1.0 / 2.4) - 0.055;
  182. c.b = lt.b ? c.b * 12.92 : 1.055 * pow(c.b, 1.0 / 2.4) - 0.055;
  183. return c;
  184. }
  185. vec4 linearToGammaPrecise(vec4 c) { return vec4(linearToGammaPrecise(c.rgb), c.a); }
  186. // http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
  187. mediump float gammaToLinearFast(mediump float c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); }
  188. mediump vec3 gammaToLinearFast(mediump vec3 c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); }
  189. mediump vec4 gammaToLinearFast(mediump vec4 c) { return vec4(gammaToLinearFast(c.rgb), c.a); }
  190. mediump float linearToGammaFast(mediump float c) { return max(1.055 * pow(max(c, 0.0), 0.41666666) - 0.055, 0.0); }
  191. mediump vec3 linearToGammaFast(mediump vec3 c) { return max(1.055 * pow(max(c, vec3(0.0)), vec3(0.41666666)) - 0.055, vec3(0.0)); }
  192. mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c.rgb), c.a); }
  193. #define gammaToLinear gammaToLinearFast
  194. #define linearToGamma linearToGammaFast
  195. #ifdef LOVE_GAMMA_CORRECT
  196. #define gammaCorrectColor gammaToLinear
  197. #define unGammaCorrectColor linearToGamma
  198. #define gammaCorrectColorPrecise gammaToLinearPrecise
  199. #define unGammaCorrectColorPrecise linearToGammaPrecise
  200. #define gammaCorrectColorFast gammaToLinearFast
  201. #define unGammaCorrectColorFast linearToGammaFast
  202. #else
  203. #define gammaCorrectColor
  204. #define unGammaCorrectColor
  205. #define gammaCorrectColorPrecise
  206. #define unGammaCorrectColorPrecise
  207. #define gammaCorrectColorFast
  208. #define unGammaCorrectColorFast
  209. #endif]]
  210. GLSL.VERTEX = {
  211. HEADER = [[
  212. #define love_Position gl_Position
  213. #if __VERSION__ >= 130
  214. #define attribute in
  215. #define varying out
  216. #ifndef LOVE_GLSL1_ON_GLSL3
  217. #define love_VertexID gl_VertexID
  218. #define love_InstanceID gl_InstanceID
  219. #endif
  220. #endif
  221. #ifdef GL_ES
  222. uniform mediump float love_PointSize;
  223. #endif]],
  224. FUNCTIONS = [[
  225. void setPointSize() {
  226. #ifdef GL_ES
  227. gl_PointSize = love_PointSize;
  228. #endif
  229. }]],
  230. MAIN = [[
  231. LOVE_IO_LOCATION(0) attribute vec4 VertexPosition;
  232. LOVE_IO_LOCATION(1) attribute vec4 VertexTexCoord;
  233. LOVE_IO_LOCATION(2) attribute vec4 VertexColor;
  234. varying vec4 VaryingTexCoord;
  235. varying vec4 VaryingColor;
  236. vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
  237. void main() {
  238. love_initializeBuiltinUniforms();
  239. VaryingTexCoord = VertexTexCoord;
  240. VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor;
  241. setPointSize();
  242. love_Position = position(ClipSpaceFromLocal, VertexPosition);
  243. }]],
  244. }
  245. GLSL.PIXEL = {
  246. HEADER = [[
  247. #ifdef GL_ES
  248. precision mediump float;
  249. #endif
  250. #define love_MaxRenderTargets gl_MaxDrawBuffers
  251. #if __VERSION__ >= 130
  252. #define varying in
  253. // Some drivers seem to make the pixel shader do more work when multiple
  254. // pixel shader outputs are defined, even when only one is actually used.
  255. // TODO: We should use reflection or something instead of this, to determine
  256. // how many outputs are actually used in the shader code.
  257. #ifdef LOVE_MULTI_RENDER_TARGETS
  258. LOVE_IO_LOCATION(0) out vec4 love_RenderTargets[love_MaxRenderTargets];
  259. #define love_PixelColor love_RenderTargets[0]
  260. #else
  261. LOVE_IO_LOCATION(0) out vec4 love_PixelColor;
  262. #endif
  263. #else
  264. #ifdef LOVE_MULTI_RENDER_TARGETS
  265. #define love_RenderTargets gl_FragData
  266. #endif
  267. #define love_PixelColor gl_FragColor
  268. #endif
  269. // Legacy
  270. #define love_MaxCanvases love_MaxRenderTargets
  271. #define love_Canvases love_RenderTargets
  272. #ifdef LOVE_MULTI_RENDER_TARGETS
  273. #define LOVE_MULTI_CANVASES 1
  274. #endif
  275. // See Shader::updateScreenParams in Shader.cpp.
  276. #define love_PixelCoord (vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w))]],
  277. FUNCTIONS = [[
  278. uniform sampler2D love_VideoYChannel;
  279. uniform sampler2D love_VideoCbChannel;
  280. uniform sampler2D love_VideoCrChannel;
  281. vec4 VideoTexel(vec2 texcoords) {
  282. vec3 yuv;
  283. yuv[0] = Texel(love_VideoYChannel, texcoords).r;
  284. yuv[1] = Texel(love_VideoCbChannel, texcoords).r;
  285. yuv[2] = Texel(love_VideoCrChannel, texcoords).r;
  286. yuv += vec3(-0.0627451017, -0.501960814, -0.501960814);
  287. vec4 color;
  288. color.r = dot(yuv, vec3(1.164, 0.000, 1.596));
  289. color.g = dot(yuv, vec3(1.164, -0.391, -0.813));
  290. color.b = dot(yuv, vec3(1.164, 2.018, 0.000));
  291. color.a = 1.0;
  292. return gammaCorrectColor(color);
  293. }]],
  294. MAIN = [[
  295. uniform sampler2D MainTex;
  296. varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
  297. varying mediump vec4 VaryingColor;
  298. vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
  299. void main() {
  300. love_initializeBuiltinUniforms();
  301. love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
  302. }]],
  303. MAIN_CUSTOM = [[
  304. varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
  305. varying mediump vec4 VaryingColor;
  306. void effect();
  307. void main() {
  308. love_initializeBuiltinUniforms();
  309. effect();
  310. }]],
  311. }
  312. local function getLanguageTarget(code)
  313. if not code then return nil end
  314. return (code:match("^%s*#pragma language (%w+)")) or "glsl1"
  315. end
  316. local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, custom, multirendertarget, useubo)
  317. stage = stage:upper()
  318. local lines = {
  319. GLSL.VERSION[lang][gles],
  320. "#define " ..stage .. " " .. stage,
  321. glsl1on3 and "#define LOVE_GLSL1_ON_GLSL3 1" or "",
  322. gammacorrect and "#define LOVE_GAMMA_CORRECT 1" or "",
  323. multirendertarget and "#define LOVE_MULTI_RENDER_TARGETS 1" or "",
  324. useubo and "#define LOVE_USE_UNIFORM_BUFFERS 1" or "",
  325. GLSL.SYNTAX,
  326. GLSL[stage].HEADER,
  327. GLSL.UNIFORMS,
  328. GLSL.FUNCTIONS,
  329. GLSL[stage].FUNCTIONS,
  330. custom and GLSL[stage].MAIN_CUSTOM or GLSL[stage].MAIN,
  331. ((lang == "glsl1" or glsl1on3) and not gles) and "#line 0" or "#line 1",
  332. code,
  333. }
  334. return table_concat(lines, "\n")
  335. end
  336. local function isVertexCode(code)
  337. return code:match("vec4%s+position%s*%(") ~= nil
  338. end
  339. local function isPixelCode(code)
  340. if code:match("vec4%s+effect%s*%(") then
  341. return true
  342. elseif code:match("void%s+effect%s*%(") then -- custom effect function
  343. local mrt = (code:match("love_RenderTargets") ~= nil) or (code:match("love_Canvases") ~= nil)
  344. return true, true, mrt
  345. else
  346. return false
  347. end
  348. end
  349. function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
  350. local vertexcode, pixelcode
  351. local is_custompixel = false -- whether pixel code has "effects" function instead of "effect"
  352. local is_multicanvas = false
  353. if arg1 then
  354. if isVertexCode(arg1) then
  355. vertexcode = arg1 -- first arg contains vertex shader code
  356. end
  357. local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg1)
  358. if ispixel then
  359. pixelcode = arg1 -- first arg contains pixel shader code
  360. is_custompixel, is_multicanvas = isCustomPixel, isMultiCanvas
  361. end
  362. end
  363. if arg2 then
  364. if isVertexCode(arg2) then
  365. vertexcode = arg2 -- second arg contains vertex shader code
  366. end
  367. local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg2)
  368. if ispixel then
  369. pixelcode = arg2 -- second arg contains pixel shader code
  370. is_custompixel, is_multicanvas = isCustomPixel, isMultiCanvas
  371. end
  372. end
  373. local graphicsfeatures = love.graphics.getSupported()
  374. local supportsGLSL3 = graphicsfeatures.glsl3
  375. local supportsGLSL4 = graphicsfeatures.glsl4
  376. local gammacorrect = love.graphics.isGammaCorrect()
  377. local renderer = love.graphics.getRenderer()
  378. local useubo = renderer == "Metal"
  379. local targetlang = getLanguageTarget(pixelcode or vertexcode)
  380. if getLanguageTarget(vertexcode or pixelcode) ~= targetlang then
  381. error("vertex and pixel shader languages must match", 2)
  382. end
  383. if targetlang == "glsl3" and not supportsGLSL3 then
  384. error("GLSL 3 shaders are not supported on this system.", 2)
  385. end
  386. if targetlang == "glsl4" and not supportsGLSL4 then
  387. error("GLSL 4 shaders are not supported on this system.", 2)
  388. end
  389. if targetlang ~= nil and not GLSL.VERSION[targetlang] then
  390. error("Invalid shader language: " .. targetlang, 2)
  391. end
  392. local lang = targetlang or "glsl1"
  393. local glsl1on3 = false
  394. if lang == "glsl1" and supportsGLSL3 then
  395. lang = "glsl3"
  396. glsl1on3 = true
  397. end
  398. if vertexcode then
  399. vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect, false, false, useubo)
  400. end
  401. if pixelcode then
  402. pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_custompixel, is_multicanvas, useubo)
  403. end
  404. return vertexcode, pixelcode
  405. end
  406. local defaultcode = {
  407. vertex = [[
  408. vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) {
  409. return clipSpaceFromLocal * localPosition;
  410. }]],
  411. pixel = [[
  412. vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
  413. return Texel(tex, texcoord) * vcolor;
  414. }]],
  415. videopixel = [[
  416. void effect() {
  417. love_PixelColor = VideoTexel(VaryingTexCoord.xy) * VaryingColor;
  418. }]],
  419. arraypixel = [[
  420. uniform ArrayImage MainTex;
  421. void effect() {
  422. love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor;
  423. }]],
  424. }
  425. local defaults = {}
  426. local defaults_gammacorrect = {}
  427. local langs = {
  428. glsl1 = {target="glsl1", gles=false},
  429. essl1 = {target="glsl1", gles=true},
  430. glsl3 = {target="glsl3", gles=false},
  431. essl3 = {target="glsl3", gles=true},
  432. }
  433. -- FIXME: this is temporary until a glslang pull request is merged in.
  434. local useubo = true
  435. for lang, info in pairs(langs) do
  436. for _, gammacorrect in ipairs{false, true} do
  437. local t = gammacorrect and defaults_gammacorrect or defaults
  438. t[lang] = {
  439. vertex = createShaderStageCode("VERTEX", defaultcode.vertex, info.target, info.gles, false, gammacorrect, false, false, useubo),
  440. pixel = createShaderStageCode("PIXEL", defaultcode.pixel, info.target, info.gles, false, gammacorrect, false, false, useubo),
  441. videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, info.target, info.gles, false, gammacorrect, true, false, useubo),
  442. arraypixel = createShaderStageCode("PIXEL", defaultcode.arraypixel, info.target, info.gles, false, gammacorrect, true, false, useubo),
  443. }
  444. end
  445. end
  446. love.graphics._setDefaultShaderCode(defaults, defaults_gammacorrect)
  447. -- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
  448. --)luastring"--"