I am trying to implement 2d light. I port 2d light from libgdx https://gist.github.com/mattdesl/5286905 . When i try it in libgdx i can have about 70 lights, before fps go down. But when i try defold i can have 5 light before fps go down. The problem is with shadow fragment shader. If i comment line in shader(distance = min(distance, dst)) fps is ok. If watch in profiler, the problem is with vsync. What i am doing wrong, how can i fixed it.
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
#define PI 3.14
varying vec2 vTexCoord0;
varying LOWP vec4 vColor;
uniform sampler2D u_texture;
uniform vec2 resolution;
//for debugging; use a constant value in final release
uniform float upScale;
//alpha threshold for our occlusion map
const float THRESHOLD = 0.75;
void main(void) {
float distance = 1.0;
for (float y=0.0; y<resolution.y; y+=1.0) {
//rectangular to polar filter
vec2 norm = vec2(vTexCoord0.s, y/resolution.y) * 2.0 - 1.0;
float theta = PI*1.5 + norm.x * PI;
float r = (1.0 + norm.y) * 0.5;
//coord which we will sample from occlude map
vec2 coord = vec2(-r * sin(theta), -r * cos(theta))/2.0 + 0.5;
//sample the occlusion map
vec4 data = texture2D(u_texture, coord);
//the current distance is how far from the top we've come
float dst = y/resolution.y / upScale;
//if we've hit an opaque fragment (occluder), then get new distance
//if the new distance is below the current, then we'll use that for our ray
float caster = data.a;
if (caster > THRESHOLD) {
//if comment this line all work correct
distance = min(distance, dst);
}
}
gl_FragColor = vec4(vec3(distance), 1.0);
}
module that render light
local Target_helper = require "helpers.render.render_target.render_target_helper"
local Screen_helper = require "helpers.render.screen.screen_helper"
local M = {}
M.__index = M
local add_light_hash=hash("add_light")
local function init_render_targets(self,size)
self.light_size=size
self.pred = render.predicate({"screen"})
self.block_light_pred = render.predicate({"block_light"})
self.occlusion_map_target=Target_helper.create_default("2dlight_occlusion_map",size,size,false)
local shadow_color_params = {
format = render.FORMAT_RGBA,
width = size,
height = size,
min_filter = render.FILTER_LINEAR,
mag_filter = render.FILTER_LINEAR,
u_wrap = render.WRAP_REPEAT,
v_wrap = render.WRAP_REPEAT }
self.shadow_map_target=Target_helper.new_with_params("2dlight_shadow_map",size,1,shadow_color_params,nil)
self.light_map_target=Target_helper.create_default("2dlight_light_map",size,size,false)
self.clear_color = vmath.vector4(0, 0, 0, 1)
self.shadow_map_constants = render.constant_buffer()
self.shadow_map_constants.resolution = vmath.vector4(size, size, 0, 0)
end
local function enable_blend(self)
render.enable_state(render.STATE_BLEND)
if(self.additive) then
render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE)
else
render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
end
end
local function draw_occlusion(self,light)
local width=render.get_width()
local height=render.get_height()
render.set_viewport(0, 0, self.light_size, self.light_size)
render.set_projection(vmath.matrix4_orthographic(-self.light_size/2+light.position.x, self.light_size/2+light.position.x, -self.light_size/2+light.position.y, self.light_size/2+light.position.y, -1, 1))
render.enable_render_target(self.occlusion_map_target.target)
enable_blend(self)
render.clear({[render.BUFFER_COLOR_BIT] = vmath.vector4(0,0,0,0), [render.BUFFER_DEPTH_BIT] = 1, [render.BUFFER_STENCIL_BIT] = 0})
render.draw(self.block_light_pred)
enable_blend(self)
render.disable_render_target(self.occlusion_map_target.target)
--self.screen_helper:draw_in(self.occlusion_map_target.target,0,0,256,256)
end
local function draw_shadow_map(self)
render.enable_render_target(self.shadow_map_target.target)
render.enable_material("2d_light_shadow")
self.screen_helper:draw(self.occlusion_map_target.target,self.shadow_map_constants,vmath.vector4(0,0,0,0))
render.disable_material("2d_light_shadow")
render.disable_render_target(self.shadow_map_target.target)
--self.screen_helper:draw_in(self.shadow_map_target.target,0,0,256,256)
end
local function draw_light_map(self,light)
local width=render.get_width()
local height=render.get_height()
local width_scale = width/self.light_size
local height_scale = height/self.light_size
render.set_viewport(0, 0, render.get_window_width(), render.get_height())
local x=0.01 * width_scale-light.position.x/width*0.02*width_scale + 0.01
local y=0.01 * height_scale-light.position.y/height*0.02*height_scale + 0.01
local projection=vmath.matrix4_orthographic(x-0.01*width_scale,x+0.01*width_scale,y-0.01*height_scale,y+0.01*height_scale,-1,1)
render.set_projection(projection)
--print(light.color)
render.enable_material("light_map")
render.enable_texture(0, self.shadow_map_target.target, render.BUFFER_COLOR_BIT)
render.draw(self.pred,light.const)
render.disable_texture(0,self.shadow_map_target.target)
render.disable_material("light_map")
end
function M.new(light_size, up_scale, additive, soft_shadows)
local self = setmetatable({},M)
self.screen_helper=Screen_helper.new(render)
self.lights={}
init_render_targets(self,light_size)
return self
end
local function draw_light(self,light)
draw_occlusion(self,light)
draw_shadow_map(self)
--draw_light_map(self,light)
render.set_viewport(0, 0, render.get_window_width(), render.get_height())
end
function M:draw()
for key,light in pairs(self.lights) do
draw_light(self,light)
end
end
function M:handle_message(message_id,message)
if(message_id==add_light_hash)then
local light_constants = render.constant_buffer()
light_constants.resolution = vmath.vector4(self.light_size, self.light_size, 0, 0)
light_constants.vColor = message.color
local light={position=message.position,size=message.size,color=message.color,const=light_constants}
self.lights[message.light_id]=light
end
end
return M