From a7078a4be9f4c44a41e5c7e7a633169b53f78d48 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 11 Nov 2016 12:27:52 -0300 Subject: [PATCH] Done with lights and shadows (wonder if i'm missing something..) --- drivers/gles3/rasterizer_gles3.cpp | 2 +- drivers/gles3/rasterizer_scene_gles3.cpp | 838 +++++++++++---------- drivers/gles3/rasterizer_scene_gles3.h | 91 ++- drivers/gles3/rasterizer_storage_gles3.cpp | 43 +- drivers/gles3/rasterizer_storage_gles3.h | 11 +- drivers/gles3/shader_gles3.cpp | 9 + drivers/gles3/shader_gles3.h | 6 + drivers/gles3/shaders/scene.glsl | 256 ++++--- scene/3d/light.cpp | 60 +- scene/3d/light.h | 5 +- servers/visual/rasterizer.h | 7 +- servers/visual/visual_server_raster.h | 4 +- servers/visual/visual_server_scene.cpp | 2 +- servers/visual/visual_server_scene.h | 2 - servers/visual_server.h | 5 +- 15 files changed, 783 insertions(+), 558 deletions(-) diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index e838020c45d..c799cd12af2 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -125,6 +125,7 @@ void RasterizerGLES3::begin_frame(){ storage->update_dirty_shaders(); storage->update_dirty_materials(); + scene->iteration(); } @@ -258,7 +259,6 @@ void RasterizerGLES3::register_config() { GLOBAL_DEF("rendering/gles3/use_nearest_mipmap_filter",false); GLOBAL_DEF("rendering/gles3/anisotropic_filter_level",4.0); - } RasterizerGLES3::RasterizerGLES3() diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 287801b597e..4ae257abc43 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -131,8 +131,10 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); //interpola nearest (though nvidia can improve this) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Remove artifact on the edges of the shadowmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -559,11 +561,6 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) { light_instance->light=p_light; light_instance->light_ptr=storage->light_owner.getornull(p_light); - glGenBuffers(1, &light_instance->light_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, light_instance->light_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInstance::LightDataUBO), NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - ERR_FAIL_COND_V(!light_instance->light_ptr,RID()); light_instance->self=light_instance_owner.make_rid(light_instance); @@ -818,9 +815,50 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } -void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) { +void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { + + int omni_indices[16]; + int omni_count=0; + int spot_indices[16]; + int spot_count=0; + + int maxobj = MIN(16,state.max_forward_lights_per_object); + + int lc = e->instance->light_instances.size(); + if (lc) { + + const RID* lights=e->instance->light_instances.ptr(); + + for(int i=0;ilast_pass!=render_pass) //not visible + continue; + + if (li->light_ptr->type==VS::LIGHT_OMNI) { + if (omni_countinstance->layer_mask&li->light_ptr->cull_mask) { + omni_indices[omni_count++]=li->light_index; + } + } + + if (li->light_ptr->type==VS::LIGHT_SPOT) { + if (spot_countinstance->layer_mask&li->light_ptr->cull_mask) { + spot_indices[spot_count++]=li->light_index; + } + } + } + } + + state.scene_shader.set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT,omni_count); + + if (omni_count) { + glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES),omni_count,omni_indices); + } + + state.scene_shader.set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT,spot_count); + if (spot_count) { + glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES),spot_count,spot_indices); + } - glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform } @@ -894,7 +932,7 @@ void RasterizerSceneGLES3::_set_cull(bool p_front,bool p_reverse_cull) { -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow) { +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow,bool p_directional_add) { if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { //p_reverse_cull=!p_reverse_cull; @@ -906,7 +944,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo - if (!p_shadow) { + if (!p_shadow && !p_directional_add) { glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); glBindTexture(GL_TEXTURE_2D,state.brdf_texture); @@ -934,160 +972,147 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.current_line_width=-1; state.current_depth_draw=-1; - glDisable(GL_BLEND); - RasterizerStorageGLES3::Material* prev_material=NULL; RasterizerStorageGLES3::Geometry* prev_geometry=NULL; VS::InstanceType prev_base_type = VS::INSTANCE_MAX; - int prev_light_type=-1; - int prev_light_index=-1; - int prev_blend=-1; int current_blend_mode=-1; - bool prev_additive=false; + int prev_shading=-1; + + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); //by default unshaded (easier to set) + + bool first=true; for (int i=0;imaterial; - bool rebind=i==0; + bool rebind=first; - int light_type=(e->sort_key>>RenderList::SORT_KEY_LIGHT_TYPE_SHIFT)&0xF; - int light_index=(e->sort_key>>RenderList::SORT_KEY_LIGHT_INDEX_SHIFT)&0xFFFF; - - bool additive=false; + int shading = (e->sort_key>>RenderList::SORT_KEY_SHADING_SHIFT)&RenderList::SORT_KEY_SHADING_MASK; if (!p_shadow) { - if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) { - if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + + if (p_directional_add) { + if (e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask&directional_light->light_ptr->cull_mask)) { + continue; + } + + shading&=~1; //ignore the ignore directional for base pass + } + + if (shading!=prev_shading) { + + if (e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) { + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); + //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); } else { state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,light_type!=0xF); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,(light_type&3)==VS::LIGHT_DIRECTIONAL); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,(light_type&0xF)==VS::LIGHT_OMNI); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,(light_type&0xF)==VS::LIGHT_SPOT); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,!p_directional_add); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,shadow_filter_mode==SHADOW_FILTER_PCF5); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,shadow_filter_mode==SHADOW_FILTER_PCF13); - if ((light_type&3)==VS::LIGHT_DIRECTIONAL) { - if (light_instances[light_index]->light_ptr->shadow) { + if (p_directional_add || (directional_light && (e->sort_key&RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG)==0)) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,true); + + if (directional_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,true); - switch(light_instances[light_index]->light_ptr->directional_shadow_mode) { + switch(directional_light->light_ptr->directional_shadow_mode) { case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,true); break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,true); break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,directional_light->light_ptr->directional_blend_splits); + break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,directional_light->light_ptr->directional_blend_splits); + break; } } - } + } } rebind=true; } - - if (!*e->additive_ptr) { - - additive=false; - *e->additive_ptr=true; - } else { - additive=true; - } - - bool desired_blend=false; - int desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX; - - if (additive) { - desired_blend=true; - desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; - } else { - desired_blend=p_alpha_pass; - desired_blend_mode=material->shader->spatial.blend_mode; - } - - if (prev_blend!=desired_blend) { - - if (desired_blend) { - glEnable(GL_BLEND); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glColorMask(1,1,1,0); - } + if (p_alpha_pass || p_directional_add) { + int desired_blend_mode; + if (p_directional_add) { + desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; } else { - glDisable(GL_BLEND); - glColorMask(1,1,1,1); + desired_blend_mode=material->shader->spatial.blend_mode; } - prev_blend=desired_blend; - } - - if (desired_blend && desired_blend_mode!=current_blend_mode) { + if (desired_blend_mode!=current_blend_mode) { - switch(desired_blend_mode) { + switch(desired_blend_mode) { - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - } break; + } break; + } + + current_blend_mode=desired_blend_mode; } - current_blend_mode=desired_blend_mode; } - if (light_index!=prev_light_index) { - if (light_index!=0xFFFF) { //not unshaded - _setup_light(light_instances[light_index]); - } - } } @@ -1098,17 +1123,16 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e // _rinfo.mat_change_count++; } + if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { + _setup_light(e); + } + if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) { _setup_geometry(e); } - if (!p_shadow && (rebind || prev_additive!=additive)) { - state.scene_shader.set_uniform(SceneShaderGLES3::NO_AMBIENT_LIGHT, additive); - - } - _set_cull(e->sort_key&RenderList::SORT_KEY_MIRROR_FLAG,p_reverse_cull); state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror?-1.0:1.0); @@ -1120,9 +1144,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e prev_material=material; prev_base_type=e->instance->base_type; prev_geometry=e->geometry; - prev_additive=additive; - prev_light_type=light_type; - prev_light_index=light_index; + prev_shading=shading; + first=false; } @@ -1133,14 +1156,14 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); } @@ -1214,8 +1237,6 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->material=m; e->instance=p_instance; e->owner=p_owner; - e->additive=false; - e->additive_ptr=&e->additive; e->sort_key=0; if (e->geometry->last_pass!=render_pass) { @@ -1223,6 +1244,9 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->geometry->index=current_geometry_index++; } + if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask&e->instance->layer_mask)==0) { + e->sort_key|=RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG; + } e->sort_key|=uint64_t(e->geometry->index)<sort_key|=uint64_t(e->instance->base_type)<additive_ptr=&oe->additive; } } @@ -1261,106 +1284,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g //e->light_type=0xFF; // no lights! - - - if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { - e->sort_key|=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED; - e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<base->shadow_enabled) { - light_type|=0x8; - if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) - light_type|=0x10; - else if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) - light_type|=0x30; - - } -*/ - - RenderList::Element *ec; - if (duplicate) { - ec = render_list.add_element(); - copymem(ec,e,sizeof(RenderList::Element)); - } else { - - ec=e; - duplicate=true; - } - - ec->additive_ptr=&e->additive; - - ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; - ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //this is zero byt whathever - - if (directional_light_instances[i]->light_ptr->shadow) { - //add proper flags for directional shadow mode - ec->sort_key|=uint64_t(directional_light_instances[i]->light_ptr->directional_shadow_mode+1) << (RenderList::SORT_KEY_LIGHT_TYPE_SHIFT+2); - } - - lit=true; - } - - - const RID *liptr = p_instance->light_instances.ptr(); - int ilc=p_instance->light_instances.size(); - - - - for(int i=0;ilast_pass!=render_pass) //lit by light not in visible scene - continue; - - -// if (li->base->shadow_enabled) { -// light_type|=0x8; -// } - - RenderList::Element *ec; - if (duplicate) { - - ec = render_list.add_element(); - copymem(ec,e,sizeof(RenderList::Element)); - } else { - - duplicate=true; - ec=e; - } - - ec->additive_ptr=&e->additive; - - ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - ec->sort_key|=uint64_t(li->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; - ec->sort_key|=uint64_t(li->light_ptr->type) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; - - lit=true; - } - - - if (!lit) { - e->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - e->sort_key|=uint64_t(0xE)<sort_key|=uint64_t(0xFFFF)<sort_key|=RenderList::SORT_KEY_UNSHADED_FLAG; } - - } void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { @@ -1534,13 +1461,149 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri } +void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& p_camera_inverse_transform) { + + LightInstance *li = directional_lights[p_index]; + + LightDataUBO ubo_data; //used for filling + + float sign = li->light_ptr->negative?-1:1; + + Color linear_col = li->light_ptr->color.to_linear(); + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; + + //omni, keep at 0 + ubo_data.light_pos_inv_radius[0]=0.0; + ubo_data.light_pos_inv_radius[1]=0.0; + ubo_data.light_pos_inv_radius[2]=0.0; + ubo_data.light_pos_inv_radius[3]=0.0; + + Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); + ubo_data.light_direction_attenuation[0]=direction.x; + ubo_data.light_direction_attenuation[1]=direction.y; + ubo_data.light_direction_attenuation[2]=direction.z; + ubo_data.light_direction_attenuation[3]=1.0; + + ubo_data.light_params[0]=0; + ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[2]=0; + ubo_data.light_params[3]=0; + + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; + + + if (li->light_ptr->shadow) { + + int shadow_count=0; + + switch(li->light_ptr->directional_shadow_mode) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { + shadow_count=1; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { + shadow_count=2; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { + shadow_count=4; + } break; + + } + + for(int j=0;jdirectional_rect.pos.x; + uint32_t y=li->directional_rect.pos.y; + uint32_t width=li->directional_rect.size.x; + uint32_t height=li->directional_rect.size.y; + + + + if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + + width/=2; + height/=2; + + if (j==0) { + + } else if (j==1) { + x+=width; + } else if (j==2) { + y+=height; + } else if (j==3) { + x+=width; + y+=height; + + } + + + + } else if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + + height/=2; + + if (j==0) { + + } else { + y+=height; + } + + } + + ubo_data.shadow_split_offsets[j]=1.0/li->shadow_transform[j].split; + + Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse(); + + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); + rectm.set_light_atlas_rect(atlas_rect); + +// print_line("atlas rect: "+atlas_rect); + + CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; + + store_camera(shadow_mtx,&ubo_data.shadow_matrix1[16*j]); + + ubo_data.light_clamp[0]=atlas_rect.pos.x; + ubo_data.light_clamp[1]=atlas_rect.pos.y; + ubo_data.light_clamp[2]=atlas_rect.size.x; + ubo_data.light_clamp[3]=atlas_rect.size.y; + + } + + } + + glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightDataUBO), &ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + directional_light=li; + + glBindBufferBase(GL_UNIFORM_BUFFER,3,state.directional_ubo); + +} + void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cull_count,const Transform& p_camera_inverse_transform,const CameraMatrix& p_camera_projection,RID p_shadow_atlas) { + state.omni_light_count=0; + state.spot_light_count=0; + state.directional_light_count=0; + + directional_light=NULL; + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - directional_light_instance_count=0; - light_instance_count=0; for(int i=0;ilight_ptr->type) { case VS::LIGHT_DIRECTIONAL: { - ERR_FAIL_COND( directional_light_instance_count >= RenderList::MAX_LIGHTS); - directional_light_instances[directional_light_instance_count++]=li; - - Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; - - //omni, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=0.0; - li->light_ubo_data.light_pos_inv_radius[1]=0.0; - li->light_ubo_data.light_pos_inv_radius[2]=0.0; - li->light_ubo_data.light_pos_inv_radius[3]=0.0; - - Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); - li->light_ubo_data.light_direction_attenuation[0]=direction.x; - li->light_ubo_data.light_direction_attenuation[1]=direction.y; - li->light_ubo_data.light_direction_attenuation[2]=direction.z; - li->light_ubo_data.light_direction_attenuation[3]=1.0; - - li->light_ubo_data.light_params[0]=0; - li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[2]=0; - li->light_ubo_data.light_params[3]=0; - - if (li->light_ptr->shadow) { - - int shadow_count=0; - - switch(li->light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - shadow_count=1; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { - shadow_count=2; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - shadow_count=4; - } break; - - } - - for(int j=0;jdirectional_rect.pos.x; - uint32_t y=li->directional_rect.pos.y; - uint32_t width=li->directional_rect.size.x; - uint32_t height=li->directional_rect.size.y; - - - - if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - - width/=2; - height/=2; - - if (j==0) { - - } else if (j==1) { - x+=width; - } else if (j==2) { - y+=height; - } else if (j==3) { - x+=width; - y+=height; - - } - - - - } else if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - - height/=2; - - if (j==0) { - - } else { - y+=height; - } - - } - - li->light_ubo_data.shadow_split_offsets[j]=1.0/li->shadow_transform[j].split; - - Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse(); - - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); - rectm.set_light_atlas_rect(atlas_rect); - -// print_line("atlas rect: "+atlas_rect); - - CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; - - store_camera(shadow_mtx,&li->light_ubo_data.shadow_matrix1[16*j]); - - li->light_ubo_data.light_clamp[0]=atlas_rect.pos.x; - li->light_ubo_data.light_clamp[1]=atlas_rect.pos.y; - li->light_ubo_data.light_clamp[2]=atlas_rect.size.x; - li->light_ubo_data.light_clamp[3]=atlas_rect.size.y; - - } - + if (state.directional_light_countlight_ptr->negative?-1:1; + Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; + Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); //directional, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=pos.x; - li->light_ubo_data.light_pos_inv_radius[1]=pos.y; - li->light_ubo_data.light_pos_inv_radius[2]=pos.z; - li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + ubo_data.light_pos_inv_radius[0]=pos.x; + ubo_data.light_pos_inv_radius[1]=pos.y; + ubo_data.light_pos_inv_radius[2]=pos.z; + ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); - li->light_ubo_data.light_direction_attenuation[0]=0; - li->light_ubo_data.light_direction_attenuation[1]=0; - li->light_ubo_data.light_direction_attenuation[2]=0; - li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + ubo_data.light_direction_attenuation[0]=0; + ubo_data.light_direction_attenuation[1]=0; + ubo_data.light_direction_attenuation[2]=0; + ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - li->light_ubo_data.light_params[0]=0; - li->light_ubo_data.light_params[1]=0; - li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[3]=0; + ubo_data.light_params[0]=0; + ubo_data.light_params[1]=0; + ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[3]=0; + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { // fill in the shadow information @@ -1724,17 +1692,21 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu Transform proj = (p_camera_inverse_transform * li->transform).inverse(); - store_transform(proj,li->light_ubo_data.shadow_matrix1); + store_transform(proj,ubo_data.shadow_matrix1); - li->light_ubo_data.light_params[3]=1.0; //means it has shadow - li->light_ubo_data.light_clamp[0]=float(x)/atlas_size; - li->light_ubo_data.light_clamp[1]=float(y)/atlas_size; - li->light_ubo_data.light_clamp[2]=float(width)/atlas_size; - li->light_ubo_data.light_clamp[3]=float(height)/atlas_size; + ubo_data.light_params[3]=1.0; //means it has shadow + ubo_data.light_clamp[0]=float(x)/atlas_size; + ubo_data.light_clamp[1]=float(y)/atlas_size; + ubo_data.light_clamp[2]=float(width)/atlas_size; + ubo_data.light_clamp[3]=float(height)/atlas_size; } + li->light_index=state.omni_light_count; + copymem(&state.omni_array_tmp[li->light_index*state.ubo_light_size],&ubo_data,state.ubo_light_size); + state.omni_light_count++; + #if 0 @@ -1746,30 +1718,38 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } break; case VS::LIGHT_SPOT: { + float sign = li->light_ptr->negative?-1:1; + Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); //directional, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=pos.x; - li->light_ubo_data.light_pos_inv_radius[1]=pos.y; - li->light_ubo_data.light_pos_inv_radius[2]=pos.z; - li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + ubo_data.light_pos_inv_radius[0]=pos.x; + ubo_data.light_pos_inv_radius[1]=pos.y; + ubo_data.light_pos_inv_radius[2]=pos.z; + ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); - li->light_ubo_data.light_direction_attenuation[0]=direction.x; - li->light_ubo_data.light_direction_attenuation[1]=direction.y; - li->light_ubo_data.light_direction_attenuation[2]=direction.z; - li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + ubo_data.light_direction_attenuation[0]=direction.x; + ubo_data.light_direction_attenuation[1]=direction.y; + ubo_data.light_direction_attenuation[2]=direction.z; + ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - li->light_ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - li->light_ubo_data.light_params[1]=Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); - li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[3]=0; + ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; + ubo_data.light_params[1]=Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); + ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[3]=0; + + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { // fill in the shadow information @@ -1796,11 +1776,11 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu Rect2 rect(float(x)/atlas_size,float(y)/atlas_size,float(width)/atlas_size,float(height)/atlas_size); - li->light_ubo_data.light_params[3]=1.0; //means it has shadow - li->light_ubo_data.light_clamp[0]=rect.pos.x; - li->light_ubo_data.light_clamp[1]=rect.pos.y; - li->light_ubo_data.light_clamp[2]=rect.size.x; - li->light_ubo_data.light_clamp[3]=rect.size.y; + ubo_data.light_params[3]=1.0; //means it has shadow + ubo_data.light_clamp[0]=rect.pos.x; + ubo_data.light_clamp[1]=rect.pos.y; + ubo_data.light_clamp[2]=rect.size.x; + ubo_data.light_clamp[3]=rect.size.y; Transform modelview = (p_camera_inverse_transform * li->transform).inverse(); @@ -1811,10 +1791,15 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; - store_camera(shadow_mtx,li->light_ubo_data.shadow_matrix1); + store_camera(shadow_mtx,ubo_data.shadow_matrix1); } + + li->light_index=state.spot_light_count; + copymem(&state.spot_array_tmp[li->light_index*state.ubo_light_size],&ubo_data,state.ubo_light_size); + state.spot_light_count++; + #if 0 if (li->light_ptr->shadow_enabled) { CameraMatrix bias; @@ -1829,24 +1814,34 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } - /* make light hash */ - - // actually, not really a hash, but helps to sort the lights - // and avoid recompiling redudant shader versions - - li->last_pass=render_pass; - li->light_index=i; //update UBO for forward rendering, blit to texture for clustered - glBindBuffer(GL_UNIFORM_BUFFER, li->light_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightInstance::LightDataUBO), &li->light_ubo_data); + } + + + + if (state.omni_light_count) { + + glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, state.omni_light_count*state.ubo_light_size, state.omni_array_tmp); glBindBuffer(GL_UNIFORM_BUFFER, 0); - light_instances[i]=li; - light_instance_count++; + glBindBufferBase(GL_UNIFORM_BUFFER,4,state.omni_array_ubo); } + + if (state.spot_light_count) { + + glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, state.spot_light_count*state.ubo_light_size, state.spot_array_tmp); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glBindBufferBase(GL_UNIFORM_BUFFER,5,state.spot_array_ubo); + } + + + } void RasterizerSceneGLES3::_copy_screen() { @@ -1969,6 +1964,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C //first of all, make a new render pass render_pass++; + //fill up ubo Environment *env = environment_owner.getornull(p_environment); @@ -2075,7 +2071,20 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false); + if (state.directional_light_count==0) { + directional_light=NULL; + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,false); + } else { + for(int i=0;i0) { + glEnable(GL_BLEND); + } + _setup_directional_light(i,p_cam_transform.affine_inverse()); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,i>0); + + } + } state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); @@ -2107,9 +2116,20 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.sort_by_depth(true); - _render_list(&render_list.elements[render_list.max_elements-render_list.alpha_element_count],render_list.alpha_element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,true,false); + if (state.directional_light_count==0) { + directional_light=NULL; + _render_list(&render_list.elements[render_list.max_elements-render_list.alpha_element_count],render_list.alpha_element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,true,false,false); + } else { + for(int i=0;i0); + + } + } + _copy_to_front_buffer(env); /* if (shadow_atlas) { @@ -2123,7 +2143,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } */ - if (directional_shadow.fbo) { + if (false && directional_shadow.fbo) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -2285,6 +2305,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa render_pass++; + directional_light=NULL; + LightInstance *light_instance = light_instance_owner.getornull(p_light); ERR_FAIL_COND(!light_instance); RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light); @@ -2512,7 +2534,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); - _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true); + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); @@ -2593,7 +2615,6 @@ bool RasterizerSceneGLES3::free(RID p_rid) { } - glDeleteBuffers(1,&light_instance->light_ubo); light_instance_owner.free(p_rid); memdelete(light_instance); @@ -2860,6 +2881,53 @@ void RasterizerSceneGLES3::initialize() { ERR_PRINT("Directional shadow framebuffer status invalid"); } } + + { + //spot and omni ubos + + int max_ubo_size; + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE,&max_ubo_size); + const int ubo_light_size=160; + state.ubo_light_size=ubo_light_size; + state.max_ubo_lights=max_ubo_size/ubo_light_size; + + state.spot_array_tmp = (uint8_t*)memalloc(ubo_light_size*state.max_ubo_lights); + state.omni_array_tmp = (uint8_t*)memalloc(ubo_light_size*state.max_ubo_lights); + + + glGenBuffers(1, &state.spot_array_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); + glBufferData(GL_UNIFORM_BUFFER, ubo_light_size*state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glGenBuffers(1, &state.omni_array_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); + glBufferData(GL_UNIFORM_BUFFER, ubo_light_size*state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glGenBuffers(1, &state.directional_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + state.max_forward_lights_per_object=8; + + state.scene_shader.add_custom_define("#define MAX_LIGHT_DATA_STRUCTS "+itos(state.max_ubo_lights)+"\n"); + state.scene_shader.add_custom_define("#define MAX_FORWARD_LIGHTS "+itos(state.max_forward_lights_per_object)+"\n"); + + + + } + + GLOBAL_DEF("rendering/gles3/shadow_filter_mode",1); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/shadow_filter_mode",PropertyInfo(Variant::INT,"rendering/gles3/shadow_filter_mode",PROPERTY_HINT_ENUM,"Disabled,PCF5,PCF13")); + shadow_filter_mode=SHADOW_FILTER_NEAREST; + +} + +void RasterizerSceneGLES3::iteration() { + + shadow_filter_mode=ShadowFilterMode(int(Globals::get_singleton()->get("rendering/gles3/shadow_filter_mode"))); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index d7beebbcf6d..24b6a36fcca 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -8,6 +8,15 @@ class RasterizerSceneGLES3 : public RasterizerScene { public: + enum ShadowFilterMode { + SHADOW_FILTER_NEAREST, + SHADOW_FILTER_PCF5, + SHADOW_FILTER_PCF13, + }; + + + ShadowFilterMode shadow_filter_mode; + uint64_t shadow_atlas_realloc_tolerance_msec; @@ -27,6 +36,7 @@ public: struct State { + bool texscreen_copied; int current_blend_mode; float current_line_width; @@ -73,6 +83,22 @@ public: GLuint skybox_verts; GLuint skybox_array; + GLuint directional_ubo; + + GLuint spot_array_ubo; + GLuint omni_array_ubo; + + uint32_t ubo_light_size; + uint8_t *spot_array_tmp; + uint8_t *omni_array_tmp; + + int max_ubo_lights; + int max_forward_lights_per_object; + + int spot_light_count; + int omni_light_count; + int directional_light_count; + bool cull_front; } state; @@ -204,6 +230,22 @@ public: /* LIGHT INSTANCE */ + struct LightDataUBO { + + float light_pos_inv_radius[4]; + float light_direction_attenuation[4]; + float light_color_energy[4]; + float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled + float light_clamp[4]; + float light_shadow_color[4]; + float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional + float shadow_matrix2[16]; + float shadow_matrix3[16]; + float shadow_matrix4[16]; + float shadow_split_offsets[4]; + + }; + struct LightInstance : public RID_Data { struct ShadowTransform { @@ -214,20 +256,6 @@ public: float split; }; - struct LightDataUBO { - - float light_pos_inv_radius[4]; - float light_direction_attenuation[4]; - float light_color_energy[4]; - float light_params[4]; //cone attenuation, specular, shadow darkening, - float light_clamp[4]; //cone attenuation, specular, shadow darkening, - float shadow_split_offsets[4]; - float shadow_matrix1[16]; - float shadow_matrix2[16]; - float shadow_matrix3[16]; - float shadow_matrix4[16]; - - } light_ubo_data; ShadowTransform shadow_transform[4]; @@ -241,8 +269,6 @@ public: Vector3 spot_vector; float linear_att; - GLuint light_ubo; - uint64_t shadow_pass; uint64_t last_scene_pass; uint64_t last_scene_shadow_pass; @@ -280,14 +306,16 @@ public: SORT_FLAG_INSTANCING=2, MAX_DIRECTIONAL_LIGHTS=16, MAX_LIGHTS=4096, - SORT_KEY_DEPTH_LAYER_SHIFT=58, - SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important - SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important - SORT_KEY_LIGHT_INDEX_UNSHADED=uint64_t(0xF) << SORT_KEY_LIGHT_TYPE_SHIFT, //type is most important - SORT_KEY_LIGHT_MASK=(uint64_t(0xFFFFF) << SORT_KEY_LIGHT_INDEX_SHIFT), //type is most important - SORT_KEY_MATERIAL_INDEX_SHIFT=22, - SORT_KEY_GEOMETRY_INDEX_SHIFT=6, - SORT_KEY_GEOMETRY_TYPE_SHIFT=2, + + + SORT_KEY_DEPTH_LAYER_SHIFT=60, + SORT_KEY_UNSHADED_FLAG=uint64_t(1)<<59, + SORT_KEY_NO_DIRECTIONAL_FLAG=uint64_t(1)<<58, + SORT_KEY_SHADING_SHIFT=58, + SORT_KEY_SHADING_MASK=3, + SORT_KEY_MATERIAL_INDEX_SHIFT=40, + SORT_KEY_GEOMETRY_INDEX_SHIFT=20, + SORT_KEY_GEOMETRY_TYPE_SHIFT=15, SORT_KEY_SKELETON_FLAG=2, SORT_KEY_MIRROR_FLAG=1 @@ -302,8 +330,6 @@ public: RasterizerStorageGLES3::Material *material; RasterizerStorageGLES3::GeometryOwner *owner; uint64_t sort_key; - bool *additive_ptr; - bool additive; }; @@ -314,6 +340,7 @@ public: int element_count; int alpha_element_count; + void clear() { element_count=0; @@ -399,12 +426,10 @@ public: }; + LightInstance *directional_light; + LightInstance *directional_lights[RenderList::MAX_DIRECTIONAL_LIGHTS]; - LightInstance *directional_light_instances[RenderList::MAX_DIRECTIONAL_LIGHTS]; - int directional_light_instance_count; - LightInstance *light_instances[RenderList::MAX_LIGHTS]; - int light_instance_count; RenderList render_list; @@ -414,9 +439,9 @@ public: _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); - _FORCE_INLINE_ void _setup_light(LightInstance *p_light); + _FORCE_INLINE_ void _setup_light(RenderList::Element *e); - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow); + void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add); _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow); @@ -424,6 +449,7 @@ public: void _draw_skybox(RID p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_transform); + void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix& p_camera_projection, RID p_shadow_atlas); void _copy_screen(); void _copy_to_front_buffer(Environment *env); @@ -439,6 +465,7 @@ public: virtual void set_scene_pass(uint64_t p_pass); + void iteration(); void initialize(); void finalize(); RasterizerSceneGLES3(); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b988781e14a..6e278e563bc 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -3169,7 +3169,6 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->param[VS::LIGHT_PARAM_RANGE]=1.0; light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45; light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0; - light->param[VS::LIGHT_PARAM_SHADOW_DARKNESS]=0; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6; @@ -3184,6 +3183,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; light->omni_shadow_mode=VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; light->omni_shadow_detail=VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; + light->directional_blend_splits=false; light->version=0; @@ -3207,7 +3207,6 @@ void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param, case VS::LIGHT_PARAM_RANGE: case VS::LIGHT_PARAM_SPOT_ANGLE: case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: - case VS::LIGHT_PARAM_SHADOW_DARKNESS: case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: @@ -3230,20 +3229,22 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ light->version++; light->instance_change_notify(); +} +void RasterizerStorageGLES3::light_set_shadow_color(RID p_light,const Color& p_color) { + + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->shadow_color=p_color; } + void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ Light * light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); - -} -void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_texture){ - - Light * light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); + light->projector=p_texture; } void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){ @@ -3263,12 +3264,6 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){ light->version++; light->instance_change_notify(); -} -void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ - - Light * light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - } void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { @@ -3315,6 +3310,26 @@ void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::L } +void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light,bool p_enable) { + + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_blend_splits=p_enable; + light->version++; + light->instance_change_notify(); + +} + + +bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,false); + + return light->directional_blend_splits; +} + VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) { const Light * light = light_owner.getornull(p_light); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index f8b34d6a162..0e3d47b61f6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -634,12 +634,15 @@ public: VS::LightType type; float param[VS::LIGHT_PARAM_MAX]; Color color; + Color shadow_color; + RID projector; bool shadow; bool negative; uint32_t cull_mask; VS::LightOmniShadowMode omni_shadow_mode; VS::LightOmniShadowDetail omni_shadow_detail; VS::LightDirectionalShadowMode directional_shadow_mode; + bool directional_blend_splits; uint64_t version; }; @@ -650,17 +653,19 @@ public: virtual void light_set_color(RID p_light,const Color& p_color); virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value); virtual void light_set_shadow(RID p_light,bool p_enabled); + virtual void light_set_shadow_color(RID p_light,const Color& p_color); virtual void light_set_projector(RID p_light,RID p_texture); - virtual void light_set_attenuation_texure(RID p_light,RID p_texture); virtual void light_set_negative(RID p_light,bool p_enable); virtual void light_set_cull_mask(RID p_light,uint32_t p_mask); - virtual void light_set_shader(RID p_light,RID p_shader); + virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); - virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail); virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable); + virtual bool light_directional_get_blend_splits(RID p_light) const; + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 052c9152419..6f0616035a7 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -228,8 +228,15 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { #endif + int define_line_ofs=1; + for(int i=0;i custom_defines; + int base_material_tex_index; Version * get_current_version(); @@ -357,6 +359,10 @@ public: void set_base_material_tex_index(int p_idx); + void add_custom_define(const String& p_define) { + custom_defines.push_back(p_define.utf8()); + } + virtual ~ShaderGLES3(); }; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index de1591e8ff6..ceb5a721182 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -68,24 +68,26 @@ layout(std140) uniform SceneData { //ubo:0 uniform highp mat4 world_transform; -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { //ubo:3 +layout(std140) uniform DirectionalLightData { //ubo:3 highp vec4 light_pos_inv_radius; mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; - mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; #endif + /* Varyings */ out highp vec3 vertex_interp; @@ -343,30 +345,71 @@ layout(std140) uniform SceneData { }; +//directional light data -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { +layout(std140) uniform DirectionalLightData { highp vec4 light_pos_inv_radius; mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; - mediump vec4 light_params; //cone attenuation, specular, shadow darkening, shadow enabled + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; -#endif - uniform highp sampler2DShadow directional_shadow; //texunit:-4 + +#endif + +//omni and spot + +struct LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color; + highp mat4 shadow_matrix; + +}; + + +layout(std140) uniform OmniLightData { //ubo:4 + + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +layout(std140) uniform SpotLightData { //ubo:5 + + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + + uniform highp sampler2DShadow shadow_atlas; //texunit:-3 +#ifdef USE_FORWARD_LIGHTING + +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; + +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; + +#endif + + + #ifdef USE_MULTIPLE_RENDER_TARGETS layout(location=0) out vec4 diffuse_buffer; @@ -415,18 +458,51 @@ float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0) return dotNL * D * F * vis; } -void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, vec3 specular_color, float roughness, float attenuation, inout vec3 diffuse, inout vec3 specular) { +void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - diffuse += max(0.0,dot(normal,light_vec)) * diffuse_color * attenuation; + diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color; //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation; float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0; - specular += s * specular_color * attenuation; + specular += s * light_color * specular_color; } float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { +#ifdef SHADOW_MODE_PCF_13 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y*2.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y*2.0),depth,1.0)); + return avg*(1.0/13.0); + +#endif + +#ifdef SHADOW_MODE_PCF_5 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + return avg*(1.0/5.0); +#endif + +#if !defined(SHADOW_MODE_PCF_5) && !defined(SHADOW_MODE_PCF_13) + return textureProj(shadow,vec4(pos,depth,1.0)); +#endif + } #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -435,6 +511,73 @@ in highp float dp_clip; #endif +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; + float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w )); + + if (omni_lights[idx].light_params.w>0.5) { + //there is a shadowmap + + highp vec3 splane=(omni_lights[idx].shadow_matrix * vec4(vertex,1.0)).xyz; + float shadow_len=length(splane); + splane=normalize(splane); + vec4 clamp_rect=omni_lights[idx].light_clamp; + + if (splane.z>=0.0) { + + splane.z+=1.0; + + clamp_rect.y+=clamp_rect.w; + + } else { + + splane.z=1.0 - splane.z; + + //if (clamp_rect.z0.5) { + //there is a shadowmap + highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0)); + splane.xyz/=splane.w; + light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp)); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); + +} + void main() { #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -561,9 +704,9 @@ FRAGMENT_SHADER_CODE #endif -#ifdef USE_FORWARD_DIRECTIONAL +#ifdef USE_LIGHT_DIRECTIONAL - float light_attenuation=1.0; + vec3 light_attenuation=vec3(1.0); #ifdef LIGHT_DIRECTIONAL_SHADOW @@ -589,7 +732,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(1.0,0.4,0.4); #if defined(LIGHT_USE_PSSM_BLEND) @@ -603,7 +745,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(0.4,1.0,0.4); #if defined(LIGHT_USE_PSSM_BLEND) splane=(shadow_matrix3 * vec4(vertex,1.0)); @@ -619,7 +760,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(0.4,0.4,1.0); #if defined(LIGHT_USE_PSSM_BLEND) splane=(shadow_matrix4 * vec4(vertex,1.0)); @@ -678,12 +818,12 @@ FRAGMENT_SHADER_CODE //one one sample - light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp); + light_attenuation=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp)); #if defined(LIGHT_USE_PSSM_BLEND) if (use_blend) { - float light_attenuation2=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp); + vec3 light_attenuation2=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp)); light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend); } #endif @@ -692,84 +832,24 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_DIRECTIONAL_SHADOW - light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); -#endif //USE_FORWARD_DIRECTIONAL +#endif //#USE_LIGHT_DIRECTIONAL -#ifdef USE_FORWARD_OMNI +#ifdef USE_FORWARD_LIGHTING - vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex; - float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w; - float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w ); - - if (light_params.w>0.5) { - //there is a shadowmap - - highp vec3 splane=(shadow_matrix1 * vec4(vertex,1.0)).xyz; - float shadow_len=length(splane); - splane=normalize(splane); - vec4 clamp_rect=light_clamp; - - if (splane.z>=0.0) { - - splane.z+=1.0; - - clamp_rect.y+=clamp_rect.w; - - } else { - - splane.z=1.0 - splane.z; - - //if (clamp_rect.z0.5) { - //there is a shadowmap - - highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); - splane.xyz/=splane.w; - // splane.xy=splane.xy*0.5+0.5; - - //splane.xy=light_clamp.xy+splane.xy*light_clamp.zw; - light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,light_clamp); - + for(int i=0;ilight_set_shadow_color(light,p_shadow_color); +} + +Color Light::get_shadow_color() const{ + + return shadow_color; +} + AABB Light::get_aabb() const { @@ -197,18 +208,18 @@ void Light::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_color","color"), &Light::set_color ); ObjectTypeDB::bind_method(_MD("get_color"), &Light::get_color ); - ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light/color"), _SCS("set_color"), _SCS("get_color")); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/energy"), _SCS("set_param"), _SCS("get_param"), PARAM_ENERGY); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "light/negative"), _SCS("set_negative"), _SCS("is_negative")); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/specular"), _SCS("set_param"), _SCS("get_param"), PARAM_SPECULAR); - ADD_PROPERTY( PropertyInfo( Variant::INT, "light/cull_mask"), _SCS("set_cull_mask"), _SCS("get_cull_mask")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/enabled"), _SCS("set_shadow"), _SCS("has_shadow")); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkness"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_DARKNESS); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/normal_bias"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_NORMAL_BIAS); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias_split_scale"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS_SPLIT_SCALE); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/max_distance"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_MAX_DISTANCE); + ObjectTypeDB::bind_method(_MD("set_shadow_color","shadow_color"), &Light::set_shadow_color ); + ObjectTypeDB::bind_method(_MD("get_shadow_color"), &Light::get_shadow_color ); + ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light/color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_color"), _SCS("get_color")); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/energy",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_ENERGY); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "light/negative"), _SCS("set_negative"), _SCS("is_negative")); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/specular",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SPECULAR); + ADD_PROPERTY( PropertyInfo( Variant::INT, "light/cull_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_cull_mask"), _SCS("get_cull_mask")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/enabled"), _SCS("set_shadow"), _SCS("has_shadow")); + ADD_PROPERTY( PropertyInfo( Variant::COLOR, "shadow/color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_shadow_color"), _SCS("get_shadow_color")); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/max_distance",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_MAX_DISTANCE); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editor/editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only")); BIND_CONSTANT( PARAM_ENERGY ); @@ -218,7 +229,6 @@ void Light::_bind_methods() { BIND_CONSTANT( PARAM_SPOT_ANGLE ); BIND_CONSTANT( PARAM_SPOT_ATTENUATION ); BIND_CONSTANT( PARAM_SHADOW_MAX_DISTANCE ); - BIND_CONSTANT( PARAM_SHADOW_DARKNESS ); BIND_CONSTANT( PARAM_SHADOW_SPLIT_1_OFFSET ); BIND_CONSTANT( PARAM_SHADOW_SPLIT_2_OFFSET ); BIND_CONSTANT( PARAM_SHADOW_SPLIT_3_OFFSET ); @@ -250,7 +260,6 @@ Light::Light(VisualServer::LightType p_type) { set_param(PARAM_SPOT_ANGLE,45); set_param(PARAM_SPOT_ATTENUATION,1); set_param(PARAM_SHADOW_MAX_DISTANCE,0); - set_param(PARAM_SHADOW_DARKNESS,0); set_param(PARAM_SHADOW_SPLIT_1_OFFSET,0.1); set_param(PARAM_SHADOW_SPLIT_2_OFFSET,0.2); set_param(PARAM_SHADOW_SPLIT_3_OFFSET,0.5); @@ -291,6 +300,7 @@ DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const { void DirectionalLight::set_blend_splits(bool p_enable) { blend_splits=p_enable; + VS::get_singleton()->light_directional_set_blend_splits(light,p_enable); } bool DirectionalLight::is_blend_splits_enabled() const { @@ -307,11 +317,13 @@ void DirectionalLight::_bind_methods() { ObjectTypeDB::bind_method( _MD("set_blend_splits","enabled"),&DirectionalLight::set_blend_splits); ObjectTypeDB::bind_method( _MD("is_blend_splits_enabled"),&DirectionalLight::is_blend_splits_enabled); - ADD_PROPERTY( PropertyInfo( Variant::INT, "directional/shadow_mode",PROPERTY_HINT_ENUM,"Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode")); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_1_OFFSET); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_2"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_2_OFFSET); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_3"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_3_OFFSET); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "directional/blend_splits"), _SCS("set_blend_splits"), _SCS("is_blend_splits_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "directional_shadow/mode",PROPERTY_HINT_ENUM,"Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode")); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow/split_1",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_1_OFFSET); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow/split_2",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_2_OFFSET); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow/split_3",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_3_OFFSET); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "directional_shadow/blend_splits"), _SCS("set_blend_splits"), _SCS("is_blend_splits_enabled")); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow/normal_bias",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_NORMAL_BIAS); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow/bias_split_scale",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS_SPLIT_SCALE); BIND_CONSTANT( SHADOW_ORTHOGONAL ); BIND_CONSTANT( SHADOW_PARALLEL_2_SPLITS ); @@ -358,8 +370,8 @@ void OmniLight::_bind_methods() { ObjectTypeDB::bind_method( _MD("set_shadow_detail","detail"),&OmniLight::set_shadow_detail); ObjectTypeDB::bind_method( _MD("get_shadow_detail"),&OmniLight::get_shadow_detail); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/range"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/range",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION); ADD_PROPERTY( PropertyInfo( Variant::INT, "omni/shadow_mode",PROPERTY_HINT_ENUM,"Dual Paraboloid,Cube"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode")); ADD_PROPERTY( PropertyInfo( Variant::INT, "omni/shadow_detail",PROPERTY_HINT_ENUM,"Vertical,Horizontal"), _SCS("set_shadow_detail"), _SCS("get_shadow_detail")); @@ -374,10 +386,10 @@ OmniLight::OmniLight() : Light( VisualServer::LIGHT_OMNI ) { void SpotLight::_bind_methods() { - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/range"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_angle"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ANGLE); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ATTENUATION); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/range",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_angle",PROPERTY_HINT_RANGE,"0,180,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ANGLE); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ATTENUATION); } diff --git a/scene/3d/light.h b/scene/3d/light.h index da285428178..fcf5ce90f9d 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -52,7 +52,6 @@ public: PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE, PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION, PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, - PARAM_SHADOW_DARKNESS = VS::LIGHT_PARAM_SHADOW_DARKNESS, PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, @@ -66,6 +65,7 @@ private: Color color; float param[PARAM_MAX]; + Color shadow_color; bool shadow; bool negative; uint32_t cull_mask; @@ -107,6 +107,9 @@ public: void set_color(const Color& p_color); Color get_color() const; + void set_shadow_color(const Color& p_shadow_color); + Color get_shadow_color() const; + virtual AABB get_aabb() const; virtual DVector get_faces(uint32_t p_usage_flags) const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index d87cc0fd8c0..06509c6fd09 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -78,6 +78,7 @@ public: Transform transform; int depth_layer; + uint32_t layer_mask; //RID sampled_light; @@ -114,6 +115,7 @@ public: billboard=false; billboard_y=false; depth_layer=0; + layer_mask=1; } }; @@ -295,16 +297,17 @@ public: virtual void light_set_color(RID p_light,const Color& p_color)=0; virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value)=0; virtual void light_set_shadow(RID p_light,bool p_enabled)=0; + virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0; virtual void light_set_projector(RID p_light,RID p_texture)=0; - virtual void light_set_attenuation_texure(RID p_light,RID p_texture)=0; virtual void light_set_negative(RID p_light,bool p_enable)=0; virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0; - virtual void light_set_shader(RID p_light,RID p_shader)=0; virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode)=0; virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail)=0; virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode)=0; + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0; + virtual bool light_directional_get_blend_splits(RID p_light) const=0; virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light)=0; virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light)=0; diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 7810cc90181..4d8a46122cd 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -757,16 +757,16 @@ public: BIND2(light_set_color,RID,const Color&) BIND3(light_set_param,RID ,LightParam ,float ) BIND2(light_set_shadow,RID ,bool ) + BIND2(light_set_shadow_color,RID ,const Color& ) BIND2(light_set_projector,RID,RID ) - BIND2(light_set_attenuation_texure,RID,RID ) BIND2(light_set_negative,RID,bool ) BIND2(light_set_cull_mask,RID ,uint32_t ) - BIND2(light_set_shader,RID ,RID ) BIND2(light_omni_set_shadow_mode,RID,LightOmniShadowMode) BIND2(light_omni_set_shadow_detail,RID,LightOmniShadowDetail) BIND2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode) + BIND2(light_directional_set_blend_splits,RID,bool) /* PROBE API */ diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index e36e31e1914..e214374f4d5 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -1165,7 +1165,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer float texture_size=VSG::scene_render->get_directional_light_shadow_size(light->instance); - bool overlap = false;//rasterizer->light_instance_get_pssm_shadow_overlap(p_light->light_info->instance); + bool overlap = VSG::storage->light_directional_get_blend_splits(p_instance->base); for (int i=0;i