summaryrefslogtreecommitdiff
path: root/drivers/gles3
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-11-09 23:55:06 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-11-09 23:55:06 -0300
commitcacf9ebb7fd8df8845daca9da2fe55456cc179aa (patch)
tree5881cb42ace5001916e9d1843f5a7acbc35332a6 /drivers/gles3
parent6b2a27bbe5fa112365fc88b9b4678a61293bcb53 (diff)
all light types and shadows are working, pending a lot of clean-up
Diffstat (limited to 'drivers/gles3')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp1043
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h74
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp324
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h101
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp15
-rw-r--r--drivers/gles3/shader_compiler_gles3.h7
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/cube_to_dp.glsl79
-rw-r--r--drivers/gles3/shaders/scene.glsl341
10 files changed, 1678 insertions, 309 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index c10c5fee65..c455d4bd11 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -824,8 +824,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
bool prev_distance_field=false;
-
-
while(p_item_list) {
Item *ci=p_item_list;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 93dc01d473..287801b597 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1,8 +1,18 @@
#include "rasterizer_scene_gles3.h"
#include "globals.h"
#include "os/os.h"
+#include "rasterizer_canvas_gles3.h"
+static const GLenum _cube_side_enum[6]={
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+
+};
static _FORCE_INLINE_ void store_matrix32(const Matrix32& p_mtx, float* p_array) {
@@ -78,6 +88,9 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size<0);
+
+ p_size = nearest_power_of_2(p_size);
+
if (p_size==shadow_atlas->size)
return;
@@ -104,7 +117,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){
//clear owners
shadow_atlas->shadow_owners.clear();
- shadow_atlas->size=nearest_power_of_2(p_size);
+ shadow_atlas->size=p_size;
if (shadow_atlas->size) {
glGenFramebuffers(1, &shadow_atlas->fbo);
@@ -188,7 +201,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas,int
swaps=0;
for(int i=0;i<3;i++) {
- if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision > shadow_atlas->quadrants[shadow_atlas->size_order[i+1]].subdivision) {
+ if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i+1]].subdivision) {
SWAP(shadow_atlas->size_order[i],shadow_atlas->size_order[i+1]);
swaps++;
}
@@ -260,20 +273,22 @@ bool RasterizerSceneGLES3::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas,i
}
-uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version){
+bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version){
+
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
- ERR_FAIL_COND_V(!shadow_atlas,ShadowAtlas::SHADOW_INVALID);
+ ERR_FAIL_COND_V(!shadow_atlas,false);
LightInstance *li = light_instance_owner.getornull(p_light_intance);
- ERR_FAIL_COND_V(!li,ShadowAtlas::SHADOW_INVALID);
+ ERR_FAIL_COND_V(!li,false);
if (shadow_atlas->size==0 || shadow_atlas->smallest_subdiv==0) {
- return ShadowAtlas::SHADOW_INVALID;
+ return false;
}
uint32_t quad_size = shadow_atlas->size>>1;
- int desired_fit = MAX(quad_size/shadow_atlas->smallest_subdiv,nearest_power_of_2(quad_size*p_coverage));
+ int desired_fit = MIN(quad_size/shadow_atlas->smallest_subdiv,nearest_power_of_2(quad_size*p_coverage));
+
int valid_quadrants[4];
int valid_quadrant_count=0;
@@ -300,8 +315,7 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh
}
}
-
- ERR_FAIL_COND_V(valid_quadrant_count==0,ShadowAtlas::SHADOW_INVALID);
+ ERR_FAIL_COND_V(valid_quadrant_count==0,false);
uint64_t tick = OS::get_singleton()->get_ticks_msec();
@@ -317,13 +331,12 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh
bool should_realloc=shadow_atlas->quadrants[q].subdivision!=best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick-tick > shadow_atlas_realloc_tolerance_msec);
bool should_redraw=shadow_atlas->quadrants[q].shadows[s].version!=p_light_version;
+
+
if (!should_realloc) {
+ shadow_atlas->quadrants[q].shadows[s].version=p_light_version;
//already existing, see if it should redraw or it's just OK
- if (should_redraw) {
- key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT;
- }
-
- return key;
+ return should_redraw;
}
int new_quadrant,new_shadow;
@@ -339,6 +352,10 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh
sli->shadow_atlases.erase(p_atlas);
}
+ //erase previous
+ shadow_atlas->quadrants[q].shadows[s].version=0;
+ shadow_atlas->quadrants[q].shadows[s].owner=RID();
+
sh->owner=p_light_intance;
sh->alloc_tick=tick;
sh->version=p_light_version;
@@ -349,19 +366,16 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh
//update it in map
shadow_atlas->shadow_owners[p_light_intance]=key;
//make it dirty, as it should redraw anyway
- key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT;
-
- return key;
+ return true;
}
//no better place for this shadow found, keep current
//already existing, see if it should redraw or it's just OK
- if (should_redraw) {
- key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT;
- }
- return key;
+ shadow_atlas->quadrants[q].shadows[s].version=p_light_version;
+
+ return should_redraw;
}
int new_quadrant,new_shadow;
@@ -387,20 +401,49 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh
//update it in map
shadow_atlas->shadow_owners[p_light_intance]=key;
//make it dirty, as it should redraw anyway
- key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT;
- return key;
+ return true;
}
//no place to allocate this light, apologies
- return ShadowAtlas::SHADOW_INVALID;
+ return false;
}
+void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) {
+
+ directional_shadow.light_count=p_count;
+ directional_shadow.current_light=0;
+}
+
+int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) {
+
+ ERR_FAIL_COND_V(directional_shadow.light_count==0,0);
+
+ int shadow_size;
+
+ if (directional_shadow.light_count==1) {
+ shadow_size = directional_shadow.size;
+ } else {
+ shadow_size = directional_shadow.size/2; //more than 4 not supported anyway
+ }
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
+ ERR_FAIL_COND_V(!light_instance,0);
+
+ switch(light_instance->light_ptr->directional_shadow_mode) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size/=2; break;
+ }
+
+ return shadow_size;
+
+}
/* ENVIRONMENT API */
@@ -511,6 +554,7 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
light_instance->last_pass=0;
light_instance->last_scene_pass=0;
+ light_instance->last_scene_shadow_pass=0;
light_instance->light=p_light;
light_instance->light_ptr=storage->light_owner.getornull(p_light);
@@ -520,10 +564,11 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
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());
- return light_instance_owner.make_rid(light_instance);
+ light_instance->self=light_instance_owner.make_rid(light_instance);
+
+ return light_instance->self;
}
void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){
@@ -534,6 +579,25 @@ void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,con
light_instance->transform=p_transform;
}
+void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ if (light_instance->light_ptr->type!=VS::LIGHT_DIRECTIONAL) {
+ p_pass=0;
+ }
+
+ ERR_FAIL_INDEX(p_pass,4);
+
+ light_instance->shadow_transform[p_pass].camera=p_projection;
+ light_instance->shadow_transform[p_pass].transform=p_transform;
+ light_instance->shadow_transform[p_pass].far=p_far;
+ light_instance->shadow_transform[p_pass].split=p_split;
+
+}
+
+
void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
@@ -542,7 +606,6 @@ void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
light_instance->last_scene_pass=scene_pass;
}
-
////////////////////////////
////////////////////////////
////////////////////////////
@@ -757,9 +820,10 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) {
-
glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform
}
+
+
void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection) {
if (p_instance->billboard || p_instance->billboard_y || p_instance->depth_scale) {
@@ -815,7 +879,22 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans
}
}
-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) {
+void RasterizerSceneGLES3::_set_cull(bool p_front,bool p_reverse_cull) {
+
+ bool front = p_front;
+ if (p_reverse_cull)
+ front=!front;
+
+ if (front!=state.cull_front) {
+
+ glCullFace(front?GL_FRONT:GL_BACK);
+ state.cull_front=front;
+ }
+}
+
+
+
+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) {
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) {
//p_reverse_cull=!p_reverse_cull;
@@ -824,25 +903,30 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
glFrontFace(GL_CW);
}
- bool shadow=false;
-
glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo
- 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);
+ if (!p_shadow) {
+ 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);
- if (p_base_env) {
- glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2);
- glBindTexture(p_base_env->target,p_base_env->tex_id);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true);
+ if (p_base_env) {
+ glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2);
+ glBindTexture(p_base_env->target,p_base_env->tex_id);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true);
+ } else {
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false);
+
+ }
} else {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false);
}
+ state.cull_front=false;
+ glCullFace(GL_BACK);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false);
@@ -875,28 +959,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
bool additive=false;
- if (!shadow) {
-#if 0
- if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) {
- texscreen_copied=true;
- _copy_to_texscreen();
-
- //force reset state
- prev_material=NULL;
- prev_light=0x777E;
- prev_geometry_cmp=NULL;
- prev_light_type=0xEF;
- prev_skeleton =NULL;
- prev_sort_flags=0xFF;
- prev_morph_values=NULL;
- prev_receive_shadows_state=-1;
- glEnable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
+ if (!p_shadow) {
- }
-#endif
if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) {
if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) {
@@ -905,27 +969,38 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
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::SHADELESS,true);
+ 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,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==VS::LIGHT_DIRECTIONAL);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,light_type==VS::LIGHT_OMNI);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,light_type==VS::LIGHT_SPOT);
- /*
- if (receive_shadows_state==1) {
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,(light_type&0x8));
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,(light_type&0x10));
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,(light_type&0x20));
- }
- else {
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false);
+ 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::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);
+
+ if ((light_type&3)==VS::LIGHT_DIRECTIONAL) {
+
+ if (light_instances[light_index]->light_ptr->shadow) {
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,true);
+
+ switch(light_instances[light_index]->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;
+ }
+ }
}
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
- */
+
+
}
rebind=true;
@@ -1007,14 +1082,16 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
current_blend_mode=desired_blend_mode;
}
- }
- if (light_index!=prev_light_index) {
- if (light_index!=0xFFFF) { //not unshaded
- _setup_light(light_instances[light_index]);
+ if (light_index!=prev_light_index) {
+ if (light_index!=0xFFFF) { //not unshaded
+ _setup_light(light_instances[light_index]);
+ }
}
+
}
+
if (material!=prev_material || rebind) {
rebind = _setup_material(material,p_alpha_pass);
@@ -1027,20 +1104,17 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
_setup_geometry(e);
}
- if (rebind || prev_additive!=additive) {
+ if (!p_shadow && (rebind || prev_additive!=additive)) {
state.scene_shader.set_uniform(SceneShaderGLES3::NO_AMBIENT_LIGHT, additive);
}
-// _set_cull(e->mirror,p_reverse_cull);
+ _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);
_setup_transform(e->instance,p_view_transform,p_projection);
-
-// _render(e->geometry, material, skeleton,e->owner,e->instance->transform);
-
_render_geometry(e);
prev_material=material;
@@ -1052,15 +1126,26 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
}
- //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count));
glFrontFace(GL_CW);
glBindVertexArray(0);
+ 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::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);
+
}
-void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material) {
+
+void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow) {
RasterizerStorageGLES3::Material *m=NULL;
RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material);
@@ -1096,57 +1181,29 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
bool has_alpha = has_base_alpha || has_blend_alpha;
bool shadow = false;
-#if 0
- if (shadow) {
+ bool mirror = p_instance->mirror;
- if (has_blend_alpha || (has_base_alpha && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA))
+ if (m->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) {
+ mirror=!mirror;
+ }
+
+ if (p_shadow) {
+
+ if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
return; //bye
- if (!m->shader_cache || (!m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) {
+ if (!m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
//shader does not use discard and does not write a vertex position, use generic material
if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)
- m = shadow_mat_double_sided_ptr;
+ m = storage->material_owner.getptr(default_material_twosided);
else
- m = shadow_mat_ptr;
- if (m->last_pass!=frame) {
-
- if (m->shader.is_valid()) {
-
- m->shader_cache=shader_owner.get(m->shader);
- if (m->shader_cache) {
-
-
- if (!m->shader_cache->valid)
- m->shader_cache=NULL;
- } else {
- m->shader=RID();
- }
-
- } else {
- m->shader_cache=NULL;
- }
-
- m->last_pass=frame;
- }
+ m = storage->material_owner.getptr(default_material);
}
- render_list = &opaque_render_list;
- /* notyet
- if (!m->shader_cache || m->shader_cache->can_zpass)
- render_list = &alpha_render_list;
- } else {
- render_list = &opaque_render_list;
- }*/
-
- } else {
- if (has_alpha) {
- render_list = &alpha_render_list;
- } else {
- render_list = &opaque_render_list;
+ has_alpha=false;
- }
}
-#endif
+
RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
@@ -1161,50 +1218,49 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
e->additive_ptr=&e->additive;
e->sort_key=0;
-
if (e->geometry->last_pass!=render_pass) {
e->geometry->last_pass=render_pass;
e->geometry->index=current_geometry_index++;
}
+
e->sort_key|=uint64_t(e->geometry->index)<<RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
e->sort_key|=uint64_t(e->instance->base_type)<<RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
- if (e->material->last_pass!=render_pass) {
- e->material->last_pass=render_pass;
- e->material->index=current_material_index++;
- }
+ if (!p_shadow) {
- e->sort_key|=uint64_t(e->material->index)<<RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
- e->sort_key|=uint64_t(e->instance->depth_layer)<<RenderList::SORT_KEY_DEPTH_LAYER_SHIFT;
- //if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
- // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING;
+ if (e->material->last_pass!=render_pass) {
+ e->material->last_pass=render_pass;
+ e->material->index=current_material_index++;
+ }
- bool mirror = e->instance->mirror;
+ e->sort_key|=uint64_t(e->material->index)<<RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
+ e->sort_key|=uint64_t(e->instance->depth_layer)<<RenderList::SORT_KEY_DEPTH_LAYER_SHIFT;
- if (m->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) {
- mirror=!mirror;
- }
+ if (!has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
- if (mirror) {
- e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG;
- }
+ //if nothing exists, add this element as opaque too
+ RenderList::Element *oe = render_list.add_element();
- //e->light_type=0xFF; // no lights!
+ if (!oe)
+ return;
- if (!shadow && !has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ copymem(oe,e,sizeof(RenderList::Element));
+ oe->additive_ptr=&oe->additive;
+ }
+ }
- //if nothing exists, add this element as opaque too
- RenderList::Element *oe = render_list.add_element();
+ //if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
+ // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING;
- if (!oe)
- return;
- copymem(oe,e,sizeof(RenderList::Element));
- oe->additive_ptr=&oe->additive;
+ if (mirror) {
+ e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG;
}
+ //e->light_type=0xFF; // no lights!
+
@@ -1246,7 +1302,12 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
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;
+ 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;
}
@@ -1302,7 +1363,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
}
-void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) {
+void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) {
RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox);
@@ -1382,7 +1443,7 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,
}
-void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_cam_projection,const Transform& p_cam_transform) {
+void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatrix& p_cam_projection,const Transform& p_cam_transform) {
//store camera into ubo
@@ -1444,6 +1505,20 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_c
}
+ {
+ //directional shadow
+
+ state.ubo_data.shadow_directional_pixel_size[0]=1.0/directional_shadow.size;
+ state.ubo_data.shadow_directional_pixel_size[1]=1.0/directional_shadow.size;
+
+ glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-4);
+ glBindTexture(GL_TEXTURE_2D,directional_shadow.depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
+ }
+
+
+
glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
@@ -1459,13 +1534,14 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_c
}
-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) {
+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) {
+
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
directional_light_instance_count=0;
light_instance_count=0;
- Vector<float> lpercent;
-
for(int i=0;i<p_light_cull_count;i++) {
ERR_BREAK( i>=RenderList::MAX_LIGHTS );
@@ -1502,23 +1578,90 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
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;
-#if 0
- if (li->light_ptr->shadow_enabled) {
- CameraMatrix bias;
- bias.set_light_bias();
+ }
+
+ for(int j=0;j<shadow_count;j++) {
+
+
+ uint32_t x=li->directional_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) {
- int passes=light_instance_get_shadow_passes(p_light_instance);
+ 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;
- for(int i=0;i<passes;i++) {
- Transform modelview=Transform(camera_transform_inverse * li->custom_transform[i]).inverse();
- li->shadow_projection[i] = bias * li->custom_projection[i] * modelview;
}
- lights_use_shadow=true;
+
}
-#endif
+
} break;
case VS::LIGHT_OMNI: {
@@ -1542,29 +1685,57 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
li->light_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]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- li->light_ubo_data.light_params[2]=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;
-#if 0
- Transform ai = p_camera_inverse_transform.affine_inverse();
- float zn = p_camera_projection.get_z_near();
- Plane p (ai.origin + ai.basis.get_axis(2) * -zn, -ai.basis.get_axis(2) );
+ if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
+ // fill in the shadow information
- Vector3 point1 = li->transform.origin;
- Vector3 point2 = li->transform.origin+p_camera_inverse_transform.affine_inverse().basis.get_axis(1).normalized()*li->light_ptr->param[VS::LIGHT_PARAM_RANGE];
+ uint32_t key = shadow_atlas->shadow_owners[li->self];
- p.intersects_segment(ai.origin,point1,&point1);
- p.intersects_segment(ai.origin,point2,&point2);
- float r = point1.distance_to(point2);
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ ERR_CONTINUE(shadow>=shadow_atlas->quadrants[quadrant].shadows.size());
+
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size>>1;
+
+ uint32_t x=(quadrant&1)*quadrant_size;
+ uint32_t y=(quadrant>>1)*quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ uint32_t width=shadow_size;
+ uint32_t height=shadow_size;
+
+
+ if (li->light_ptr->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
+
+ height/=2;
+ } else {
+ width/=2;
+
+ }
+
+ Transform proj = (p_camera_inverse_transform * li->transform).inverse();
+
+ store_transform(proj,li->light_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;
+
+ }
- float vp_w,vp_h;
- p_camera_projection.get_viewport_size(vp_w,vp_h);
- lpercent.push_back(r*2/((vp_h+vp_w)*0.5));
-#endif
#if 0
if (li->light_ptr->shadow_enabled) {
@@ -1596,10 +1767,54 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
li->light_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]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- li->light_ubo_data.light_params[2]=0;
+ 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;
+ if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
+ // fill in the shadow information
+
+ uint32_t key = shadow_atlas->shadow_owners[li->self];
+
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ ERR_CONTINUE(shadow>=shadow_atlas->quadrants[quadrant].shadows.size());
+
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size>>1;
+
+ uint32_t x=(quadrant&1)*quadrant_size;
+ uint32_t y=(quadrant>>1)*quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ uint32_t width=shadow_size;
+ uint32_t height=shadow_size;
+
+ 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;
+
+ Transform modelview = (p_camera_inverse_transform * li->transform).inverse();
+
+ CameraMatrix bias;
+ bias.set_light_bias();
+ CameraMatrix rectm;
+ rectm.set_light_atlas_rect(rect);
+
+ CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview;
+
+ store_camera(shadow_mtx,li->light_ubo_data.shadow_matrix1);
+
+
+ }
#if 0
if (li->light_ptr->shadow_enabled) {
CameraMatrix bias;
@@ -1679,24 +1894,39 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
}
-void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment){
+void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
- //first of all, make a new render pass
- render_pass++;
+ //copy to front buffer
+ glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
- //fill up ubo
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthFunc(GL_LEQUAL);
+ glColorMask(1,1,1,1);
- Environment *env = environment_owner.getornull(p_environment);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,p_texture);
- _setup_environment(env,p_cam_projection,p_cam_transform);
+ glViewport(0,0,storage->frame.current_rt->width*0.5,storage->frame.current_rt->height*0.5);
- _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true);
+ storage->shaders.copy.bind();
- render_list.clear();
+ _copy_screen();
- current_material_index=0;
+ //turn off everything used
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,false);
- bool use_mrt=false;
+
+}
+
+void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow){
+
+ current_geometry_index=0;
+ current_material_index=0;
//fill list
@@ -1716,7 +1946,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
int mat_idx = inst->materials[i].is_valid() ? i : -1;
RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
- _add_geometry(s,inst,NULL,mat_idx);
+ _add_geometry(s,inst,NULL,mat_idx,p_shadow);
}
//mesh->last_pass=frame;
@@ -1731,7 +1961,39 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
}
}
+}
+
+
+void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID p_environment,RID p_shadow_atlas){
+
+ //first of all, make a new render pass
+ render_pass++;
+
+ //fill up ubo
+
+ Environment *env = environment_owner.getornull(p_environment);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+
+ if (shadow_atlas && shadow_atlas->size) {
+ glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-3);
+ glBindTexture(GL_TEXTURE_2D,shadow_atlas->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
+ state.ubo_data.shadow_atlas_pixel_size[0]=1.0/shadow_atlas->size;
+ state.ubo_data.shadow_atlas_pixel_size[1]=1.0/shadow_atlas->size;
+ }
+
+ _setup_environment(env,p_cam_projection,p_cam_transform);
+
+ _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas);
+
+ render_list.clear();
+
+ bool use_mrt=false;
+
+
+ _fill_render_list(p_cull_result,p_cull_count,false);
//
@@ -1742,6 +2004,8 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
RasterizerStorageGLES3::Texture* env_radiance_tex=NULL;
+ glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
+
if (use_mrt) {
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo);
@@ -1811,7 +2075,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
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);
+ _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
@@ -1843,11 +2107,34 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
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);
+ _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);
_copy_to_front_buffer(env);
+/* if (shadow_atlas) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,shadow_atlas->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
+
+ }
+*/
+ if (directional_shadow.fbo) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,directional_shadow.depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
+
+ }
+
+
#if 0
if (use_fb) {
@@ -1994,6 +2281,294 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
#endif
}
+void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count) {
+
+ render_pass++;
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light);
+ ERR_FAIL_COND(!light_instance);
+ RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light);
+ ERR_FAIL_COND(!light);
+
+ uint32_t x,y,width,height,vp_height;
+
+
+ float dp_direction=0.0;
+ float zfar=0;
+ bool flip_facing=false;
+ int custom_vp_size=0;
+ GLuint fbo;
+ int current_cubemap=-1;
+ float bias=0;
+ float normal_bias=0;
+
+ CameraMatrix light_projection;
+ Transform light_transform;
+
+
+ if (light->type==VS::LIGHT_DIRECTIONAL) {
+ //set pssm stuff
+ if (light_instance->last_scene_shadow_pass!=scene_pass) {
+ //assign rect if unassigned
+ light_instance->light_directional_index = directional_shadow.current_light;
+ light_instance->last_scene_shadow_pass=scene_pass;
+ directional_shadow.current_light++;
+
+ if (directional_shadow.light_count==1) {
+ light_instance->directional_rect=Rect2(0,0,directional_shadow.size,directional_shadow.size);
+ } else if (directional_shadow.light_count==2) {
+ light_instance->directional_rect=Rect2(0,0,directional_shadow.size,directional_shadow.size/2);
+ if (light_instance->light_directional_index==1) {
+ light_instance->directional_rect.pos.x+=light_instance->directional_rect.size.x;
+ }
+ } else { //3 and 4
+ light_instance->directional_rect=Rect2(0,0,directional_shadow.size/2,directional_shadow.size/2);
+ if (light_instance->light_directional_index&1) {
+ light_instance->directional_rect.pos.x+=light_instance->directional_rect.size.x;
+ }
+ if (light_instance->light_directional_index/2) {
+ light_instance->directional_rect.pos.y+=light_instance->directional_rect.size.y;
+ }
+ }
+ }
+
+ light_projection=light_instance->shadow_transform[p_pass].camera;
+ light_transform=light_instance->shadow_transform[p_pass].transform;
+
+ x=light_instance->directional_rect.pos.x;
+ y=light_instance->directional_rect.pos.y;
+ width=light_instance->directional_rect.size.x;
+ height=light_instance->directional_rect.size.y;
+
+
+
+ if (light->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+
+
+ width/=2;
+ height/=2;
+
+ if (p_pass==0) {
+
+ } else if (p_pass==1) {
+ x+=width;
+ } else if (p_pass==2) {
+ y+=height;
+ } else if (p_pass==3) {
+ x+=width;
+ y+=height;
+
+ }
+
+
+
+ } else if (light->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+
+ height/=2;
+
+ if (p_pass==0) {
+
+ } else {
+ y+=height;
+ }
+
+ }
+
+ zfar=light->param[VS::LIGHT_PARAM_RANGE];
+ bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
+ normal_bias=light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS];
+ fbo=directional_shadow.fbo;
+ vp_height=directional_shadow.size;
+
+ } else {
+ //set from shadow atlas
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+ ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
+
+ fbo=shadow_atlas->fbo;
+ vp_height=shadow_atlas->size;
+
+
+ uint32_t key = shadow_atlas->shadow_owners[p_light];
+
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ ERR_FAIL_INDEX(shadow,shadow_atlas->quadrants[quadrant].shadows.size());
+
+ uint32_t quadrant_size = shadow_atlas->size>>1;
+
+ x=(quadrant&1)*quadrant_size;
+ y=(quadrant>>1)*quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ width=shadow_size;
+ height=shadow_size;
+
+ if (light->type==VS::LIGHT_OMNI) {
+
+
+ if (light->omni_shadow_mode==VS::LIGHT_OMNI_SHADOW_CUBE) {
+
+ int cubemap_index=shadow_cubemaps.size()-1;
+
+ for(int i=shadow_cubemaps.size()-1;i>=0;i--) {
+ //find appropriate cubemap to render to
+ if (shadow_cubemaps[i].size>shadow_size*2)
+ break;
+
+ cubemap_index=i;
+ }
+
+ fbo=shadow_cubemaps[cubemap_index].fbo_id[p_pass];
+ light_projection=light_instance->shadow_transform[0].camera;
+ light_transform=light_instance->shadow_transform[0].transform;
+ custom_vp_size=shadow_cubemaps[cubemap_index].size;
+ zfar=light->param[VS::LIGHT_PARAM_RANGE];
+
+ current_cubemap=cubemap_index;
+
+
+ } else {
+
+ light_projection=light_instance->shadow_transform[0].camera;
+ light_transform=light_instance->shadow_transform[0].transform;
+
+ if (light->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
+
+ height/=2;
+ y+=p_pass*height;
+ } else {
+ width/=2;
+ x+=p_pass*width;
+
+ }
+
+ dp_direction = p_pass==0?1.0:-1.0;
+ flip_facing = (p_pass == 1);
+ zfar=light->param[VS::LIGHT_PARAM_RANGE];
+ bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
+
+ state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,true);
+ }
+
+ } else if (light->type==VS::LIGHT_SPOT) {
+
+ light_projection=light_instance->shadow_transform[0].camera;
+ light_transform=light_instance->shadow_transform[0].transform;
+
+ dp_direction = 1.0;
+ flip_facing = false;
+ zfar=light->param[VS::LIGHT_PARAM_RANGE];
+ bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
+ normal_bias=light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS];
+ }
+
+ }
+
+ //todo hacer que se redibuje cuando corresponde
+
+
+ render_list.clear();
+ _fill_render_list(p_cull_result,p_cull_count,true);
+
+ render_list.sort_by_depth(false); //shadow is front to back for performance
+
+ glDepthMask(true);
+ glColorMask(0,0,0,0);
+ glDisable(GL_BLEND);
+ glDisable(GL_DITHER);
+ glEnable(GL_DEPTH_TEST);
+
+ glBindFramebuffer(GL_FRAMEBUFFER,fbo);
+
+ if (custom_vp_size) {
+ glViewport(0,0,custom_vp_size,custom_vp_size);
+ glScissor(0,0,custom_vp_size,custom_vp_size);
+
+ } else {
+ glViewport(x,y,width,height);
+ glScissor(x,y,width,height);
+ }
+
+ //glViewport(x,vp_height-(height+y),width,height);
+ //glScissor(x,vp_height-(height+y),width,height);
+ glEnable(GL_SCISSOR_TEST);
+ glClearDepth(1.0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ state.ubo_data.shadow_z_offset=bias;
+ state.ubo_data.shadow_slope_scale=normal_bias;
+ state.ubo_data.shadow_dual_paraboloid_render_side=dp_direction;
+ state.ubo_data.shadow_dual_paraboloid_render_zfar=zfar;
+
+ _setup_environment(NULL,light_projection,light_transform);
+
+ 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);
+
+ state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false);
+
+
+ if (light->type==VS::LIGHT_OMNI && light->omni_shadow_mode==VS::LIGHT_OMNI_SHADOW_CUBE && p_pass==5) {
+ //convert the chosen cubemap to dual paraboloid!
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+
+ glBindFramebuffer(GL_FRAMEBUFFER,shadow_atlas->fbo);
+ state.cube_to_dp_shader.bind();
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP,shadow_cubemaps[current_cubemap].cubemap);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glDisable(GL_CULL_FACE);
+
+ for(int i=0;i<2;i++) {
+
+ state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FLIP,i==1);
+ state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_NEAR,light_projection.get_z_near());
+ state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FAR,light_projection.get_z_far());
+ state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::BIAS,light->param[VS::LIGHT_PARAM_SHADOW_BIAS]);
+
+ uint32_t local_width=width,local_height=height;
+ uint32_t local_x=x,local_y=y;
+ if (light->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
+
+ local_height/=2;
+ local_y+=i*local_height;
+ } else {
+ local_width/=2;
+ local_x+=i*local_width;
+ }
+
+ glViewport(local_x,local_y,local_width,local_height);
+ glScissor(local_x,local_y,local_width,local_height);
+ glEnable(GL_SCISSOR_TEST);
+ glClearDepth(1.0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glDisable(GL_SCISSOR_TEST);
+ //glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+
+ _copy_screen();
+
+ }
+
+ }
+
+ glColorMask(1,1,1,1);
+
+
+}
+
void RasterizerSceneGLES3::set_scene_pass(uint64_t p_pass) {
scene_pass=p_pass;
}
@@ -2169,6 +2744,12 @@ void RasterizerSceneGLES3::initialize() {
default_material = storage->material_create();
storage->material_set_shader(default_material,default_shader);
+ default_shader_twosided = storage->shader_create(VS::SHADER_SPATIAL);
+ default_material_twosided = storage->material_create();
+ storage->shader_set_code(default_shader_twosided,"render_mode cull_disabled;\n");
+ storage->material_set_shader(default_material_twosided,default_shader_twosided);
+
+
glGenBuffers(1, &state.scene_ubo);
glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW);
@@ -2208,9 +2789,77 @@ void RasterizerSceneGLES3::initialize() {
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
}
render_list.init();
+ state.cube_to_dp_shader.init();
_generate_brdf();
shadow_atlas_realloc_tolerance_msec=500;
+
+
+
+
+
+ int max_shadow_cubemap_sampler_size=512;
+
+ int cube_size = max_shadow_cubemap_sampler_size;
+
+ glActiveTexture(GL_TEXTURE0);
+
+ while(cube_size>=32) {
+
+ ShadowCubeMap cube;
+ cube.size=cube_size;
+
+ glGenTextures(1,&cube.cubemap);
+ glBindTexture(GL_TEXTURE_CUBE_MAP,cube.cubemap);
+ //gen cubemap first
+ for(int i=0;i<6;i++) {
+
+ glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ }
+
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ // Remove artifact on the edges of the shadowmap
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ //gen renderbuffers second, because it needs a complete cubemap
+ for(int i=0;i<6;i++) {
+
+ glGenFramebuffers(1, &cube.fbo_id[i]);
+ glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,_cube_side_enum[i], cube.cubemap, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE);
+ }
+
+ shadow_cubemaps.push_back(cube);
+
+ cube_size>>=1;
+ }
+
+ {
+ //directional light shadow
+ directional_shadow.light_count=0;
+ directional_shadow.size=nearest_power_of_2(GLOBAL_DEF("renderer/directional_shadow_size",2048));
+ glGenFramebuffers(1,&directional_shadow.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER,directional_shadow.fbo);
+ glGenTextures(1,&directional_shadow.depth);
+ glBindTexture(GL_TEXTURE_2D,directional_shadow.depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ 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_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D, directional_shadow.depth, 0);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status!=GL_FRAMEBUFFER_COMPLETE) {
+ ERR_PRINT("Directional shadow framebuffer status invalid");
+ }
+ }
}
void RasterizerSceneGLES3::finalize(){
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 9df6315e45..d7beebbcf6 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -3,6 +3,7 @@
#include "rasterizer_storage_gles3.h"
#include "drivers/gles3/shaders/scene.glsl.h"
+#include "drivers/gles3/shaders/cube_to_dp.glsl.h"
class RasterizerSceneGLES3 : public RasterizerScene {
public:
@@ -16,10 +17,13 @@ public:
uint32_t current_geometry_index;
RID default_material;
+ RID default_material_twosided;
RID default_shader;
+ RID default_shader_twosided;
RasterizerStorageGLES3 *storage;
+
struct State {
@@ -29,6 +33,7 @@ public:
int current_depth_draw;
SceneShaderGLES3 scene_shader;
+ CubeToDpShaderGLES3 cube_to_dp_shader;
struct SceneDataUBO {
@@ -41,6 +46,12 @@ public:
float bg_color[4];
float ambient_energy;
float bg_energy;
+ float shadow_z_offset;
+ float shadow_slope_scale;
+ float shadow_dual_paraboloid_render_zfar;
+ float shadow_dual_paraboloid_render_side;
+ float shadow_atlas_pixel_size[2];
+ float shadow_directional_pixel_size[2];
} ubo_data;
@@ -62,7 +73,7 @@ public:
GLuint skybox_verts;
GLuint skybox_array;
-
+ bool cull_front;
} state;
@@ -71,7 +82,6 @@ public:
struct ShadowAtlas : public RID_Data {
enum {
- SHADOW_INDEX_DIRTY_BIT=(1<<31),
QUADRANT_SHIFT=27,
SHADOW_INDEX_MASK=(1<<QUADRANT_SHIFT)-1,
SHADOW_INVALID=0xFFFFFFFF
@@ -111,13 +121,35 @@ public:
Map<RID,uint32_t> shadow_owners;
};
+ struct ShadowCubeMap {
+
+ GLuint fbo_id[6];
+ GLuint cubemap;
+ int size;
+ };
+
+ Vector<ShadowCubeMap> shadow_cubemaps;
+
RID_Owner<ShadowAtlas> shadow_atlas_owner;
RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas,int p_size);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision);
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
- uint32_t shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version);
+ bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version);
+
+
+ struct DirectionalShadow {
+ GLuint fbo;
+ GLuint depth;
+ int light_count;
+ int size;
+ int current_light;
+ } directional_shadow;
+
+ virtual int get_directional_light_shadow_size(RID p_light_intance);
+ virtual void set_directional_shadow_count(int p_count);
+
/* ENVIRONMENT API */
@@ -174,12 +206,12 @@ public:
struct LightInstance : public RID_Data {
- struct SplitInfo {
+ struct ShadowTransform {
CameraMatrix camera;
Transform transform;
- float near;
float far;
+ float split;
};
struct LightDataUBO {
@@ -188,6 +220,7 @@ public:
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];
@@ -197,13 +230,11 @@ public:
} light_ubo_data;
- SplitInfo split_info[4];
+ ShadowTransform shadow_transform[4];
+ RID self;
RID light;
RasterizerStorageGLES3::Light *light_ptr;
-
- CameraMatrix shadow_matrix[4];
-
Transform transform;
Vector3 light_vector;
@@ -214,12 +245,17 @@ public:
uint64_t shadow_pass;
uint64_t last_scene_pass;
+ uint64_t last_scene_shadow_pass;
uint64_t last_pass;
uint16_t light_index;
+ uint16_t light_directional_index;
+
+ uint32_t current_shadow_atlas_key;
Vector2 dp;
- CameraMatrix shadow_projection[4];
+ Rect2 directional_rect;
+
Set<RID> shadow_atlases; //shadow atlases where this light is registered
@@ -231,6 +267,7 @@ public:
virtual RID light_instance_create(RID p_light);
virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
+ virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass);
virtual void light_instance_mark_visible(RID p_light_instance);
/* RENDER LIST */
@@ -371,26 +408,31 @@ public:
RenderList render_list;
+ _FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull);
+
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass);
_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);
- 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);
+ 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);
- _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material);
+ _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow);
- void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale);
+ 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,CameraMatrix& p_cam_projection, const Transform& p_cam_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);
+ void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_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);
+ void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
- virtual void render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment);
+ void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow);
+ virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID p_environment,RID p_shadow_atlas);
+ virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);
virtual bool free(RID p_rid);
void _generate_brdf();
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 4b2c607297..b988781e14 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1290,12 +1290,13 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
shaders.actions_scene.render_mode_values["cull_front"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_FRONT);
shaders.actions_scene.render_mode_values["cull_back"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK);
- shaders.actions_scene.render_mode_values["cull_disable"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
+ shaders.actions_scene.render_mode_values["cull_disabled"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
shaders.actions_scene.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded;
shaders.actions_scene.render_mode_flags["ontop"]=&p_shader->spatial.ontop;
shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha;
+ shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex;
actions=&shaders.actions_scene;
actions->uniforms=&p_shader->uniforms;
@@ -1318,6 +1319,9 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
p_shader->texture_count=gen_code.texture_uniforms.size();
p_shader->texture_hints=gen_code.texture_hints;
+ p_shader->uses_vertex_time=gen_code.uses_vertex_time;
+ p_shader->uses_fragment_time=gen_code.uses_fragment_time;
+
//all materials using this shader will have to be invalidated, unfortunately
for (SelfList<Material>* E = p_shader->materials.first();E;E=E->next() ) {
@@ -1535,6 +1539,57 @@ void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_wid
}
+bool RasterizerStorageGLES3::material_is_animated(RID p_material) {
+
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,false);
+ if (material->dirty_list.in_list()) {
+ _update_material(material);
+ }
+
+ return material->is_animated_cache;
+
+}
+bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
+
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,false);
+ if (material->dirty_list.in_list()) {
+ _update_material(material);
+ }
+
+ return material->can_cast_shadow_cache;
+}
+
+void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
+
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+
+ Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.find(p_instance);
+ if (E) {
+ E->get()++;
+ } else {
+ material->instance_owners[p_instance]=1;
+ }
+}
+
+void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
+
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+
+ Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.find(p_instance);
+ ERR_FAIL_COND(!E);
+ E->get()--;
+
+ if (E->get()==0) {
+ material->instance_owners.erase(E);
+ }
+}
+
+
+
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data,bool p_linear_color) {
switch(type) {
case ShaderLanguage::TYPE_BOOL: {
@@ -2011,6 +2066,48 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
if (material->dirty_list.in_list())
_material_dirty_list.remove( &material->dirty_list );
+
+ if (material->shader && material->shader->dirty_list.in_list()) {
+ _update_shader(material->shader);
+ }
+ //update caches
+
+ {
+ bool can_cast_shadow = false;
+ bool is_animated = false;
+
+ if (material->shader && material->shader->mode==VS::SHADER_SPATIAL) {
+ if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode==Shader::Spatial::BLEND_MODE_MIX) {
+ can_cast_shadow=true;
+ }
+
+ if (material->shader->spatial.uses_discard && material->shader->uses_fragment_time) {
+ is_animated=true;
+ }
+
+ if (material->shader->spatial.uses_vertex && material->shader->uses_vertex_time) {
+ is_animated=true;
+ }
+
+ }
+
+ if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
+ material->can_cast_shadow_cache=can_cast_shadow;
+ material->is_animated_cache=is_animated;
+
+ for(Map<Instantiable*,int>::Element *E=material->instantiable_owners.front();E;E=E->next()) {
+ E->key()->instance_material_change_notify();
+ }
+
+ for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
+ E->key()->base_material_changed();
+ }
+
+ }
+
+ }
+
+
//clear ubo if it needs to be cleared
if (material->ubo_size) {
@@ -2102,6 +2199,36 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
}
+void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) {
+
+ Material * material = material_owner.getornull(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
+
+ if (I) {
+ I->get()++;
+ } else {
+ material->instantiable_owners[p_instantiable]=1;
+ }
+
+}
+
+void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) {
+
+ Material * material = material_owner.getornull(p_material);
+ ERR_FAIL_COND(!material);
+
+ Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
+ ERR_FAIL_COND(!I);
+
+ I->get()--;
+ if (I->get()==0) {
+ material->instantiable_owners.erase(I);
+ }
+}
+
+
void RasterizerStorageGLES3::update_dirty_materials() {
while( _material_dirty_list.first() ) {
@@ -2406,6 +2533,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
surface->active=true;
surface->array_len=p_vertex_count;
surface->index_array_len=p_index_count;
+ surface->array_byte_size=p_array.size();
+ surface->index_array_byte_size=p_index_array.size();
surface->primitive=p_primitive;
surface->mesh=mesh;
surface->format=p_format;
@@ -2556,8 +2685,22 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface
ERR_FAIL_COND(!mesh);
ERR_FAIL_INDEX(p_surface,mesh->surfaces.size());
+ if (mesh->surfaces[p_surface]->material==p_material)
+ return;
+
+ if (mesh->surfaces[p_surface]->material.is_valid()) {
+ _material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh);
+ }
+
mesh->surfaces[p_surface]->material=p_material;
+ if (mesh->surfaces[p_surface]->material.is_valid()) {
+ _material_add_instantiable(mesh->surfaces[p_surface]->material,mesh);
+ }
+
+ mesh->instance_material_change_notify();
+
+
}
RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{
@@ -2595,17 +2738,17 @@ DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int
Surface *surface = mesh->surfaces[p_surface];
glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id);
- void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_len,GL_MAP_READ_BIT);
+ void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_byte_size,GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data,DVector<uint8_t>());
DVector<uint8_t> ret;
- ret.resize(surface->array_len);
+ ret.resize(surface->array_byte_size);
{
DVector<uint8_t>::Write w = ret.write();
- copymem(w.ptr(),data,surface->array_len);
+ copymem(w.ptr(),data,surface->array_byte_size);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
@@ -2622,18 +2765,18 @@ DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh
ERR_FAIL_COND_V(surface->index_array_len==0,DVector<uint8_t>());
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->vertex_id);
- void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_len,GL_MAP_READ_BIT);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id);
+ void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_byte_size,GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data,DVector<uint8_t>());
DVector<uint8_t> ret;
- ret.resize(surface->index_array_len);
+ ret.resize(surface->index_array_byte_size);
{
DVector<uint8_t>::Write w = ret.write();
- copymem(w.ptr(),data,surface->index_array_len);
+ copymem(w.ptr(),data,surface->index_array_byte_size);
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
@@ -2662,6 +2805,59 @@ VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_
return mesh->surfaces[p_surface]->primitive;
}
+AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
+
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,AABB());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),AABB());
+
+ return mesh->surfaces[p_surface]->aabb;
+
+
+}
+Vector<DVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const{
+
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,Vector<DVector<uint8_t> >());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector<DVector<uint8_t> >());
+
+ Vector<DVector<uint8_t> > bsarr;
+
+ for(int i=0;i<mesh->surfaces[p_surface]->morph_targets.size();i++) {
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mesh->surfaces[p_surface]->morph_targets[i].vertex_id);
+ void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,mesh->surfaces[p_surface]->array_byte_size,GL_MAP_READ_BIT);
+
+ ERR_FAIL_COND_V(!data,Vector<DVector<uint8_t> >());
+
+ DVector<uint8_t> ret;
+ ret.resize(mesh->surfaces[p_surface]->array_byte_size);
+
+ {
+
+ DVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(),data,mesh->surfaces[p_surface]->array_byte_size);
+ }
+
+ bsarr.push_back(ret);
+
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+ }
+
+ return bsarr;
+
+}
+Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const{
+
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,Vector<AABB >());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector<AABB >());
+
+ return mesh->surfaces[p_surface]->skeleton_bone_aabb;
+
+}
+
+
void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -2670,6 +2866,10 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
Surface *surface = mesh->surfaces[p_surface];
+ if (surface->material.is_valid()) {
+ _material_remove_instantiable(surface->material,mesh);
+ }
+
glDeleteBuffers(1,&surface->vertex_id);
if (surface->index_id) {
glDeleteBuffers(1,&surface->index_id);
@@ -2683,6 +2883,8 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
glDeleteVertexArrays(1,&surface->morph_targets[i].array_id);
}
+ mesh->instance_material_change_notify();
+
memdelete(surface);
mesh->surfaces.remove(p_surface);
@@ -2971,7 +3173,6 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
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;
- light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET]=1.0;
light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]=0.1;
light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]=0.1;
@@ -2981,6 +3182,10 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
light->negative=false;
light->cull_mask=0xFFFFFFFF;
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->version=0;
return light_owner.make_rid(light);
}
@@ -2998,9 +3203,23 @@ void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param,
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param,VS::LIGHT_PARAM_MAX);
- if (p_param==VS::LIGHT_PARAM_RANGE || p_param==VS::LIGHT_PARAM_SPOT_ANGLE) {
- light->instance_change_notify();
+ switch(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:
+ case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+ case VS::LIGHT_PARAM_SHADOW_BIAS:
+ case VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE: {
+
+ light->version++;
+ light->instance_change_notify();
+ } break;
}
+
light->param[p_param]=p_value;
}
void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){
@@ -3009,6 +3228,10 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){
ERR_FAIL_COND(!light);
light->shadow=p_enabled;
+ light->version++;
+ light->instance_change_notify();
+
+
}
void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){
@@ -3021,9 +3244,8 @@ void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_text
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
-
-
}
+
void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){
Light * light = light_owner.getornull(p_light);
@@ -3037,6 +3259,10 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){
ERR_FAIL_COND(!light);
light->cull_mask=p_mask;
+
+ light->version++;
+ light->instance_change_notify();
+
}
void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){
@@ -3045,22 +3271,92 @@ void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){
}
+void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) {
+
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->omni_shadow_mode=p_mode;
+
+ light->version++;
+ light->instance_change_notify();
+
+
+}
+
+VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) {
+
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI_SHADOW_CUBE);
+
+ return light->omni_shadow_mode;
+}
+
+
+void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail) {
+
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->omni_shadow_detail=p_detail;
+ light->version++;
+ light->instance_change_notify();
+}
+
void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
+ light->directional_shadow_mode=p_mode;
+ light->version++;
+ light->instance_change_notify();
+
+}
+
+VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) {
+
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+ return light->directional_shadow_mode;
}
+
VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
- return VS::LIGHT_DIRECTIONAL;
+ return light->type;
}
+float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param) {
+
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
+
+ return light->param[p_param];
+}
+
+bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
+
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
+
+ return light->shadow;
+}
+
+uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const {
+
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,0);
+
+ return light->version;
+}
+
+
AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
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 b12c2d93b6..f8b34d6a16 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -99,6 +99,38 @@ public:
+ struct Instantiable : public RID_Data {
+
+ SelfList<RasterizerScene::InstanceBase>::List instance_list;
+
+ _FORCE_INLINE_ void instance_change_notify() {
+
+ SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
+ while(instances) {
+
+ instances->self()->base_changed();
+ instances=instances->next();
+ }
+ }
+
+ _FORCE_INLINE_ void instance_material_change_notify() {
+
+ SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
+ while(instances) {
+
+ instances->self()->base_material_changed();
+ instances=instances->next();
+ }
+ }
+
+ Instantiable() { }
+ virtual ~Instantiable() {
+
+ while(instance_list.first()) {
+ instance_list.first()->self()->base_removed();
+ }
+ }
+ };
@@ -282,9 +314,14 @@ public:
bool uses_alpha;
bool unshaded;
bool ontop;
+ bool uses_vertex;
+ bool uses_discard;
} spatial;
+ bool uses_vertex_time;
+ bool uses_fragment_time;
+
Shader() : dirty_list(this) {
shader=NULL;
@@ -315,6 +352,8 @@ public:
void update_dirty_shaders();
+
+
/* COMMON MATERIAL API */
struct Material : public RID_Data {
@@ -331,7 +370,15 @@ public:
uint32_t index;
uint64_t last_pass;
+ Map<Instantiable*,int> instantiable_owners;
+ Map<RasterizerScene::InstanceBase*,int> instance_owners;
+
+ bool can_cast_shadow_cache;
+ bool is_animated_cache;
+
Material() : list(this), dirty_list(this) {
+ can_cast_shadow_cache=false;
+ is_animated_cache=false;
shader=NULL;
line_width=1.0;
ubo_id=0;
@@ -343,6 +390,8 @@ public:
mutable SelfList<Material>::List _material_dirty_list;
void _material_make_dirty(Material *p_material) const;
+ void _material_add_instantiable(RID p_material,Instantiable *p_instantiable);
+ void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable);
mutable RID_Owner<Material> material_owner;
@@ -357,34 +406,18 @@ public:
virtual void material_set_line_width(RID p_material, float p_width);
+ virtual bool material_is_animated(RID p_material);
+ virtual bool material_casts_shadows(RID p_material);
+
+ virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
+ virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
+
void _update_material(Material* material);
void update_dirty_materials();
/* MESH API */
- struct Instantiable : public RID_Data {
-
- SelfList<RasterizerScene::InstanceBase>::List instance_list;
-
- _FORCE_INLINE_ void instance_change_notify() {
-
- SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
- while(instances) {
-
- instances->self()->base_changed();
- instances=instances->next();
- }
- }
-
- Instantiable() { }
- virtual ~Instantiable() {
-
- while(instance_list.first()) {
- instance_list.first()->self()->base_removed();
- }
- }
- };
struct Geometry : Instantiable {
@@ -455,7 +488,8 @@ public:
int index_array_len;
int max_bone;
- int array_bytes;
+ int array_byte_size;
+ int index_array_byte_size;
VS::PrimitiveType primitive;
@@ -464,7 +498,8 @@ public:
Surface() {
- array_bytes=0;
+ array_byte_size=0;
+ index_array_byte_size=0;
mesh=NULL;
format=0;
array_id=0;
@@ -526,6 +561,10 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
+ virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const;
+ virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const;
+ virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const;
+
virtual void mesh_remove_surface(RID p_mesh, int p_surface);
virtual int mesh_get_surface_count(RID p_mesh) const;
@@ -598,7 +637,10 @@ public:
bool shadow;
bool negative;
uint32_t cull_mask;
+ VS::LightOmniShadowMode omni_shadow_mode;
+ VS::LightOmniShadowDetail omni_shadow_detail;
VS::LightDirectionalShadowMode directional_shadow_mode;
+ uint64_t version;
};
mutable RID_Owner<Light> light_owner;
@@ -614,11 +656,22 @@ public:
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 VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
+ virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
+
+ virtual bool light_has_shadow(RID p_light) const;
virtual VS::LightType light_get_type(RID p_light) const;
+ virtual float light_get_param(RID p_light,VS::LightParam p_param);
+
virtual AABB light_get_aabb(RID p_light) const;
+ virtual uint64_t light_get_version(RID p_light) const;
+
/* PROBE API */
virtual RID reflection_probe_create();
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 0dff53bfb9..dce52ecd93 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -330,6 +330,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
SL::FunctionNode *fnode=pnode->functions[i].function;
+ current_func_name=fnode->name;
if (fnode->name=="vertex") {
@@ -401,6 +402,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
else
code=_mkid(vnode->name);
+ if (vnode->name==time_name) {
+ if (current_func_name==vertex_name) {
+ r_gen_code.uses_vertex_time=true;
+ }
+ if (current_func_name==fragment_name) {
+ r_gen_code.uses_fragment_time=true;
+ }
+ }
} break;
case SL::Node::TYPE_CONSTANT: {
@@ -536,6 +545,8 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
r_gen_code.fragment=String();
r_gen_code.fragment_global=String();
r_gen_code.light=String();
+ r_gen_code.uses_fragment_time=false;
+ r_gen_code.uses_vertex_time=false;
@@ -645,7 +656,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
-
+ vertex_name="vertex";
+ fragment_name="fragment";
+ time_name="TIME";
diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h
index dcea82d773..3549526808 100644
--- a/drivers/gles3/shader_compiler_gles3.h
+++ b/drivers/gles3/shader_compiler_gles3.h
@@ -32,6 +32,9 @@ public:
String fragment;
String light;
+ bool uses_fragment_time;
+ bool uses_vertex_time;
+
};
private:
@@ -49,6 +52,10 @@ private:
String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions);
+ StringName current_func_name;
+ StringName vertex_name;
+ StringName fragment_name;
+ StringName time_name;
Set<StringName> used_name_defines;
Set<StringName> used_rmode_defines;
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index afffe10316..44d325b091 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -6,4 +6,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
+ env.GLES3_GLSL('cube_to_dp.glsl');
diff --git a/drivers/gles3/shaders/cube_to_dp.glsl b/drivers/gles3/shaders/cube_to_dp.glsl
new file mode 100644
index 0000000000..5ffc78c0b9
--- /dev/null
+++ b/drivers/gles3/shaders/cube_to_dp.glsl
@@ -0,0 +1,79 @@
+[vertex]
+
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+out vec2 uv_interp;
+
+void main() {
+
+ uv_interp = uv_in;
+ gl_Position = vertex_attrib;
+}
+
+[fragment]
+
+
+uniform highp samplerCube source_cube; //texunit:0
+in vec2 uv_interp;
+
+uniform bool z_flip;
+uniform highp float z_far;
+uniform highp float z_near;
+uniform highp float bias;
+
+void main() {
+
+ highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 );
+/*
+ if(z_flip) {
+ normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
+ } else {
+ normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y));
+ }
+*/
+
+ //normal.z = sqrt(1.0-dot(normal.xy,normal.xy));
+ //normal.xy*=1.0+normal.z;
+
+ normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+/*
+ normal.z=0.5;
+ normal=normalize(normal);
+*/
+ if (!z_flip) {
+ normal.z=-normal.z;
+ }
+
+ //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
+ float depth = texture(source_cube,normal).r;
+
+ // absolute values for direction cosines, bigger value equals closer to basis axis
+ vec3 unorm = abs(normal);
+
+ if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3( 1.0, 0.0, 0.0 ) : vec3( -1.0, 0.0, 0.0 ) ;
+ } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3( 0.0, 1.0, 0.0 ) : vec3( 0.0, -1.0, 0.0 ) ;
+ } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 0.0, 0.0, -1.0 ) ;
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3( 1.0, 0.0, 0.0 );
+ }
+
+ float depth_fix = 1.0 / dot(normal,unorm);
+
+
+ depth = 2.0 * depth - 1.0;
+ float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near));
+ gl_FragDepth = (linear_depth*depth_fix+bias) / z_far;
+}
+
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 60ac015a17..de1591e8ff 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1,7 +1,6 @@
[vertex]
-#define ENABLE_UV_INTERP
/*
from VisualServer:
@@ -56,6 +55,15 @@ layout(std140) uniform SceneData { //ubo:0
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
+
+ float shadow_z_offset;
+ float shadow_z_slope_scale;
+ float shadow_dual_paraboloid_render_zfar;
+ float shadow_dual_paraboloid_render_side;
+
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
};
uniform highp mat4 world_transform;
@@ -68,6 +76,7 @@ layout(std140) uniform LightData { //ubo:3
mediump vec4 light_direction_attenuation;
mediump vec4 light_color_energy;
mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
+ mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@@ -75,19 +84,6 @@ layout(std140) uniform LightData { //ubo:3
highp mat4 shadow_matrix4;
};
-#ifdef USE_FORWARD_1_SHADOW_MAP
-out mediump vec4 forward_shadow_pos1;
-#endif
-
-#ifdef USE_FORWARD_2_SHADOW_MAP
-out mediump vec4 forward_shadow_pos2;
-#endif
-
-#ifdef USE_FORWARD_4_SHADOW_MAP
-out mediump vec4 forward_shadow_pos3;
-out mediump vec4 forward_shadow_pos4;
-#endif
-
#endif
/* Varyings */
@@ -120,13 +116,6 @@ varying vec4 position_interp;
#endif
-#ifdef USE_SHADOW_PASS
-
-uniform highp float shadow_z_offset;
-uniform highp float shadow_z_slope_scale;
-
-#endif
-
VERTEX_SHADER_GLOBALS
@@ -141,6 +130,11 @@ MATERIAL_UNIFORMS
#endif
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+out highp float dp_clip;
+
+#endif
void main() {
@@ -206,24 +200,49 @@ VERTEX_SHADER_CODE
}
+ vertex_interp = vertex.xyz;
+ normal_interp = normal;
+
+#if defined(ENABLE_TANGENT_INTERP)
+ tangent_interp = tangent;
+ binormal_interp = binormal;
+#endif
+
+#ifdef RENDER_SHADOW
+
+
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+ vertex_interp.z*= shadow_dual_paraboloid_render_side;
+ normal_interp.z*= shadow_dual_paraboloid_render_side;
-#ifdef USE_SHADOW_PASS
+ dp_clip=vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
+
+ //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
+
+ highp vec3 vtx = vertex_interp+normalize(vertex_interp)*shadow_z_offset;
+ highp float distance = length(vtx);
+ vtx = normalize(vtx);
+ vtx.xy/=1.0-vtx.z;
+ vtx.z=(distance/shadow_dual_paraboloid_render_zfar);
+ vtx.z=vtx.z * 2.0 - 1.0;
+
+ vertex.xyz=vtx;
+ vertex.w=1.0;
+
+
+#else
float z_ofs = shadow_z_offset;
z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale;
vertex_interp.z-=z_ofs;
-#endif
+#endif //RENDER_SHADOW_DUAL_PARABOLOID
- vertex_interp = vertex.xyz;
- normal_interp = normal;
+#endif //RENDER_SHADOW
-#if defined(ENABLE_TANGENT_INTERP)
- tangent_interp = tangent;
- binormal_interp = binormal;
-#endif
-#if !defined(SKIP_TRANSFORM_USED)
+#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_SHADOW_DUAL_PARABOLOID)
gl_Position = projection_matrix * vec4(vertex_interp,1.0);
#else
gl_Position = vertex;
@@ -239,11 +258,6 @@ VERTEX_SHADER_CODE
#define M_PI 3.14159265359
-
-#define ENABLE_UV_INTERP
-//hack to use uv if no uv present so it works with lightmap
-
-
/* Varyings */
#if defined(ENABLE_COLOR_INTERP)
@@ -318,6 +332,15 @@ layout(std140) uniform SceneData {
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
+
+ float shadow_z_offset;
+ float shadow_z_slope_scale;
+ float shadow_dual_paraboloid_render_zfar;
+ float shadow_dual_paraboloid_render_side;
+
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
};
@@ -328,7 +351,8 @@ layout(std140) uniform LightData {
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, specular, shadow darkening, shadow enabled
+ mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@@ -336,20 +360,12 @@ layout(std140) uniform LightData {
highp mat4 shadow_matrix4;
};
-#ifdef USE_FORWARD_1_SHADOW_MAP
-in mediump vec4 forward_shadow_pos1;
#endif
-#ifdef USE_FORWARD_2_SHADOW_MAP
-in mediump vec4 forward_shadow_pos2;
-#endif
-#ifdef USE_FORWARD_4_SHADOW_MAP
-in mediump vec4 forward_shadow_pos3;
-in mediump vec4 forward_shadow_pos4;
-#endif
+uniform highp sampler2DShadow directional_shadow; //texunit:-4
+uniform highp sampler2DShadow shadow_atlas; //texunit:-3
-#endif
#ifdef USE_MULTIPLE_RENDER_TARGETS
@@ -408,10 +424,27 @@ void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color,
}
+float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) {
+
+ return textureProj(shadow,vec4(pos,depth,1.0));
+}
+
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+in highp float dp_clip;
+
+#endif
+
void main() {
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+ if (dp_clip>0.0)
+ discard;
+#endif
+
//lay out everything, whathever is unused is optimized away anyway
- vec3 vertex = vertex_interp;
+ highp vec3 vertex = vertex_interp;
vec3 albedo = vec3(0.8,0.8,0.8);
vec3 specular = vec3(0.2,0.2,0.2);
float roughness = 1.0;
@@ -528,27 +561,216 @@ FRAGMENT_SHADER_CODE
#endif
-#ifdef USE_FORWARD_LIGHTING
-
#ifdef USE_FORWARD_DIRECTIONAL
- light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light);
+ float light_attenuation=1.0;
+
+#ifdef LIGHT_DIRECTIONAL_SHADOW
+
+ if (gl_FragCoord.w > shadow_split_offsets.w) {
+
+ vec3 pssm_coord;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+ float pssm_blend;
+ vec3 pssm_coord2;
+ bool use_blend=true;
+ vec3 light_pssm_split_inv = 1.0/shadow_split_offsets.xyz;
+ float w_inv = 1.0/gl_FragCoord.w;
#endif
+
+#ifdef LIGHT_USE_PSSM4
+
+
+ if (gl_FragCoord.w > shadow_split_offsets.y) {
+
+ if (gl_FragCoord.w > shadow_split_offsets.x) {
+
+ 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)
+
+ splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
+
+ } else {
+
+ 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));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv);
+#endif
+
+ }
+ } else {
+
+
+ if (gl_FragCoord.w > shadow_split_offsets.z) {
+
+ 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));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv);
+#endif
+
+ } else {
+ highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ diffuse_light*=vec3(1.0,0.4,1.0);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ use_blend=false;
+
+#endif
+
+ }
+ }
+
+#endif //LIGHT_USE_PSSM4
+
+#ifdef LIGHT_USE_PSSM2
+
+ if (gl_FragCoord.w > shadow_split_offsets.x) {
+
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+ splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
+
+ } else {
+ highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+#if defined(LIGHT_USE_PSSM_BLEND)
+ use_blend=false;
+
+#endif
+
+ }
+
+#endif //LIGHT_USE_PSSM2
+
+#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
+ { //regular orthogonal
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ }
+#endif
+
+
+ //one one sample
+ light_attenuation=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);
+ light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend);
+ }
+#endif
+
+ }
+
+#endif //LIGHT_DIRECTIONAL_SHADOW
+
+ light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
+
+
+#endif //USE_FORWARD_DIRECTIONAL
+
+
#ifdef USE_FORWARD_OMNI
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.z<clamp_rect.w) {
+ // clamp_rect.x+=clamp_rect.z;
+ //} else {
+ // clamp_rect.y+=clamp_rect.w;
+ //}
+
+ }
+
+ splane.xy/=splane.z;
+ splane.xy=splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * light_pos_inv_radius.w;
+
+ splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw;
+
+ light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect);
+ }
+
light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
-#endif
+
+#endif //USE_FORWARD_OMNI
#ifdef USE_FORWARD_SPOT
-#endif
+ 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 );
+ vec3 spot_dir = light_direction_attenuation.xyz;
+ float spot_cutoff=light_params.y;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff);
+ float rim = (1.0 - scos) / (1.0 - spot_cutoff);
+ light_attenuation *= 1.0 - pow( rim, light_params.x);
+
+ if (light_params.w>0.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);
+
+ }
+
+ light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
+
+#endif //USE_FORWARD_SPOT
-#endif
#if defined(USE_LIGHT_SHADER_CODE)
@@ -560,6 +782,11 @@ LIGHT_SHADER_CODE
}
#endif
+#ifdef RENDER_SHADOW
+//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
+#else
+
+
#ifdef USE_MULTIPLE_RENDER_TARGETS
//approximate ambient scale for SSAO, since we will lack full ambient
@@ -574,13 +801,17 @@ LIGHT_SHADER_CODE
#else
+
#ifdef SHADELESS
frag_color=vec4(albedo,alpha);
#else
frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
-#endif
+#endif //SHADELESS
+
+#endif //USE_MULTIPLE_RENDER_TARGETS
+
+#endif //RENDER_SHADOW
-#endif
}