Shader uniform type mismatch handling in Love2D
0 reputation · 16 Aug 2021, 05:14 UTC
0 reputation · 16 Aug 2021, 05:14 UTC
The goal is to diagnose intermittent rendering artifacts that appear when a uniform is bound with a Lua value of an incompatible type. For example, setting a GLSL float uniform with a Lua string or passing a table with fewer elements than required for a vector uniform.
Constraints include the fact that Love2D’s love.graphics.setShader API does not document explicit type checking. On some desktop OpenGL drivers the binding silently succeeds, producing no console output, while on WebGL or mobile GL ES the same call may generate a warning, an error, or no observable effect. Additionally, if the uniform is not referenced in the shader, the engine logs a warning only at compile time, further obscuring the issue.
Unresolved behavior: does Love2D guarantee consistent error reporting across platforms when a uniform type mismatch occurs? How can a developer reliably detect and handle such mismatches to avoid silent failures?
Specific questions:
love.graphics.setShader when the Lua value type does not match the declared GLSL uniform type?35775 reputation · 16 Aug 2021, 05:39 UTC
Love2D’s shader:send (used internally by love.graphics.setShader) does not perform runtime type checking against the GLSL uniform declaration. It only does implicit conversion: Lua numbers become floats, Lua tables become vectors or matrices by element count. If the Lua value’s type or size does not match the uniform, the call is forwarded to the underlying OpenGL/WebGL/GLES driver, which may:
Because error reporting is driver‑ and backend‑dependent, there is no guaranteed warning or error on desktop OpenGL, while WebGL (via love.js) and mobile GLES builds are more likely to show a warning in the browser/device console.
Confirmed facts (from Love2D source and documentation):
shader:getUniform(name) returns the declared GLSL type ("float", "vec3", "mat4", etc.) and component count.love.graphics.newShader); this warning is not repeated on later send calls.Recommended steps for cross‑platform type safety:
local uType, uSize = shader:getUniform('myUniform')
-- uType is a string like "float", "vec3", "mat4"
-- uSize is the number of components (1 for float/mat1, 3 for vec3, 16 for mat4)
local function safeSend(shader, name, value)
local typ, size = shader:getUniform(name)
if typ == nil then
error('Uniform not found: ' .. name)
end
if typ == 'float' then
if type(value) ~= 'number' then
error(string.format('Uniform %s expects a number, got %s', name, type(value)))
end
shader:send(name, value)
elseif typ:match('^vec%d+$') then
local n = tonumber(typ:match('vec(%d+)'))
if type(value) ~= 'table' or #value ~= n then
error(string.format('Uniform %s expects %d numbers, got %s', name, n, table.concat(value, ', ')))
end
shader:send(name, unpack(value))
elseif typ == 'mat4' then
if type(value) ~= 'table' or #value ~= 16 then
error(string.format('Uniform %s expects 16 numbers (column‑major), got %s', name, table.concat(value, ', ')))
end
shader:send(name, unpack(value))
else
error('Unsupported uniform type: ' .. typ)
end
end
safeSend wherever you would call shader:send. This runs the same validation on desktop, WebGL, and mobile because the check is performed in Lua before the GL call.If you need to know whether a particular platform is emitting GL errors, you can check love.graphics.getRendererInfo() to distinguish OpenGL, OpenGL ES, or WebGL backends, but the helper above eliminates reliance on such diagnostics.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.