Created Shaders in Android (markdown)

Miku AuahDark
2020-02-14 11:15:18 +08:00
parent fbb427888a
commit 1a466bfd88
+130
@@ -0,0 +1,130 @@
Shaders in Android
=====
To use shaders in LÖVE Android you use the same API as in LÖVE
```lua
love.graphics.newShader[[
Your shader code
]]
```
The reason the shader code doesn't work is that desktop machines use OpenGL and Android devices use OpenGLES, 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:
* [No acceptable conversion](#no-acceptable-conversion)
* [Field selection out of range](#field-selection-out-of-range)
* [Uniform couldn´t be initialized](#uniform-couldn-t-be-initialized)
If you stuck on desktops without OpenGLES driver support, you can use ANGLE, or since 11.0, [`love.graphics.validateShader(true, shaderCode)`](https://love2d.org/wiki/love.graphics.validateShader).
------------------
No acceptable conversion
-----
OpenGLES doesn´t handle float and int conversions by default, instead every float or int should be manually converted. For example:
```glsl
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`
```glsl
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:
```glsl
float foo;
int bar;
if (foo == bar)
```
Should be:
```glsl
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
```glsl
uniform vec2[4] array;
```
Generating an array with 4 `vec2` elements. But OpenGLES doesn´t use this notation. Instead you should write it like this:
```glsl
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](http://www.love2d.org/wiki/love.graphics.newShader#Shader_Language) you can use `extern` as you would use `uniform` in OpenGLSL 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
```glsl
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 OpenGLSL 1.2 (The one used in desktop environments), Android uses an OpenGLSL based on it it doesn´t include this feature.
Instead you could just use:
```glsl
uniform float foo;
float bar = 5;
```
And in your shader code check if it´s `0.0`
```glsl
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.
```lua
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](https://github.com/binji/love-nacl/wiki/Modifying-your-shaders-to-work-with-L%C3%96VELINESS) page of the LÖVELINESS Wiki.
Look at this links for more information on shaders in Android:
* [OpenGL Wiki](http://www.opengl.org/wiki/Main_Page) Not everything works in OpenGL ES
* [OpenGLES Shading Language PDF](http://www.khronos.org/files/opengles_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](http://www.khronos.org/files/opengles_shading_language.pdf) OpenGLES 2.0 Shading Language is based on this OpenGLSL implemantation. It still differs.