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
This commit is contained in:
Alex Szpakowski
2017-02-25 17:52:27 -04:00
parent f3f6b10ac8
commit ff8358a979
5 changed files with 47 additions and 24 deletions
+13 -1
View File
@@ -174,12 +174,24 @@ void Shader::attachDefault()
current = nullptr; 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 void Shader::checkMainTextureType(TextureType textype) const
{ {
const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN); const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN);
if (info != nullptr && info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype) 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) bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err)
+1
View File
@@ -176,6 +176,7 @@ public:
**/ **/
virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0; virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0;
TextureType getMainTextureType() const;
void checkMainTextureType(TextureType textype) const; void checkMainTextureType(TextureType textype) const;
virtual ptrdiff_t getHandle() const = 0; virtual ptrdiff_t getHandle() const = 0;
+1 -4
View File
@@ -134,10 +134,7 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
gl.useVertexAttribArrays(enabledattribs, instancedattribs); gl.useVertexAttribArrays(enabledattribs, instancedattribs);
if (texture.get()) gl.bindTextureToUnit(texture, 0, false);
gl.bindTextureToUnit(texture, 0, false);
else
gl.bindTextureToUnit(TEXTURE_2D, gl.getDefaultTexture(TEXTURE_2D), 0, false);
Graphics::TempTransform transform(gfx, m); Graphics::TempTransform transform(gfx, m);
+19 -2
View File
@@ -867,8 +867,25 @@ void OpenGL::bindTextureToUnit(TextureType target, GLuint texture, int textureun
void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restoreprev) void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restoreprev)
{ {
GLuint handle = texture != nullptr ? (GLuint) texture->getHandle() : getDefaultTexture(TEXTURE_2D); TextureType textype = TEXTURE_2D;
TextureType textype = texture != nullptr ? texture->getTextureType() : 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); bindTextureToUnit(textype, handle, textureunit, restoreprev);
} }
+13 -17
View File
@@ -262,15 +262,11 @@ void main() {
love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord); love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
}]], }]],
MAIN_MULTI_CANVAS = [[ MAIN_CUSTOM = [[
uniform sampler2D MainTex; void effect();
varying mediump vec4 VaryingTexCoord;
varying mediump vec4 VaryingColor;
void effects(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
void main() { 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" return (code:match("^%s*#pragma language (%w+)")) or "glsl1"
end end
local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, multicanvas) local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacorrect, custom)
stage = stage:upper() stage = stage:upper()
local lines = { local lines = {
GLSL.VERSION[lang][gles], GLSL.VERSION[lang][gles],
@@ -291,7 +287,7 @@ local function createShaderStageCode(stage, code, lang, gles, glsl1on3, gammacor
GLSL.UNIFORMS, GLSL.UNIFORMS,
GLSL.FUNCTIONS, GLSL.FUNCTIONS,
GLSL[stage].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", (lang == "glsl3" or gles) and "#line 1" or "#line 0",
code, code,
} }
@@ -305,8 +301,8 @@ end
local function isPixelCode(code) local function isPixelCode(code)
if code:match("vec4%s+effect%s*%(") then if code:match("vec4%s+effect%s*%(") then
return true return true
elseif code:match("void%s+effects%s*%(") then elseif code:match("void%s+effect%s*%(") then
-- function for rendering to multiple canvases simultaneously -- custom effect function
return true, true return true, true
else else
return false return false
@@ -315,17 +311,17 @@ end
function love.graphics._shaderCodeToGLSL(gles, arg1, arg2) function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
local vertexcode, pixelcode 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 arg1 then
if isVertexCode(arg1) then if isVertexCode(arg1) then
vertexcode = arg1 -- first arg contains vertex shader code vertexcode = arg1 -- first arg contains vertex shader code
end end
local ispixel, isMultiCanvas = isPixelCode(arg1) local ispixel, isCustomPixel = isPixelCode(arg1)
if ispixel then if ispixel then
pixelcode = arg1 -- first arg contains pixel shader code pixelcode = arg1 -- first arg contains pixel shader code
is_multicanvas = isMultiCanvas is_custompixel = isCustomPixel
end end
end end
@@ -334,10 +330,10 @@ function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
vertexcode = arg2 -- second arg contains vertex shader code vertexcode = arg2 -- second arg contains vertex shader code
end end
local ispixel, isMultiCanvas = isPixelCode(arg2) local ispixel, isCustomPixel = isPixelCode(arg2)
if ispixel then if ispixel then
pixelcode = arg2 -- second arg contains pixel shader code pixelcode = arg2 -- second arg contains pixel shader code
is_multicanvas = isMultiCanvas is_custompixel = isCustomPixel
end end
end end
@@ -368,7 +364,7 @@ function love.graphics._shaderCodeToGLSL(gles, arg1, arg2)
vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect) vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gles, glsl1on3, gammacorrect)
end end
if pixelcode then if pixelcode then
pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_multicanvas) pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gles, glsl1on3, gammacorrect, is_custompixel)
end end
return vertexcode, pixelcode return vertexcode, pixelcode