After some optimisation Defold 10 lights(256 rays per light) frame 26-30ms.In samsung galaxy s3. On pc 50+ light sources 16 ms.I think i make all possible optimisation.If someone see more places to optimize please tell me.
shadow fragment shader. The bootleneck
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
#define PI 3.14
#define THRESHOLD 0.75
varying mediump vec4 position;
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D TEX0;
//number of rays for every light
//can't use uniform because of webGl
const float resolution=256.0;
uniform vec4 up_scale;
uniform vec4 pos;
float mult_pi=PI*1.5;
void main(void) {
float distance = 1.0;
//angle do not changed for one ray, changed only r(lenght)
float theta = (var_texcoord0.s*2.0 -1.0) * PI + mult_pi;
const float add = 1.0/resolution;
vec2 pre_coord = vec2(sin(theta)*resolution/2.0/pos.z,cos(theta)*resolution/2.0/pos.w);
for (float r=0.0; r<1.0; r+=add) {
//coord which we will sample from occlude map
vec2 coord = pre_coord * -r +vec2(pos.x/pos.z,pos.y/pos.w);
vec4 data = texture2D(TEX0, coord);
//if we've hit an opaque fragment (occluder), then get new distance
if (data.a > THRESHOLD) {
distance = r;
break;
}
}
gl_FragColor = vec4(vec3(distance/up_scale.x), 1.0);
}
light map shader. The bootleneck too if use soft shadows(because of blur)
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
#define PI 3.14
//inputs from vertex shader
varying mediump vec4 position;
varying mediump vec2 var_texcoord0;
//uniform values
uniform lowp sampler2D TEX0;
uniform lowp sampler2D TEX1;
const float resolution=256.0;
uniform vec4 vColor;
const float soft_shadows=1.0;
//sample from the distance map
float sample(vec2 coord, float r) {
coord.x=1.0-coord.x;
return step(r, texture2D(TEX0, coord).r);
}
void main(void) {
//rectangular to polar
vec2 norm = var_texcoord0.st * 2.0 - 1.0;
float theta = atan(norm.y, norm.x);
float r = length(norm);
float coord = (theta + PI) / (2.0*PI);
//the tex coord to sample our 1D lookup texture
//always 0.0 on y axis
vec2 tc = vec2(coord, 0.0);
//the center tex coord, which gives us hard shadows
float center = sample(vec2(tc.x, tc.y), r);
//we multiply the blur amount by our distance from center
//this leads to more blurriness as the shadow "fades away"
//float blur = (1./resolution.x) * smoothstep(0., 1., r);
//now we use a simple gaussian blur
//float sum = 0.0;
//uncomment if need soft shadows
//sum += sample(vec2(tc.x - 4.0*blur, tc.y), r) * 0.05;
//sum += sample(vec2(tc.x - 3.0*blur, tc.y), r) * 0.09;
//sum += sample(vec2(tc.x - 2.0*blur, tc.y), r) * 0.12;
//sum += sample(vec2(tc.x - 1.0*blur, tc.y), r) * 0.15;
//sum += center * 0.16;
//sum += sample(vec2(tc.x + 1.0*blur, tc.y), r) * 0.15;
//sum += sample(vec2(tc.x + 2.0*blur, tc.y), r) * 0.12;
//sum += sample(vec2(tc.x + 3.0*blur, tc.y), r) * 0.09;
//sum += sample(vec2(tc.x + 4.0*blur, tc.y), r) * 0.05;
//1.0 -> in light, 0.0 -> in shadow
//float lit = mix(center, sum, soft_shadows);
float lit=center;
//multiply the summed amount by our distance, which gives us a radial falloff
//then multiply by vertex (light) color
gl_FragColor = vColor * vec4(vec3(1.0), lit * smoothstep(1.0, 0.0, r));
}