+ // Compute shadowing
+ "float shadow = 1.0 - abs(aTexCoords.y - 0.5) * 2.0;"
+ "float masking = smoothstep( 0.5, 0.8, shadow );"
+
+ "vec3 colour_comp = mix( vec3(0.0,0.0,0.0), uColour.rgb, masking );"
+
+ "float flow_thing = fract( aTexCoords.x + uTime );"
+ "vec3 final_comp = colour_comp + flow_thing * uGlow;"
+
+ "FragColor = vec4( final_comp, max( shadow* 0.2, masking ) * uColour.a );"
+ "}"
+ ,
+ UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve", "uTime", "uGlow" })
+)
+
+SHADER_DEFINE( shader_buttons,
+ // VERTEX
+ "layout (location=0) in vec2 a_co;"
+ "uniform vec4 uOffset;" // Tile x/y, uv x/y
+ "uniform mat3 uPv;"
+ ""
+ "out vec2 aTexCoords;"
+ ""
+ "void main()"
+ "{"
+ // Vertex transform
+ "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
+ "gl_Position = vec4( uPv * worldpos, 1.0 );"
+
+ // Create texture coords
+ "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
+ "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
+ "}",
+
+ // FRAGMENT
+ "out vec4 FragColor;"
+ ""
+ "uniform sampler2D uTexMain;"
+ "uniform vec4 uColour;" // rgb, light amount
+ ""
+ "in vec2 aTexCoords;"
+ ""
+ "void main()"
+ "{"
+ "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
+
+ "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
+ "}"
+ ,
+ UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
+)
+
+SHADER_DEFINE( shader_sprite,
+
+ // VERTEX
+ "layout (location=0) in vec2 a_co;" // quad mesh
+ "uniform vec4 uUv;"
+ "uniform vec3 uPos;"
+ ""
+ "uniform mat3 uPv;"
+ ""
+ "out vec2 aTexCoords;"
+ ""
+ "void main()"
+ "{"
+ "vec2 vertex_world = uUv.zw * (a_co-0.5) * uPos.z + uPos.xy;"
+ "gl_Position = vec4( uPv * vec3( vertex_world, 1.0 ), 1.0 );"
+ "aTexCoords = uUv.xy + a_co*uUv.zw;"
+ "}",
+
+ // FRAGMENT
+ "uniform sampler2D uTexMain;"
+ "out vec4 FragColor;"
+ ""
+ "in vec2 aTexCoords;"
+ ""
+ "void main()"
+ "{"
+ "vec4 texture_sample = texture( uTexMain, aTexCoords );"
+ "FragColor = texture_sample;"