Browse Source

Removed void effects(…) pixel shader prototype. Added void effect(). Allows calling love.graphics.draw with textures of different types with a custom shader without having an extra sampler2D.

effect() takes no arguments and returns nothing, you are responsible for assigning a value to either love_PixelColor or love_Canvases[n] in the function. You can declare ‘MainTex’, which will be whatever texture is used with any Drawable drawn with love.graphics.draw. You can also declare ‘VaryingColor’ and ‘VaryingTexCoord’, which are passed down from the vertex shader by love automatically. love_PixelCoord is also available.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
ff8358a979

+ 13 - 1
src/modules/graphics/Shader.cpp

@@ -174,12 +174,24 @@ void Shader::attachDefault()
 	current = nullptr;
 }
 
+TextureType Shader::getMainTextureType() const
+{
+	const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN);
+	return info != nullptr ? info->textureType : TEXTURE_MAX_ENUM;
+}
+
 void Shader::checkMainTextureType(TextureType textype) const
 {
 	const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN);
 
 	if (info != nullptr && info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype)
-		throw love::Exception("Texture's type must match the type of the shader's main texture.");
+	{
+		const char *textypestr = "unknown";
+		const char *shadertextypestr = "unknown";
+		Texture::getConstant(textype, textypestr);
+		Texture::getConstant(info->textureType, shadertextypestr);
+		throw love::Exception("Texture's type (%s) must match the type of the shader's main texture type (%s).", textypestr, shadertextypestr);
+	}
 }
 
 bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err)

+ 1 - 0
src/modules/graphics/Shader.h

@@ -176,6 +176,7 @@ public:
 	 **/
 	virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0;
 
+	TextureType getMainTextureType() const;
 	void checkMainTextureType(TextureType textype) const;
 
 	virtual ptrdiff_t getHandle() const = 0;

+ 1 - 4
src/modules/graphics/opengl/Mesh.cpp

@@ -134,10 +134,7 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
 
 	gl.useVertexAttribArrays(enabledattribs, instancedattribs);
 
-	if (texture.get())
-		gl.bindTextureToUnit(texture, 0, false);
-	else
-		gl.bindTextureToUnit(TEXTURE_2D, gl.getDefaultTexture(TEXTURE_2D), 0, false);
+	gl.bindTextureToUnit(texture, 0, false);
 
 	Graphics::TempTransform transform(gfx, m);
 

+ 19 - 2
src/modules/graphics/opengl/OpenGL.cpp

@@ -867,8 +867,25 @@ void OpenGL::bindTextureToUnit(TextureType target, GLuint texture, int textureun
 
 void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restoreprev)
 {
-	GLuint handle = texture != nullptr ? (GLuint) texture->getHandle() : getDefaultTexture(TEXTURE_2D);
-	TextureType textype = texture != nullptr ? texture->getTextureType() : TEXTURE_2D;
+	TextureType textype = TEXTURE_2D;
+	GLuint handle = 0;
+
+	if (texture != nullptr)
+	{
+		textype = texture->getTextureType();
+		handle = (GLuint) texture->getHandle();
+	}
+	else
+	{
+		if (textureunit == 0 && Shader::current != nullptr)
+		{
+			TextureType shadertex = Shader::current->getMainTextureType();
+			if (shadertex != TEXTURE_MAX_ENUM)
+				textype = shadertex;
+		}
+
+		handle = getDefaultTexture(textype);
+	}
 
 	bindTextureToUnit(textype, handle, textureunit, restoreprev);
 }

+ 13 - 17
src/modules/graphics/wrap_Graphics.lua

@@ -262,15 +262,11 @@ void main() {
 	love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
 }]],
 
-	MAIN_MULTI_CANVAS = [[
-uniform sampler2D MainTex;
-varying mediump vec4 VaryingTexCoord;
-varying mediump vec4 VaryingColor;
-
-void effects(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
+	MAIN_CUSTOM = [[
+void effect();
 
 void main() {
-	effects(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
+	effect();
 }]],
 }
 
@@ -279,7 +275,7 @@ local function getLanguageTarget(code)
 	return (code:match("^%s*#pragma language (%w+)")) or "glsl1"
 end
 
-local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, multicanvas)
+local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, custom)
 	stage = stage:upper()
 	local lines = {
 		GLSL.VERSION[lang][gles],
@@ -291,7 +287,7 @@ local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacor
 		GLSL.UNIFORMS,
 		GLSL.FUNCTIONS,
 		GLSL[stage].FUNCTIONS,
-		multicanvas and GLSL[stage].MAIN_MULTI_CANVAS or GLSL[stage].MAIN,
+		custom and GLSL[stage].MAIN_CUSTOM or GLSL[stage].MAIN,
 		(lang == "glsl3" or gles) and "#line 1" or "#line 0",
 		code,
 	}
@@ -305,8 +301,8 @@ end
 local function isPixelCode(code)
 	if code:match("vec4%s+effect%s*%(") then
 		return true
-	elseif code:match("void%s+effects%s*%(") then
-		-- function for rendering to multiple canvases simultaneously
+	elseif code:match("void%s+effect%s*%(") then
+		-- custom effect function
 		return true, true
 	else
 		return false
@@ -315,17 +311,17 @@ end
 
 function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
 	local vertexcode, pixelcode
-	local is_multicanvas = false -- whether pixel code has "effects" function instead of "effect"
+	local is_custompixel = false -- whether pixel code has "effects" function instead of "effect"
 
 	if arg1 then
 		if isVertexCode(arg1) then
 			vertexcode = arg1 -- first arg contains vertex shader code
 		end
 
-		local ispixel, isMultiCanvas = isPixelCode(arg1)
+		local ispixel, isCustomPixel = isPixelCode(arg1)
 		if ispixel then
 			pixelcode = arg1 -- first arg contains pixel shader code
-			is_multicanvas = isMultiCanvas
+			is_custompixel = isCustomPixel
 		end
 	end
 	
@@ -334,10 +330,10 @@ function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
 			vertexcode = arg2 -- second arg contains vertex shader code
 		end
 
-		local ispixel, isMultiCanvas = isPixelCode(arg2)
+		local ispixel, isCustomPixel = isPixelCode(arg2)
 		if ispixel then
 			pixelcode = arg2 -- second arg contains pixel shader code
-			is_multicanvas = isMultiCanvas
+			is_custompixel = isCustomPixel
 		end
 	end
 
@@ -368,7 +364,7 @@ function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
 		vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect)
 	end
 	if pixelcode then
-		pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_multicanvas)
+		pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_custompixel)
 	end
 
 	return vertexcode, pixelcode