diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 663a17edf..672d38bb2 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -1850,6 +1850,7 @@ FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = ""; }; FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = ""; }; FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = ""; }; + FA665DC321C34C900074BBD6 /* wrap_GraphicsShader.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = wrap_GraphicsShader.lua; sourceTree = ""; }; FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = ""; }; FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = ""; }; FA6A2B681F5F7F560074C308 /* DataView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataView.cpp; sourceTree = ""; }; @@ -2817,6 +2818,7 @@ FADF54391E3DAFF700012CC0 /* wrap_Graphics.cpp */, FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */, FADF54371E3DAFBA00012CC0 /* wrap_Graphics.lua */, + FA665DC321C34C900074BBD6 /* wrap_GraphicsShader.lua */, FADF54191E3DA46C00012CC0 /* wrap_Image.cpp */, FADF541A1E3DA46C00012CC0 /* wrap_Image.h */, FADF54281E3DAADA00012CC0 /* wrap_Mesh.cpp */, diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 08af41121..525e4dc7c 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -45,6 +45,11 @@ static const char graphics_lua[] = #include "wrap_Graphics.lua" ; +// This is in a separate file because VS2013 has a 16KB limit for raw strings.. +static const char graphics_shader_lua[] = +#include "wrap_GraphicsShader.lua" +; + namespace love { namespace graphics @@ -3075,6 +3080,11 @@ extern "C" int luaopen_love_graphics(lua_State *L) else lua_error(L); + if (luaL_loadbuffer(L, (const char *)graphics_shader_lua, sizeof(graphics_shader_lua), "wrap_GraphicsShader.lua") == 0) + lua_call(L, 0, 0); + else + lua_error(L); + return n; } diff --git a/src/modules/graphics/wrap_Graphics.lua b/src/modules/graphics/wrap_Graphics.lua index b6d7375dc..ee23a9e42 100644 --- a/src/modules/graphics/wrap_Graphics.lua +++ b/src/modules/graphics/wrap_Graphics.lua @@ -22,482 +22,6 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. --]] -local table_concat = table.concat -local ipairs = ipairs - --- SHADERS - -local GLSL = {} - -GLSL.VERSION = { -- index using [target][gles] - glsl1 = {[false]="#version 120", [true]="#version 100"}, - glsl3 = {[false]="#version 330 core", [true]="#version 300 es"}, -} - -GLSL.SYNTAX = [[ -#if !defined(GL_ES) && __VERSION__ < 140 - #define lowp - #define mediump - #define highp -#endif -#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) - #define LOVE_HIGHP_OR_MEDIUMP highp -#else - #define LOVE_HIGHP_OR_MEDIUMP mediump -#endif -#define number float -#define Image sampler2D -#define ArrayImage sampler2DArray -#define CubeImage samplerCube -#define VolumeImage sampler3D -#if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3) - #define DepthImage sampler2DShadow - #define DepthArrayImage sampler2DArrayShadow - #define DepthCubeImage samplerCubeShadow -#endif -#define extern uniform -#ifdef GL_EXT_texture_array -#extension GL_EXT_texture_array : enable -#endif -#ifdef GL_OES_texture_3D -#extension GL_OES_texture_3D : enable -#endif -#ifdef GL_OES_standard_derivatives -#extension GL_OES_standard_derivatives : enable -#endif -]] - --- Uniforms shared by the vertex and pixel shader stages. -GLSL.UNIFORMS = [[ -// According to the GLSL ES 1.0 spec, uniform precision must match between stages, -// but we can't guarantee that highp is always supported in fragment shaders... -// We *really* don't want to use mediump for these in vertex shaders though. -uniform LOVE_HIGHP_OR_MEDIUMP mat4 ViewSpaceFromLocal; -uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromView; -uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromLocal; -uniform LOVE_HIGHP_OR_MEDIUMP mat3 ViewNormalFromLocal; -uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize; - -// Compatibility -#define TransformMatrix ViewSpaceFromLocal -#define ProjectionMatrix ClipSpaceFromView -#define TransformProjectionMatrix ClipSpaceFromLocal -#define NormalMatrix ViewNormalFromLocal -]] - -GLSL.FUNCTIONS = [[ -#ifdef GL_ES - #if __VERSION__ >= 300 || defined(GL_EXT_texture_array) - precision lowp sampler2DArray; - #endif - #if __VERSION__ >= 300 || defined(GL_OES_texture_3D) - precision lowp sampler3D; - #endif - #if __VERSION__ >= 300 - precision lowp sampler2DShadow; - precision lowp samplerCubeShadow; - precision lowp sampler2DArrayShadow; - #endif -#endif - -#if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3) - #define Texel texture -#else - #if __VERSION__ >= 130 - #define texture2D Texel - #define texture3D Texel - #define textureCube Texel - #define texture2DArray Texel - #define love_texture2D texture - #define love_texture3D texture - #define love_textureCube texture - #define love_texture2DArray texture - #else - #define love_texture2D texture2D - #define love_texture3D texture3D - #define love_textureCube textureCube - #define love_texture2DArray texture2DArray - #endif - vec4 Texel(sampler2D s, vec2 c) { return love_texture2D(s, c); } - vec4 Texel(samplerCube s, vec3 c) { return love_textureCube(s, c); } - #if __VERSION__ > 100 || defined(GL_OES_texture_3D) - vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); } - #endif - #if __VERSION__ >= 130 || defined(GL_EXT_texture_array) - vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); } - #endif - #ifdef PIXEL - vec4 Texel(sampler2D s, vec2 c, float b) { return love_texture2D(s, c, b); } - vec4 Texel(samplerCube s, vec3 c, float b) { return love_textureCube(s, c, b); } - #if __VERSION__ > 100 || defined(GL_OES_texture_3D) - vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); } - #endif - #if __VERSION__ >= 130 || defined(GL_EXT_texture_array) - vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); } - #endif - #endif - #define texture love_texture -#endif - -float gammaToLinearPrecise(float c) { - return c <= 0.04045 ? c * 0.077399380804954 : pow((c + 0.055) * 0.9478672985782, 2.4); -} -vec3 gammaToLinearPrecise(vec3 c) { - bvec3 leq = lessThanEqual(c, vec3(0.04045)); - c.r = leq.r ? c.r * 0.077399380804954 : pow((c.r + 0.055) * 0.9478672985782, 2.4); - c.g = leq.g ? c.g * 0.077399380804954 : pow((c.g + 0.055) * 0.9478672985782, 2.4); - c.b = leq.b ? c.b * 0.077399380804954 : pow((c.b + 0.055) * 0.9478672985782, 2.4); - return c; -} -vec4 gammaToLinearPrecise(vec4 c) { return vec4(gammaToLinearPrecise(c.rgb), c.a); } -float linearToGammaPrecise(float c) { - return c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055; -} -vec3 linearToGammaPrecise(vec3 c) { - bvec3 lt = lessThanEqual(c, vec3(0.0031308)); - c.r = lt.r ? c.r * 12.92 : 1.055 * pow(c.r, 1.0 / 2.4) - 0.055; - c.g = lt.g ? c.g * 12.92 : 1.055 * pow(c.g, 1.0 / 2.4) - 0.055; - c.b = lt.b ? c.b * 12.92 : 1.055 * pow(c.b, 1.0 / 2.4) - 0.055; - return c; -} -vec4 linearToGammaPrecise(vec4 c) { return vec4(linearToGammaPrecise(c.rgb), c.a); } - -// http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1 - -mediump float gammaToLinearFast(mediump float c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); } -mediump vec3 gammaToLinearFast(mediump vec3 c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); } -mediump vec4 gammaToLinearFast(mediump vec4 c) { return vec4(gammaToLinearFast(c.rgb), c.a); } - -mediump float linearToGammaFast(mediump float c) { return max(1.055 * pow(max(c, 0.0), 0.41666666) - 0.055, 0.0); } -mediump vec3 linearToGammaFast(mediump vec3 c) { return max(1.055 * pow(max(c, vec3(0.0)), vec3(0.41666666)) - 0.055, vec3(0.0)); } -mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c.rgb), c.a); } - -#define gammaToLinear gammaToLinearFast -#define linearToGamma linearToGammaFast - -#ifdef LOVE_GAMMA_CORRECT - #define gammaCorrectColor gammaToLinear - #define unGammaCorrectColor linearToGamma - #define gammaCorrectColorPrecise gammaToLinearPrecise - #define unGammaCorrectColorPrecise linearToGammaPrecise - #define gammaCorrectColorFast gammaToLinearFast - #define unGammaCorrectColorFast linearToGammaFast -#else - #define gammaCorrectColor - #define unGammaCorrectColor - #define gammaCorrectColorPrecise - #define unGammaCorrectColorPrecise - #define gammaCorrectColorFast - #define unGammaCorrectColorFast -#endif]] - -GLSL.VERTEX = { - HEADER = [[ -#define love_Position gl_Position - -#if __VERSION__ >= 130 - #define attribute in - #define varying out - #ifndef LOVE_GLSL1_ON_GLSL3 - #define love_VertexID gl_VertexID - #define love_InstanceID gl_InstanceID - #endif -#endif - -#ifdef GL_ES - uniform mediump float love_PointSize; -#endif]], - - FUNCTIONS = [[ -void setPointSize() { -#ifdef GL_ES - gl_PointSize = love_PointSize; -#endif -}]], - - MAIN = [[ -attribute vec4 VertexPosition; -attribute vec4 VertexTexCoord; -attribute vec4 VertexColor; -attribute vec4 ConstantColor; - -varying vec4 VaryingTexCoord; -varying vec4 VaryingColor; - -vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition); - -void main() { - VaryingTexCoord = VertexTexCoord; - VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; - setPointSize(); - love_Position = position(ClipSpaceFromLocal, VertexPosition); -}]], -} - -GLSL.PIXEL = { - HEADER = [[ -#ifdef GL_ES - precision mediump float; -#endif - -#define love_MaxCanvases gl_MaxDrawBuffers - -#if __VERSION__ >= 130 - #define varying in - // Some drivers seem to make the pixel shader do more work when multiple - // pixel shader outputs are defined, even when only one is actually used. - // TODO: We should use reflection or something instead of this, to determine - // how many outputs are actually used in the shader code. - #ifdef LOVE_MULTI_CANVAS - layout(location = 0) out vec4 love_Canvases[love_MaxCanvases]; - #define love_PixelColor love_Canvases[0] - #else - layout(location = 0) out vec4 love_PixelColor; - #endif -#else - #ifdef LOVE_MULTI_CANVAS - #define love_Canvases gl_FragData - #endif - #define love_PixelColor gl_FragColor -#endif - -// See Shader::updateScreenParams in Shader.cpp. -#define love_PixelCoord (vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w))]], - - FUNCTIONS = [[ -uniform sampler2D love_VideoYChannel; -uniform sampler2D love_VideoCbChannel; -uniform sampler2D love_VideoCrChannel; - -vec4 VideoTexel(vec2 texcoords) { - vec3 yuv; - yuv[0] = Texel(love_VideoYChannel, texcoords).r; - yuv[1] = Texel(love_VideoCbChannel, texcoords).r; - yuv[2] = Texel(love_VideoCrChannel, texcoords).r; - yuv += vec3(-0.0627451017, -0.501960814, -0.501960814); - - vec4 color; - color.r = dot(yuv, vec3(1.164, 0.000, 1.596)); - color.g = dot(yuv, vec3(1.164, -0.391, -0.813)); - color.b = dot(yuv, vec3(1.164, 2.018, 0.000)); - color.a = 1.0; - - return gammaCorrectColor(color); -}]], - - MAIN = [[ -uniform sampler2D MainTex; -varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; -varying mediump vec4 VaryingColor; - -vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord); - -void main() { - love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord); -}]], - - MAIN_CUSTOM = [[ -varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; -varying mediump vec4 VaryingColor; - -void effect(); - -void main() { - effect(); -}]], -} - -local function getLanguageTarget(code) - if not code then return nil end - return (code:match("^%s*#pragma language (%w+)")) or "glsl1" -end - -local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, custom, multicanvas) - stage = stage:upper() - local lines = { - GLSL.VERSION[lang][gles], - "#define " ..stage .. " " .. stage, - glsl1on3 and "#define LOVE_GLSL1_ON_GLSL3 1" or "", - gammacorrect and "#define LOVE_GAMMA_CORRECT 1" or "", - multicanvas and "#define LOVE_MULTI_CANVAS 1" or "", - GLSL.SYNTAX, - GLSL[stage].HEADER, - GLSL.UNIFORMS, - GLSL.FUNCTIONS, - GLSL[stage].FUNCTIONS, - custom and GLSL[stage].MAIN_CUSTOM or GLSL[stage].MAIN, - ((lang == "glsl1" or glsl1on3) and not gles) and "#line 0" or "#line 1", - code, - } - return table_concat(lines, "\n") -end - -local function isVertexCode(code) - return code:match("vec4%s+position%s*%(") ~= nil -end - -local function isPixelCode(code) - if code:match("vec4%s+effect%s*%(") then - return true - elseif code:match("void%s+effect%s*%(") then -- custom effect function - local multicanvas = code:match("love_Canvases") ~= nil - return true, true, multicanvas - else - return false - end -end - -function love.graphics._shaderCodeToGLSL(gles, arg1, arg2) - local vertexcode, pixelcode - local is_custompixel = false -- whether pixel code has "effects" function instead of "effect" - local is_multicanvas = false - - if arg1 then - if isVertexCode(arg1) then - vertexcode = arg1 -- first arg contains vertex shader code - end - - local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg1) - if ispixel then - pixelcode = arg1 -- first arg contains pixel shader code - is_custompixel = isCustomPixel - is_multicanvas = isMultiCanvas - end - end - - if arg2 then - if isVertexCode(arg2) then - vertexcode = arg2 -- second arg contains vertex shader code - end - - local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg2) - if ispixel then - pixelcode = arg2 -- second arg contains pixel shader code - is_custompixel = isCustomPixel - is_multicanvas = isMultiCanvas - end - end - - local supportsGLSL3 = love.graphics.getSupported().glsl3 - local gammacorrect = love.graphics.isGammaCorrect() - - local targetlang = getLanguageTarget(pixelcode or vertexcode) - if getLanguageTarget(vertexcode or pixelcode) ~= targetlang then - error("vertex and pixel shader languages must match", 2) - end - - if targetlang == "glsl3" and not supportsGLSL3 then - error("GLSL 3 shaders are not supported on this system!", 2) - end - - if targetlang ~= nil and not GLSL.VERSION[targetlang] then - error("Invalid shader language: " .. targetlang, 2) - end - - local lang = targetlang or "glsl1" - local glsl1on3 = false - if lang == "glsl1" and supportsGLSL3 then - lang = "glsl3" - glsl1on3 = true - end - - if vertexcode then - vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect) - end - if pixelcode then - pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_custompixel, is_multicanvas) - end - - return vertexcode, pixelcode -end - -function love.graphics._transformGLSLErrorMessages(message) - local compiling = true - local shadertype = message:match("Cannot compile (%a+) shader code") - if not shadertype then - compiling = false - shadertype = message:match("Error validating (%a+) shader") - end - if not shadertype then return message end - local lines = {} - if compiling then - lines[#lines+1] = "Cannot compile "..shadertype.." shader code:" - else - lines[#lines+1] = "Error validating "..shadertype.." shader code:" - end - for l in message:gmatch("[^\n]+") do - -- nvidia compiler message: - -- 0() : error/warning [NUMBER]: - local linenumber, what, message = l:match("^0%((%d+)%)%s*:%s*(%w+)[^:]+:%s*(.+)$") - if not linenumber then - -- ati compiler message: - -- ERROR 0:: error/warning(#[NUMBER]) [ERRORNAME]: - linenumber, what, message = l:match("^%w+: 0:(%d+):%s*(%w+)%([^%)]+%)%s*(.+)$") - end - if not linenumber then - -- OSX compiler message (?): - -- ERROR: 0:: - what, linenumber, message = l:match("^(%w+): %d+:(%d+): (.+)$") - end - if not linenumber and l:match("^ERROR:") then - what = l - end - if linenumber and what and message then - lines[#lines+1] = ("Line %d: %s: %s"):format(linenumber, what, message) - elseif what then - lines[#lines+1] = what - end - end - -- did not match any known error messages - if #lines == 1 then return message end - return table_concat(lines, "\n") -end - -local defaultcode = { - vertex = [[ -vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) { - return clipSpaceFromLocal * localPosition; -}]], - pixel = [[ -vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) { - return Texel(tex, texcoord) * vcolor; -}]], - videopixel = [[ -void effect() { - love_PixelColor = VideoTexel(VaryingTexCoord.xy) * VaryingColor; -}]], - arraypixel = [[ -uniform ArrayImage MainTex; -void effect() { - love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor; -}]], -} - -local defaults = {} -local defaults_gammacorrect = {} - -local langs = { - glsl1 = {target="glsl1", gles=false}, - essl1 = {target="glsl1", gles=true}, - glsl3 = {target="glsl3", gles=false}, - essl3 = {target="glsl3", gles=true}, -} - -for lang, info in pairs(langs) do - for _, gammacorrect in ipairs{false, true} do - local t = gammacorrect and defaults_gammacorrect or defaults - t[lang] = { - vertex = createShaderStageCode("VERTEX", defaultcode.vertex, info.target, info.gles, false, gammacorrect), - pixel = createShaderStageCode("PIXEL", defaultcode.pixel, info.target, info.gles, false, gammacorrect, false), - videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, info.target, info.gles, false, gammacorrect, true), - arraypixel = createShaderStageCode("PIXEL", defaultcode.arraypixel, info.target, info.gles, false, gammacorrect, true), - } - end -end - -love.graphics._setDefaultShaderCode(defaults, defaults_gammacorrect) - - function love.graphics.newVideo(file, settings) settings = settings == nil and {} or settings if type(settings) ~= "table" then error("bad argument #2 to newVideo (expected table)", 2) end diff --git a/src/modules/graphics/wrap_GraphicsShader.lua b/src/modules/graphics/wrap_GraphicsShader.lua new file mode 100644 index 000000000..520605faf --- /dev/null +++ b/src/modules/graphics/wrap_GraphicsShader.lua @@ -0,0 +1,490 @@ +R"luastring"--( +-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string. +-- There is a matching delimiter at the bottom of the file. + +--[[ +Copyright (c) 2006-2018 LOVE Development Team + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +--]] + +local table_concat = table.concat +local ipairs = ipairs + +local GLSL = {} + +GLSL.VERSION = { -- index using [target][gles] + glsl1 = {[false]="#version 120", [true]="#version 100"}, + glsl3 = {[false]="#version 330 core", [true]="#version 300 es"}, +} + +GLSL.SYNTAX = [[ +#if !defined(GL_ES) && __VERSION__ < 140 + #define lowp + #define mediump + #define highp +#endif +#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) + #define LOVE_HIGHP_OR_MEDIUMP highp +#else + #define LOVE_HIGHP_OR_MEDIUMP mediump +#endif +#define number float +#define Image sampler2D +#define ArrayImage sampler2DArray +#define CubeImage samplerCube +#define VolumeImage sampler3D +#if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3) + #define DepthImage sampler2DShadow + #define DepthArrayImage sampler2DArrayShadow + #define DepthCubeImage samplerCubeShadow +#endif +#define extern uniform +#ifdef GL_EXT_texture_array +#extension GL_EXT_texture_array : enable +#endif +#ifdef GL_OES_texture_3D +#extension GL_OES_texture_3D : enable +#endif +#ifdef GL_OES_standard_derivatives +#extension GL_OES_standard_derivatives : enable +#endif +]] + +-- Uniforms shared by the vertex and pixel shader stages. +GLSL.UNIFORMS = [[ +// According to the GLSL ES 1.0 spec, uniform precision must match between stages, +// but we can't guarantee that highp is always supported in fragment shaders... +// We *really* don't want to use mediump for these in vertex shaders though. +uniform LOVE_HIGHP_OR_MEDIUMP mat4 ViewSpaceFromLocal; +uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromView; +uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromLocal; +uniform LOVE_HIGHP_OR_MEDIUMP mat3 ViewNormalFromLocal; +uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize; + +// Compatibility +#define TransformMatrix ViewSpaceFromLocal +#define ProjectionMatrix ClipSpaceFromView +#define TransformProjectionMatrix ClipSpaceFromLocal +#define NormalMatrix ViewNormalFromLocal +]] + +GLSL.FUNCTIONS = [[ +#ifdef GL_ES + #if __VERSION__ >= 300 || defined(GL_EXT_texture_array) + precision lowp sampler2DArray; + #endif + #if __VERSION__ >= 300 || defined(GL_OES_texture_3D) + precision lowp sampler3D; + #endif + #if __VERSION__ >= 300 + precision lowp sampler2DShadow; + precision lowp samplerCubeShadow; + precision lowp sampler2DArrayShadow; + #endif +#endif + +#if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3) + #define Texel texture +#else + #if __VERSION__ >= 130 + #define texture2D Texel + #define texture3D Texel + #define textureCube Texel + #define texture2DArray Texel + #define love_texture2D texture + #define love_texture3D texture + #define love_textureCube texture + #define love_texture2DArray texture + #else + #define love_texture2D texture2D + #define love_texture3D texture3D + #define love_textureCube textureCube + #define love_texture2DArray texture2DArray + #endif + vec4 Texel(sampler2D s, vec2 c) { return love_texture2D(s, c); } + vec4 Texel(samplerCube s, vec3 c) { return love_textureCube(s, c); } + #if __VERSION__ > 100 || defined(GL_OES_texture_3D) + vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); } + #endif + #if __VERSION__ >= 130 || defined(GL_EXT_texture_array) + vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); } + #endif + #ifdef PIXEL + vec4 Texel(sampler2D s, vec2 c, float b) { return love_texture2D(s, c, b); } + vec4 Texel(samplerCube s, vec3 c, float b) { return love_textureCube(s, c, b); } + #if __VERSION__ > 100 || defined(GL_OES_texture_3D) + vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); } + #endif + #if __VERSION__ >= 130 || defined(GL_EXT_texture_array) + vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); } + #endif + #endif + #define texture love_texture +#endif + +float gammaToLinearPrecise(float c) { + return c <= 0.04045 ? c * 0.077399380804954 : pow((c + 0.055) * 0.9478672985782, 2.4); +} +vec3 gammaToLinearPrecise(vec3 c) { + bvec3 leq = lessThanEqual(c, vec3(0.04045)); + c.r = leq.r ? c.r * 0.077399380804954 : pow((c.r + 0.055) * 0.9478672985782, 2.4); + c.g = leq.g ? c.g * 0.077399380804954 : pow((c.g + 0.055) * 0.9478672985782, 2.4); + c.b = leq.b ? c.b * 0.077399380804954 : pow((c.b + 0.055) * 0.9478672985782, 2.4); + return c; +} +vec4 gammaToLinearPrecise(vec4 c) { return vec4(gammaToLinearPrecise(c.rgb), c.a); } +float linearToGammaPrecise(float c) { + return c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055; +} +vec3 linearToGammaPrecise(vec3 c) { + bvec3 lt = lessThanEqual(c, vec3(0.0031308)); + c.r = lt.r ? c.r * 12.92 : 1.055 * pow(c.r, 1.0 / 2.4) - 0.055; + c.g = lt.g ? c.g * 12.92 : 1.055 * pow(c.g, 1.0 / 2.4) - 0.055; + c.b = lt.b ? c.b * 12.92 : 1.055 * pow(c.b, 1.0 / 2.4) - 0.055; + return c; +} +vec4 linearToGammaPrecise(vec4 c) { return vec4(linearToGammaPrecise(c.rgb), c.a); } + +// http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1 + +mediump float gammaToLinearFast(mediump float c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); } +mediump vec3 gammaToLinearFast(mediump vec3 c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); } +mediump vec4 gammaToLinearFast(mediump vec4 c) { return vec4(gammaToLinearFast(c.rgb), c.a); } + +mediump float linearToGammaFast(mediump float c) { return max(1.055 * pow(max(c, 0.0), 0.41666666) - 0.055, 0.0); } +mediump vec3 linearToGammaFast(mediump vec3 c) { return max(1.055 * pow(max(c, vec3(0.0)), vec3(0.41666666)) - 0.055, vec3(0.0)); } +mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c.rgb), c.a); } + +#define gammaToLinear gammaToLinearFast +#define linearToGamma linearToGammaFast + +#ifdef LOVE_GAMMA_CORRECT + #define gammaCorrectColor gammaToLinear + #define unGammaCorrectColor linearToGamma + #define gammaCorrectColorPrecise gammaToLinearPrecise + #define unGammaCorrectColorPrecise linearToGammaPrecise + #define gammaCorrectColorFast gammaToLinearFast + #define unGammaCorrectColorFast linearToGammaFast +#else + #define gammaCorrectColor + #define unGammaCorrectColor + #define gammaCorrectColorPrecise + #define unGammaCorrectColorPrecise + #define gammaCorrectColorFast + #define unGammaCorrectColorFast +#endif]] + +GLSL.VERTEX = { + HEADER = [[ +#define love_Position gl_Position + +#if __VERSION__ >= 130 + #define attribute in + #define varying out + #ifndef LOVE_GLSL1_ON_GLSL3 + #define love_VertexID gl_VertexID + #define love_InstanceID gl_InstanceID + #endif +#endif + +#ifdef GL_ES + uniform mediump float love_PointSize; +#endif]], + + FUNCTIONS = [[ +void setPointSize() { +#ifdef GL_ES + gl_PointSize = love_PointSize; +#endif +}]], + + MAIN = [[ +attribute vec4 VertexPosition; +attribute vec4 VertexTexCoord; +attribute vec4 VertexColor; +attribute vec4 ConstantColor; + +varying vec4 VaryingTexCoord; +varying vec4 VaryingColor; + +vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition); + +void main() { + VaryingTexCoord = VertexTexCoord; + VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; + setPointSize(); + love_Position = position(ClipSpaceFromLocal, VertexPosition); +}]], +} + +GLSL.PIXEL = { + HEADER = [[ +#ifdef GL_ES + precision mediump float; +#endif + +#define love_MaxCanvases gl_MaxDrawBuffers + +#if __VERSION__ >= 130 + #define varying in + // Some drivers seem to make the pixel shader do more work when multiple + // pixel shader outputs are defined, even when only one is actually used. + // TODO: We should use reflection or something instead of this, to determine + // how many outputs are actually used in the shader code. + #ifdef LOVE_MULTI_CANVAS + layout(location = 0) out vec4 love_Canvases[love_MaxCanvases]; + #define love_PixelColor love_Canvases[0] + #else + layout(location = 0) out vec4 love_PixelColor; + #endif +#else + #ifdef LOVE_MULTI_CANVAS + #define love_Canvases gl_FragData + #endif + #define love_PixelColor gl_FragColor +#endif + +// See Shader::updateScreenParams in Shader.cpp. +#define love_PixelCoord (vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w))]], + + FUNCTIONS = [[ +uniform sampler2D love_VideoYChannel; +uniform sampler2D love_VideoCbChannel; +uniform sampler2D love_VideoCrChannel; + +vec4 VideoTexel(vec2 texcoords) { + vec3 yuv; + yuv[0] = Texel(love_VideoYChannel, texcoords).r; + yuv[1] = Texel(love_VideoCbChannel, texcoords).r; + yuv[2] = Texel(love_VideoCrChannel, texcoords).r; + yuv += vec3(-0.0627451017, -0.501960814, -0.501960814); + + vec4 color; + color.r = dot(yuv, vec3(1.164, 0.000, 1.596)); + color.g = dot(yuv, vec3(1.164, -0.391, -0.813)); + color.b = dot(yuv, vec3(1.164, 2.018, 0.000)); + color.a = 1.0; + + return gammaCorrectColor(color); +}]], + + MAIN = [[ +uniform sampler2D MainTex; +varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; +varying mediump vec4 VaryingColor; + +vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord); + +void main() { + love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord); +}]], + + MAIN_CUSTOM = [[ +varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; +varying mediump vec4 VaryingColor; + +void effect(); + +void main() { + effect(); +}]], +} + +local function getLanguageTarget(code) + if not code then return nil end + return (code:match("^%s*#pragma language (%w+)")) or "glsl1" +end + +local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, custom, multicanvas) + stage = stage:upper() + local lines = { + GLSL.VERSION[lang][gles], + "#define " ..stage .. " " .. stage, + glsl1on3 and "#define LOVE_GLSL1_ON_GLSL3 1" or "", + gammacorrect and "#define LOVE_GAMMA_CORRECT 1" or "", + multicanvas and "#define LOVE_MULTI_CANVAS 1" or "", + GLSL.SYNTAX, + GLSL[stage].HEADER, + GLSL.UNIFORMS, + GLSL.FUNCTIONS, + GLSL[stage].FUNCTIONS, + custom and GLSL[stage].MAIN_CUSTOM or GLSL[stage].MAIN, + ((lang == "glsl1" or glsl1on3) and not gles) and "#line 0" or "#line 1", + code, + } + return table_concat(lines, "\n") +end + +local function isVertexCode(code) + return code:match("vec4%s+position%s*%(") ~= nil +end + +local function isPixelCode(code) + if code:match("vec4%s+effect%s*%(") then + return true + elseif code:match("void%s+effect%s*%(") then -- custom effect function + local multicanvas = code:match("love_Canvases") ~= nil + return true, true, multicanvas + else + return false + end +end + +function love.graphics._shaderCodeToGLSL(gles, arg1, arg2) + local vertexcode, pixelcode + local is_custompixel = false -- whether pixel code has "effects" function instead of "effect" + local is_multicanvas = false + + if arg1 then + if isVertexCode(arg1) then + vertexcode = arg1 -- first arg contains vertex shader code + end + + local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg1) + if ispixel then + pixelcode = arg1 -- first arg contains pixel shader code + is_custompixel, is_multicanvas = isCustomPixel, isMultiCanvas + end + end + + if arg2 then + if isVertexCode(arg2) then + vertexcode = arg2 -- second arg contains vertex shader code + end + + local ispixel, isCustomPixel, isMultiCanvas = isPixelCode(arg2) + if ispixel then + pixelcode = arg2 -- second arg contains pixel shader code + is_custompixel, is_multicanvas = isCustomPixel, isMultiCanvas + end + end + + local supportsGLSL3 = love.graphics.getSupported().glsl3 + local gammacorrect = love.graphics.isGammaCorrect() + + local targetlang = getLanguageTarget(pixelcode or vertexcode) + if getLanguageTarget(vertexcode or pixelcode) ~= targetlang then + error("vertex and pixel shader languages must match", 2) + end + + if targetlang == "glsl3" and not supportsGLSL3 then + error("GLSL 3 shaders are not supported on this system!", 2) + end + + if targetlang ~= nil and not GLSL.VERSION[targetlang] then + error("Invalid shader language: " .. targetlang, 2) + end + + local lang = targetlang or "glsl1" + local glsl1on3 = false + if lang == "glsl1" and supportsGLSL3 then + lang = "glsl3" + glsl1on3 = true + end + + if vertexcode then + vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect) + end + if pixelcode then + pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_custompixel, is_multicanvas) + end + + return vertexcode, pixelcode +end + +function love.graphics._transformGLSLErrorMessages(message) + local shadertype = message:match("Cannot compile (%a+) shader code") + local compiling = shadertype ~= nil + if not shadertype then + shadertype = message:match("Error validating (%a+) shader") + end + if not shadertype then return message end + local lines = {} + local prefix = compiling and "Cannot compile " or "Error validating " + lines[#lines+1] = prefix..shadertype.." shader code:" + for l in message:gmatch("[^\n]+") do + -- nvidia: 0() : error/warning [NUMBER]: + local linenumber, what, message = l:match("^0%((%d+)%)%s*:%s*(%w+)[^:]+:%s*(.+)$") + if not linenumber then + -- AMD: ERROR 0:: error/warning(#[NUMBER]) [ERRORNAME]: + linenumber, what, message = l:match("^%w+: 0:(%d+):%s*(%w+)%([^%)]+%)%s*(.+)$") + end + if not linenumber then + -- macOS (?): ERROR: 0:: + what, linenumber, message = l:match("^(%w+): %d+:(%d+): (.+)$") + end + if not linenumber and l:match("^ERROR:") then + what = l + end + if linenumber and what and message then + lines[#lines+1] = ("Line %d: %s: %s"):format(linenumber, what, message) + elseif what then + lines[#lines+1] = what + end + end + -- did not match any known error messages + if #lines == 1 then return message end + return table_concat(lines, "\n") +end + +local defaultcode = { + vertex = [[ +vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) { + return clipSpaceFromLocal * localPosition; +}]], + pixel = [[ +vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) { + return Texel(tex, texcoord) * vcolor; +}]], + videopixel = [[ +void effect() { + love_PixelColor = VideoTexel(VaryingTexCoord.xy) * VaryingColor; +}]], + arraypixel = [[ +uniform ArrayImage MainTex; +void effect() { + love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor; +}]], +} + +local defaults = {} +local defaults_gammacorrect = {} + +local langs = { + glsl1 = {target="glsl1", gles=false}, + essl1 = {target="glsl1", gles=true}, + glsl3 = {target="glsl3", gles=false}, + essl3 = {target="glsl3", gles=true}, +} + +for lang, info in pairs(langs) do + for _, gammacorrect in ipairs{false, true} do + local t = gammacorrect and defaults_gammacorrect or defaults + t[lang] = { + vertex = createShaderStageCode("VERTEX", defaultcode.vertex, info.target, info.gles, false, gammacorrect), + pixel = createShaderStageCode("PIXEL", defaultcode.pixel, info.target, info.gles, false, gammacorrect, false), + videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, info.target, info.gles, false, gammacorrect, true), + arraypixel = createShaderStageCode("PIXEL", defaultcode.arraypixel, info.target, info.gles, false, gammacorrect, true), + } + end +end + +love.graphics._setDefaultShaderCode(defaults, defaults_gammacorrect) + +-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string. +--)luastring"--"