Shaders in Android - love2d/love-android GitHub Wiki
Shaders in Android
To use shaders in LÖVE Android you use the same API as in LÖVE
love.graphics.newShader[[
Your shader code
]]
The reason the shader code doesn't work is that desktop machines use OpenGL and Android devices use OpenGL ES, and the shader language implementation is different in some aspects. This guide details the differences that you should take into account when writing shader code for Android.
The problems that may arise are:
If you stuck on desktops without OpenGL ES driver support, you can use ANGLE, or since 11.0, love.graphics.validateShader(true, shaderCode)
.
No acceptable conversion
OpenGL ES doesn't handle float and int conversions by default, instead every float or int should be manually converted. For example:
float foo;
if (foo == 0)
This would return an error since foo
is a float and 0
is an int, yeah 0
is a perfect float but the shader language doesn´t see it that way. Instead you should use 0.0
float foo;
if (foo == 0.0)
If you are working with too different variables it may be easier to cast the int into a float. For example:
float foo;
int bar;
if (foo == bar)
Should be:
float foo;
int bar;
if (foo == float(bar))
Field selection out of range
This error occurs when creating arrays, in OpenGL you would use the following code
uniform vec2[4] array;
Generating an array with 4 vec2
elements. But OpenGL ES doesn't use this notation. Instead you should write it like this:
uniform vec2 array[4];
The length must be specified in the identifier and not in the type
Uniform couldn't be initialized
Well this took me a while to find but it´s rather simple. In LÖVE Shader Language you can use extern
as you would use uniform
in GLSL so that you can then send data to the shader using Shader:send()
. The problem comes when you need to have a default value in the variable. In OpenGL you would normally do
uniform float foo = 5;
So if you pass a number to foo
it will take that value, but if you don't send anything it would take 5 as it's own value. This was added in GLSL 1.2 (The one used in desktop environments), but ESSL doesn't support this feature.
Instead you could just use:
uniform float foo;
float bar = 5;
And in your shader code check if it's 0.0
if (foo == 0.0) {
bar = 5;
} else {
bar = foo;
}
This code doesn't allow you to have bar == 0.0
. If you don't like that then there is another alternative, you can just store the variable value in Lua and send it before running the shader.
shader = love.graphics.newShader[[
//Shader Code//
uniform float foo;
//Shader Code//
]]
foo = 5
--Your lua code that may or may not change foo
shader:send("foo", foo) --Shader is the shader created before, that makes use of foo
love.graphics.setShader(shader)
This is a better solution and should behave as expected
More Info
This file is based in the Modifying your shaders to work with LÖVELINESS page of the LÖVELINESS Wiki.
Look at this links for more information on shaders in Android:
- OpenGL Wiki Not everything works in OpenGL ES
- OpenGL ES Shading Language PDF This file tells you what you can and can't do, plus it list the differences with OpenGLSL.
- OpenGL 2.0 Spec OpenGL ES 2.0 Shading Language is based on this OpenGLSL implemantation. It still differs.