diff src/scripts/graphics.lua @ 1399:fa3eabb3602a MRTs

Added MRT support to canvases via love.graphics.setCanvases(c1, c2, ...), and an 'effects' callback function in shaders. - Simultanious rendering to multiple canvases requires all canvases to be the same size (limitation of pre-GL3.0 framebuffers) - love.graphics.isSupported("mrtcanvas") was added - love_Canvases[n] (0-based array of active canvases) can be written to in pixel shaders in the 'effects' callback function - everything drawn to multiple canvases at once will be duplicated to all canvases if no shader is active or the standard 'effect' shader function is used
author Alex Szpakowski <slime73@gmail.com>
date Sun, 24 Mar 2013 02:20:15 -0300
parents a742f6edaf92
children bee3f7b0dca0
line wrap: on
line diff
--- a/src/scripts/graphics.lua	Thu Mar 21 12:21:13 2013 -0300
+++ b/src/scripts/graphics.lua	Sun Mar 24 02:20:15 2013 -0300
@@ -1295,7 +1295,8 @@
 #define number float
 #define Image sampler2D
 #define extern uniform
-#define Texel texture2D]]
+#define Texel texture2D
+#define love_Canvases gl_FragData]]
 
 	local GLSL_UNIFORMS = [[
 #define ModelViewMatrix gl_ModelViewMatrix
@@ -1332,10 +1333,17 @@
 
 		FOOTER = [[
 void main() {
-	// fix weird crashing issue in OSX when _tex0_ is unused within effect()
+	// fix crashing issue in OSX when _tex0_ is unused within effect()
 	float dummy = texture2D(_tex0_, vec2(.5)).r;
 	gl_FragColor = effect(VaryingColor, _tex0_, VaryingTexCoord.st, gl_FragCoord.xy);
 }]],
+
+		FOOTER_MRT = [[
+void main() {
+	// fix crashing issue in OSX when _tex0_ is unused within effect()
+	float dummy = texture2D(_tex0_, vec2(.5)).r;
+	effects(VaryingColor, _tex0_, VaryingTexCoord.st, gl_FragCoord.xy);
+}]],
 	}
 
 	local function createVertexCode(vertexcode)
@@ -1349,36 +1357,62 @@
 		return table_concat(vertexcodes, "\n")
 	end
 
-	local function createPixelCode(pixelcode)
+	local function createPixelCode(pixelcode, is_mrt)
 		local pixelcodes = {
 			GLSL_VERSION,
 			GLSL_SYNTAX, GLSL_PIXEL.HEADER, GLSL_UNIFORMS,
 			"#line 0",
 			pixelcode,
-			GLSL_PIXEL.FOOTER
+			is_mrt and GLSL_PIXEL.FOOTER_MRT or GLSL_PIXEL.FOOTER,
 		}
 		return table_concat(pixelcodes, "\n")
 	end
 
-	function love.graphics._shaderCodeToGLSL(vertexcode, pixelcode)
-		if vertexcode then
-			local s = vertexcode:gsub("\r\n\t", " ")
-			s = s:gsub("(%w+)(%s+)%(", "%1(")
-			if s:match("vec4%s*effect%(") then
-				pixelcode = vertexcode -- first argument contains pixel shader code
+	local function isVertexCode(code)
+		return code:match("vec4%s*position%(") ~= nil
+	end
+
+	local function isPixelCode(code)
+		if code:match("vec4%s*effect%(") then
+			return true
+		elseif code:match("void%s*effects%(") then -- multiple render targets (MRT)
+			return true, true
+		else
+			return false
+		end
+	end
+
+	function love.graphics._shaderCodeToGLSL(arg1, arg2)
+		local vertexcode, pixelcode
+		local is_mrt = false -- whether pixel code has "effects" function instead of "effect"
+		
+		if arg1 then
+			local s = arg1:gsub("\r\n\t", " ") -- convert whitespace to spaces for parsing
+			s = s:gsub("(%w+)(%s+)%(", "%1(") -- convert "func ()" to "func()"
+
+			if isVertexCode(s) then
+				vertexcode = arg1 -- first arg contains vertex shader code
 			end
-			if not s:match("vec4%s*position%(") then
-				vertexcode = nil -- first argument doesn't contain vertex shader code
+
+			local ispixel, isMRT = isPixelCode(s)
+			if ispixel then
+				pixelcode = arg1 -- first arg contains pixel shader code
+				is_mrt = isMRT
 			end
 		end
-		if pixelcode then
-			local s = pixelcode:gsub("\r\n\t", " ")
-			s = s:gsub("(%w+)(%s+)%(", "%1(")
-			if s:match("vec4%s*position%(") then
-				vertexcode = pixelcode -- second argument contains vertex shader code
+		
+		if arg2 then
+			local s = arg2:gsub("\r\n\t", " ") -- convert whitespace to spaces for parsing
+			s = s:gsub("(%w+)(%s+)%(", "%1(") -- convert "func ()" to "func()"
+
+			if isVertexCode(s) then
+				vertexcode = arg2 -- second arg contains vertex shader code
 			end
-			if not s:match("vec4%s*effect%(") then
-				pixelcode = nil -- second argument doesn't contain pixel shader code
+
+			local ispixel, isMRT = isPixelCode(s)
+			if ispixel then
+				pixelcode = arg2 -- second arg contains pixel shader code
+				is_mrt = isMRT
 			end
 		end
 
@@ -1386,7 +1420,7 @@
 			vertexcode = createVertexCode(vertexcode)
 		end
 		if pixelcode then
-			pixelcode = createPixelCode(pixelcode)
+			pixelcode = createPixelCode(pixelcode, is_mrt)
 		end
 
 		return vertexcode, pixelcode