Removed 3d light api.

This commit is contained in:
Relintai 2023-12-15 18:11:18 +01:00
parent ef3511a544
commit 219534c1ae
13 changed files with 3 additions and 2219 deletions

View File

@ -48,11 +48,6 @@ public:
int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
void set_directional_shadow_count(int p_count) {}
RID light_instance_create(RID p_light) { return RID(); }
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
void light_instance_mark_visible(RID p_light_instance) {}
void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, 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) {}
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
@ -393,43 +388,6 @@ public:
MMInterpolator *_multimesh_get_interpolator(RID p_multimesh) const { return nullptr; }
void multimesh_attach_canvas_item(RID p_multimesh, RID p_canvas_item, bool p_attach) {}
/* Light API */
RID light_create(RS::LightType p_type) { return RID(); }
RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
void light_set_color(RID p_light, const Color &p_color) {}
void light_set_param(RID p_light, RS::LightParam p_param, float p_value) {}
void light_set_shadow(RID p_light, bool p_enabled) {}
void light_set_shadow_color(RID p_light, const Color &p_color) {}
void light_set_projector(RID p_light, RID p_texture) {}
void light_set_negative(RID p_light, bool p_enable) {}
void light_set_cull_mask(RID p_light, uint32_t p_mask) {}
void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {}
void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {}
void light_omni_set_shadow_detail(RID p_light, RS::LightOmniShadowDetail p_detail) {}
void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {}
void light_directional_set_blend_splits(RID p_light, bool p_enable) {}
bool light_directional_get_blend_splits(RID p_light) const { return false; }
void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {}
RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
bool light_has_shadow(RID p_light) const { return false; }
RS::LightType light_get_type(RID p_light) const { return RS::LIGHT_OMNI; }
AABB light_get_aabb(RID p_light) const { return AABB(); }
float light_get_param(RID p_light, RS::LightParam p_param) { return 0.0; }
Color light_get_color(RID p_light) { return Color(); }
uint64_t light_get_version(RID p_light) const { return 0; }
/* RENDER TARGET */
RID render_target_create() { return RID(); }

View File

@ -166,13 +166,6 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
shadow_atlas->color = 0;
}
// erase shadow atlast references from lights
for (RBMap<RID, uint32_t>::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) {
LightInstance *li = light_instance_owner.getornull(E->key());
ERR_CONTINUE(!li);
li->shadow_atlases.erase(p_atlas);
}
shadow_atlas->shadow_owners.clear();
shadow_atlas->size = p_size;
@ -246,17 +239,6 @@ void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, in
return;
}
// erase all data from the quadrant
for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
ERR_CONTINUE(!li);
li->shadow_atlases.erase(p_atlas);
}
}
shadow_atlas->quadrants[p_quadrant].shadows.resize(0);
shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv);
shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
@ -309,29 +291,6 @@ bool RasterizerSceneGLES2::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas,
int found_used_idx = -1; // found an existing one, must steal it
uint64_t min_pass = 0; // pass of the existing one, try to use the least recently
for (int j = 0; j < sc; j++) {
if (!sarr[j].owner.is_valid()) {
found_free_idx = j;
break;
}
LightInstance *sli = light_instance_owner.getornull(sarr[j].owner);
ERR_CONTINUE(!sli);
if (sli->last_scene_pass != scene_pass) {
// was just allocated, don't kill it so soon, wait a bit...
if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
continue;
}
if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
found_used_idx = j;
min_pass = sli->last_scene_pass;
}
}
}
if (found_free_idx == -1 && found_used_idx == -1) {
continue; // nothing found
}
@ -353,9 +312,6 @@ bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_in
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!shadow_atlas, false);
LightInstance *li = light_instance_owner.getornull(p_light_intance);
ERR_FAIL_COND_V(!li, false);
if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
return false;
}
@ -425,8 +381,6 @@ bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_in
// it is take but invalid, so we can take it
shadow_atlas->shadow_owners.erase(sh->owner);
LightInstance *sli = light_instance_owner.get(sh->owner);
sli->shadow_atlases.erase(p_atlas);
}
// erase previous
@ -436,7 +390,6 @@ bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_in
sh->owner = p_light_intance;
sh->alloc_tick = tick;
sh->version = p_light_version;
li->shadow_atlases.insert(p_atlas);
// make a new key
key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
@ -467,14 +420,11 @@ bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_in
// it is take but invalid, so we can take it
shadow_atlas->shadow_owners.erase(sh->owner);
LightInstance *sli = light_instance_owner.get(sh->owner);
sli->shadow_atlases.erase(p_atlas);
}
sh->owner = p_light_intance;
sh->alloc_tick = tick;
sh->version = p_light_version;
li->shadow_atlases.insert(p_atlas);
// make a new key
uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
@ -506,80 +456,9 @@ int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance)
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 RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS:
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
shadow_size /= 2;
break;
}
return shadow_size;
}
//////////////////////////////////////////////////////
RID RasterizerSceneGLES2::light_instance_create(RID p_light) {
LightInstance *light_instance = memnew(LightInstance);
light_instance->last_scene_pass = 0;
light_instance->light = p_light;
light_instance->light_ptr = storage->light_owner.getornull(p_light);
light_instance->light_index = 0xFFFF;
// an ever increasing counter for each light added,
// used for sorting lights for a consistent render
light_instance->light_counter = _light_counter++;
if (!light_instance->light_ptr) {
memdelete(light_instance);
ERR_FAIL_V_MSG(RID(), "Condition ' !light_instance->light_ptr ' is true.");
}
light_instance->self = light_instance_owner.make_rid(light_instance);
return light_instance->self;
}
void RasterizerSceneGLES2::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->transform = p_transform;
}
void RasterizerSceneGLES2::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
if (light_instance->light_ptr->type != RS::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].farplane = p_far;
light_instance->shadow_transform[p_pass].split = p_split;
light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
}
void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->last_scene_pass = scene_pass;
}
////////////////////////////
////////////////////////////
////////////////////////////
void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) {
@ -720,9 +599,6 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
e->front_facing = true;
}
e->refprobe_0_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
e->refprobe_1_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
if (!p_depth_pass) {
e->depth_layer = e->instance->depth_layer;
e->priority = p_material->render_priority;
@ -736,57 +612,8 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
//add directional lights
if (p_material->shader->spatial.unshaded) {
e->light_mode = LIGHTMODE_UNSHADED;
} else {
bool copy = false;
e->light_mode = LIGHTMODE_UNSHADED;
for (int i = 0; i < render_directional_lights; i++) {
if (copy) {
RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
if (!e2) {
break;
}
*e2 = *e; //this includes accum ptr :)
e = e2;
}
//directional sort key
e->light_type1 = 0;
e->light_type2 = 1;
e->light_index = i;
copy = true;
}
//add omni / spots
for (int i = 0; i < e->instance->light_instances.size(); i++) {
LightInstance *li = light_instance_owner.getornull(e->instance->light_instances[i]);
if (!li || li->light_index >= render_light_instance_count || render_light_instances[li->light_index] != li) {
continue; // too many or light_index did not correspond to the light instances to be rendered
}
if (copy) {
RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
if (!e2) {
break;
}
*e2 = *e; //this includes accum ptr :)
e = e2;
}
//directional sort key
e->light_type1 = 1;
e->light_type2 = li->light_ptr->type == RenderingServer::LIGHT_OMNI ? 0 : 1;
e->light_index = li->light_index;
copy = true;
}
e->light_mode = LIGHTMODE_NORMAL;
}
}
// do not add anything here, as lights are duplicated elements..
@ -1206,312 +1033,6 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
}
}
void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas) {
//turn off all by default
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, false);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, false);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
if (!p_light) { //no light, return off
return;
}
//turn on lighting
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, true);
switch (p_light->light_ptr->type) {
case RS::LIGHT_DIRECTIONAL: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, true);
switch (p_light->light_ptr->directional_shadow_mode) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
//no need
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM3, true);
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
} break;
}
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits);
if (!state.render_no_shadows && p_light->light_ptr->shadow) {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
if (storage->config.use_rgba_3d_shadows) {
glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
} else {
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
}
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
} break;
case RS::LIGHT_OMNI: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true);
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
if (storage->config.use_rgba_3d_shadows) {
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
} else {
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
}
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
} break;
case RS::LIGHT_SPOT: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true);
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
if (storage->config.use_rgba_3d_shadows) {
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
} else {
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
}
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
} break;
}
}
void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shadow_atlas, const Transform &p_view_transform, bool accum_pass) {
RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
//common parameters
float energy = light_ptr->param[RS::LIGHT_PARAM_ENERGY];
float specular = light_ptr->param[RS::LIGHT_PARAM_SPECULAR];
float sign = (light_ptr->negative && !accum_pass) ? -1 : 1; //inverse color for base pass lights only
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular);
Color color = light_ptr->color * sign * energy * Math_PI;
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color);
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_COLOR, light_ptr->shadow_color);
//specific parameters
switch (light_ptr->type) {
case RS::LIGHT_DIRECTIONAL: {
//not using inverse for performance, view should be normalized anyway
Vector3 direction = p_view_transform.basis.xform_inv(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
Projection matrices[4];
if (!state.render_no_shadows && light_ptr->shadow && directional_shadow.depth) {
int shadow_count = 0;
Color split_offsets;
switch (light_ptr->directional_shadow_mode) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
shadow_count = 1;
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
shadow_count = 2;
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: {
shadow_count = 3;
} break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
shadow_count = 4;
} break;
}
for (int k = 0; k < shadow_count; k++) {
uint32_t x = light->directional_rect.position.x;
uint32_t y = light->directional_rect.position.y;
uint32_t width = light->directional_rect.size.x;
uint32_t height = light->directional_rect.size.y;
if (light_ptr->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS ||
light_ptr->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
width /= 2;
height /= 2;
if (k == 1) {
x += width;
} else if (k == 2) {
y += height;
} else if (k == 3) {
x += width;
y += height;
}
} else if (light_ptr->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
height /= 2;
if (k != 0) {
y += height;
}
}
split_offsets[k] = light->shadow_transform[k].split;
Transform modelview = (p_view_transform.inverse() * light->shadow_transform[k].transform).affine_inverse();
Projection bias;
bias.set_light_bias();
Projection 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);
Projection shadow_mtx = rectm * bias * light->shadow_transform[k].camera * modelview;
matrices[k] = shadow_mtx;
/*Color light_clamp;
light_clamp[0] = atlas_rect.position.x;
light_clamp[1] = atlas_rect.position.y;
light_clamp[2] = atlas_rect.size.x;
light_clamp[3] = atlas_rect.size.y;*/
}
// state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / directional_shadow.size, 1.0 / directional_shadow.size));
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPLIT_OFFSETS, split_offsets);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, matrices[0]);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX2, matrices[1]);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX3, matrices[2]);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX4, matrices[3]);
}
} break;
case RS::LIGHT_OMNI: {
Vector3 position = p_view_transform.xform_inv(light->transform.origin);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
float range = light_ptr->param[RS::LIGHT_PARAM_RANGE];
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
float attenuation = light_ptr->param[RS::LIGHT_PARAM_ATTENUATION];
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
if (!state.render_no_shadows && light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
uint32_t key = shadow_atlas->shadow_owners[light->self];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
ERR_BREAK(shadow >= (uint32_t)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 (light->light_ptr->omni_shadow_detail == RS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
height /= 2;
} else {
width /= 2;
}
Transform proj = (p_view_transform.inverse() * light->transform).inverse();
Color light_clamp;
light_clamp[0] = float(x) / atlas_size;
light_clamp[1] = float(y) / atlas_size;
light_clamp[2] = float(width) / atlas_size;
light_clamp[3] = float(height) / atlas_size;
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size));
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, proj);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
}
} break;
case RS::LIGHT_SPOT: {
Vector3 position = p_view_transform.xform_inv(light->transform.origin);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
float attenuation = light_ptr->param[RS::LIGHT_PARAM_ATTENUATION];
float range = light_ptr->param[RS::LIGHT_PARAM_RANGE];
float spot_attenuation = light_ptr->param[RS::LIGHT_PARAM_SPOT_ATTENUATION];
float angle = light_ptr->param[RS::LIGHT_PARAM_SPOT_ANGLE];
angle = Math::cos(Math::deg2rad(angle));
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_RANGE, spot_attenuation);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ANGLE, angle);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
if (!state.render_no_shadows && light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
uint32_t key = shadow_atlas->shadow_owners[light->self];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
ERR_BREAK(shadow >= (uint32_t)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);
Color light_clamp;
light_clamp[0] = rect.position.x;
light_clamp[1] = rect.position.y;
light_clamp[2] = rect.size.x;
light_clamp[3] = rect.size.y;
Transform modelview = (p_view_transform.inverse() * light->transform).inverse();
Projection bias;
bias.set_light_bias();
Projection rectm;
rectm.set_light_atlas_rect(rect);
Projection shadow_matrix = rectm * bias * light->shadow_transform[0].camera * modelview;
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size));
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, shadow_matrix);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
}
} break;
default: {
}
}
}
void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const Projection &p_projection, const int p_eye, RID p_shadow_atlas, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
@ -1535,7 +1056,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
Projection projection_inverse = p_projection.inverse();
bool prev_base_pass = false;
LightInstance *prev_light = nullptr;
bool prev_vertex_lit = false;
int prev_blend_mode = -2; //will always catch the first go
@ -1563,7 +1083,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
bool rebind = false;
bool accum_pass = *e->use_accum_ptr;
*e->use_accum_ptr = true; //set to accum for next time this is found
LightInstance *light = nullptr;
bool rebind_light = false;
if (!p_shadow && material->shader) {
@ -1591,28 +1110,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
prev_base_pass = base_pass;
}
if (!unshaded && e->light_index < RenderList::MAX_LIGHTS) {
light = render_light_instances[e->light_index];
if ((e->instance->layer_mask & light->light_ptr->cull_mask) == 0) {
light = nullptr; // Don't use this light, it is culled
}
}
if (light != prev_light) {
_setup_light_type(light, shadow_atlas);
rebind = true;
rebind_light = true;
}
int blend_mode = p_alpha_pass ? material->shader->spatial.blend_mode : -1; // -1 no blend, no mix
if (accum_pass) { //accum pass force pass
blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD;
if (light && light->light_ptr->negative) {
blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_SUB;
}
}
if (prev_blend_mode != blend_mode) {
if (prev_blend_mode == -1 && blend_mode != -1) {
//does blend
@ -1657,7 +1156,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
}
//condition to enable vertex lighting on this object
bool vertex_lit = (material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading) && ((!unshaded && light) || using_fog); //fog forces vertex lighting because it still applies even if unshaded or no fog
bool vertex_lit = (material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading) && ((!unshaded) || using_fog); //fog forces vertex lighting because it still applies even if unshaded or no fog
if (vertex_lit != prev_vertex_lit) {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, vertex_lit);
@ -1751,10 +1250,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
if (rebind_light && light) {
_setup_light(light, shadow_atlas, p_view_transform, accum_pass);
}
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
_render_geometry(e);
@ -1764,10 +1259,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
prev_material = material;
prev_instancing = instancing;
prev_octahedral_compression = octahedral_compression;
prev_light = light;
}
_setup_light_type(nullptr, nullptr); //clear light stuff
state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_OCTAHEDRAL_COMPRESSION, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false);
@ -1926,38 +1419,6 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
state.screen_pixel_size.x = 1.0 / viewport_width;
state.screen_pixel_size.y = 1.0 / viewport_height;
//push back the directional lights
if (p_light_cull_count) {
//hardcoded limit of 256 lights
render_light_instance_count = MIN(RenderList::MAX_LIGHTS, p_light_cull_count);
render_light_instances = (LightInstance **)alloca(sizeof(LightInstance *) * render_light_instance_count);
render_directional_lights = 0;
//doing this because directional lights are at the end, put them at the beginning
int index = 0;
for (int i = render_light_instance_count - 1; i >= 0; i--) {
RID light_rid = p_light_cull_result[i];
LightInstance *light = light_instance_owner.getornull(light_rid);
if (light->light_ptr->type == RS::LIGHT_DIRECTIONAL) {
render_directional_lights++;
//as going in reverse, directional lights are always first anyway
}
light->light_index = index;
render_light_instances[index] = light;
index++;
}
} else {
render_light_instances = nullptr;
render_directional_lights = 0;
render_light_instance_count = 0;
}
// render list stuff
render_list.clear();
@ -2114,12 +1575,6 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
state.render_no_shadows = false;
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
RasterizerStorageGLES2::Light *light = light_instance->light_ptr;
ERR_FAIL_COND(!light);
uint32_t x;
uint32_t y;
uint32_t width;
@ -2139,154 +1594,6 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
Projection light_projection;
Transform light_transform;
// TODO directional light
if (light->type == RS::LIGHT_DIRECTIONAL) {
// set pssm stuff
// TODO set this only when changed
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.position.y += light_instance->directional_rect.size.y;
}
} 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.position.x += light_instance->directional_rect.size.x;
}
if (light_instance->light_directional_index / 2) {
light_instance->directional_rect.position.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.position.x;
y = light_instance->directional_rect.position.y;
width = light_instance->directional_rect.size.width;
height = light_instance->directional_rect.size.height;
if (light->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS || light->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
width /= 2;
height /= 2;
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 == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
height /= 2;
if (p_pass == 0) {
} else {
y += height;
}
}
float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, light->param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]);
zfar = light->param[RS::LIGHT_PARAM_RANGE];
bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult;
normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult;
fbo = directional_shadow.fbo;
} else {
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;
uint32_t key = shadow_atlas->shadow_owners[p_light];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
ERR_FAIL_INDEX((int)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 == RS::LIGHT_OMNI) {
// cubemap only
if (light->omni_shadow_mode == RS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) {
int cubemap_index = shadow_cubemaps.size() - 1;
// find an appropriate cubemap to render to
for (int i = shadow_cubemaps.size() - 1; i >= 0; i--) {
if (shadow_cubemaps[i].size > shadow_size) {
break;
}
cubemap_index = i;
}
fbo = shadow_cubemaps[cubemap_index].fbo[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[RS::LIGHT_PARAM_RANGE];
current_cubemap = cubemap_index;
} else {
//dual parabolloid
state.shadow_is_dual_parabolloid = true;
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
if (light->omni_shadow_detail == RS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
height /= 2;
y += p_pass * height;
} else {
width /= 2;
x += p_pass * width;
}
state.dual_parbolloid_direction = p_pass == 0 ? 1.0 : -1.0;
flip_facing = (p_pass == 1);
zfar = light->param[RS::LIGHT_PARAM_RANGE];
bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS];
state.dual_parbolloid_zfar = zfar;
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, true);
}
} else if (light->type == RS::LIGHT_SPOT) {
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
flip_facing = false;
zfar = light->param[RS::LIGHT_PARAM_RANGE];
bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS];
normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS];
}
}
render_list.clear();
_fill_render_list(p_cull_result, p_cull_count, true, true);
@ -2321,10 +1628,6 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
}
glDisable(GL_SCISSOR_TEST);
if (light->reverse_cull) {
flip_facing = !flip_facing;
}
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false); // just in case, should be false already
@ -2333,53 +1636,6 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false);
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
// convert cubemap to dual paraboloid if needed
if (light->type == RS::LIGHT_OMNI && (light->omni_shadow_mode == RS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
state.cube_to_dp_shader.bind();
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap);
glDisable(GL_CULL_FACE);
for (int i = 0; i < 2; i++) {
state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FLIP, i == 1);
state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_NEAR, light_projection.get_z_near());
state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FAR, light_projection.get_z_far());
state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::BIAS, light->param[RS::LIGHT_PARAM_SHADOW_BIAS]);
uint32_t local_width = width;
uint32_t local_height = height;
uint32_t local_x = x;
uint32_t local_y = y;
if (light->omni_shadow_detail == RS::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.0f);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
storage->_copy_screen();
}
}
if (storage->frame.current_rt) {
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
}
@ -2393,25 +1649,7 @@ void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
}
bool RasterizerSceneGLES2::free(RID p_rid) {
if (light_instance_owner.owns(p_rid)) {
LightInstance *light_instance = light_instance_owner.getptr(p_rid);
//remove from shadow atlases..
for (RBSet<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get());
ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
uint32_t key = shadow_atlas->shadow_owners[p_rid];
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
shadow_atlas->shadow_owners.erase(p_rid);
}
light_instance_owner.free(p_rid);
memdelete(light_instance);
} else if (shadow_atlas_owner.owns(p_rid)) {
if (shadow_atlas_owner.owns(p_rid)) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid);
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);

View File

@ -113,102 +113,6 @@ public:
Color default_ambient;
Color default_bg;
// ResolveShaderGLES3 resolve_shader;
// ScreenSpaceReflectionShaderGLES3 ssr_shader;
// EffectBlurShaderGLES3 effect_blur_shader;
// SubsurfScatteringShaderGLES3 sss_shader;
// SsaoMinifyShaderGLES3 ssao_minify_shader;
// SsaoShaderGLES3 ssao_shader;
// SsaoBlurShaderGLES3 ssao_blur_shader;
// ExposureShaderGLES3 exposure_shader;
/*
struct SceneDataUBO {
//this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes
float projection_matrix[16];
float inv_projection_matrix[16];
float camera_inverse_matrix[16];
float camera_matrix[16];
float ambient_light_color[4];
float bg_color[4];
float fog_color_enabled[4];
float fog_sun_color_amount[4];
float ambient_energy;
float bg_energy;
float z_offset;
float z_slope_scale;
float shadow_dual_paraboloid_render_zfar;
float shadow_dual_paraboloid_render_side;
float viewport_size[2];
float screen_pixel_size[2];
float shadow_atlas_pixel_size[2];
float shadow_directional_pixel_size[2];
float time;
float z_far;
float reflection_multiplier;
float subsurface_scatter_width;
float ambient_occlusion_affect_light;
uint32_t fog_depth_enabled;
float fog_depth_begin;
float fog_depth_curve;
uint32_t fog_transmit_enabled;
float fog_transmit_curve;
uint32_t fog_height_enabled;
float fog_height_min;
float fog_height_max;
float fog_height_curve;
// make sure this struct is padded to be a multiple of 16 bytes for webgl
} ubo_data;
GLuint scene_ubo;
struct Environment3DRadianceUBO {
float transform[16];
float ambient_contribution;
uint8_t padding[12];
} env_radiance_data;
GLuint env_radiance_ubo;
GLuint sky_array;
GLuint directional_ubo;
GLuint spot_array_ubo;
GLuint omni_array_ubo;
GLuint reflection_array_ubo;
GLuint immediate_buffer;
GLuint immediate_array;
uint32_t ubo_light_size;
uint8_t *spot_array_tmp;
uint8_t *omni_array_tmp;
uint8_t *reflection_array_tmp;
int max_ubo_lights;
int max_forward_lights_per_object;
int max_ubo_reflections;
int max_skeleton_bones;
bool used_contact_shadows;
int spot_light_count;
int omni_light_count;
int directional_light_count;
bool used_sss;
bool using_contact_shadows;
RS::ViewportDebugDraw debug_draw;
*/
bool cull_front;
bool cull_disabled;
@ -301,57 +205,6 @@ public:
virtual int get_directional_light_shadow_size(RID p_light_intance);
virtual void set_directional_shadow_count(int p_count);
/* LIGHT INSTANCE */
struct LightInstance : public RID_Data {
struct ShadowTransform {
Projection camera;
Transform transform;
float farplane;
float split;
float bias_scale;
};
ShadowTransform shadow_transform[4];
RID self;
RID light;
RasterizerStorageGLES2::Light *light_ptr;
Transform transform;
Vector3 light_vector;
Vector3 spot_vector;
float linear_att;
// TODO passes and all that stuff ?
uint64_t last_scene_pass;
uint64_t last_scene_shadow_pass;
uint16_t light_index;
uint16_t light_directional_index;
Rect2 directional_rect;
// an ever increasing counter for each light added,
// used for sorting lights for a consistent render
uint32_t light_counter;
RBSet<RID> shadow_atlases; // atlases where this light is registered
};
mutable RID_Owner<LightInstance> light_instance_owner;
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 Projection &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
virtual void light_instance_mark_visible(RID p_light_instance);
virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_shadow_cubemaps; }
LightInstance **render_light_instances;
int render_directional_lights;
int render_light_instance_count;
/* RENDER LIST */
enum LightMode {
@ -362,7 +215,6 @@ public:
struct RenderList {
enum {
MAX_LIGHTS = 255,
MAX_REFLECTION_PROBES = 255,
DEFAULT_MAX_ELEMENTS = 65536
};
@ -544,8 +396,6 @@ public:
_FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull);
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0));
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *p_element);
_FORCE_INLINE_ void _setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas);
_FORCE_INLINE_ void _setup_light(LightInstance *p_light, ShadowAtlas *shadow_atlas, const Transform &p_view_transform, bool accum_pass);
_FORCE_INLINE_ void _render_geometry(RenderList::Element *p_element);
void _post_process(const Projection &p_cam_projection);

View File

@ -3543,257 +3543,6 @@ void RasterizerStorageGLES2::update_dirty_blend_shapes() {
}
}
/* Light API */
RID RasterizerStorageGLES2::light_create(RS::LightType p_type) {
Light *light = memnew(Light);
light->type = p_type;
light->param[RS::LIGHT_PARAM_ENERGY] = 1.0;
light->param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
light->param[RS::LIGHT_PARAM_SIZE] = 0.0;
light->param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
light->param[RS::LIGHT_PARAM_RANGE] = 1.0;
light->param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
light->param[RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
light->param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
light->param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
light->color = Color(1, 1, 1, 1);
light->shadow = false;
light->negative = false;
light->cull_mask = 0xFFFFFFFF;
light->directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
light->omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
light->omni_shadow_detail = RS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
light->directional_blend_splits = false;
light->directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
light->reverse_cull = false;
light->version = 0;
return light_owner.make_rid(light);
}
void RasterizerStorageGLES2::light_set_color(RID p_light, const Color &p_color) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->color = p_color;
}
void RasterizerStorageGLES2::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
switch (p_param) {
case RS::LIGHT_PARAM_RANGE:
case RS::LIGHT_PARAM_SPOT_ANGLE:
case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
light->instance_change_notify(true, false);
} break;
default: {
}
}
light->param[p_param] = p_value;
}
void RasterizerStorageGLES2::light_set_shadow(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow = p_enabled;
light->version++;
light->instance_change_notify(true, false);
}
void RasterizerStorageGLES2::light_set_shadow_color(RID p_light, const Color &p_color) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow_color = p_color;
}
void RasterizerStorageGLES2::light_set_projector(RID p_light, RID p_texture) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->projector = p_texture;
}
void RasterizerStorageGLES2::light_set_negative(RID p_light, bool p_enable) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->negative = p_enable;
}
void RasterizerStorageGLES2::light_set_cull_mask(RID p_light, uint32_t p_mask) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->cull_mask = p_mask;
light->version++;
light->instance_change_notify(true, false);
}
void RasterizerStorageGLES2::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->reverse_cull = p_enabled;
light->version++;
light->instance_change_notify(true, false);
}
void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, RS::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(true, false);
}
RS::LightOmniShadowMode RasterizerStorageGLES2::light_omni_get_shadow_mode(RID p_light) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
return light->omni_shadow_mode;
}
void RasterizerStorageGLES2::light_omni_set_shadow_detail(RID p_light, RS::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(true, false);
}
void RasterizerStorageGLES2::light_directional_set_shadow_mode(RID p_light, RS::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(true, false);
}
void RasterizerStorageGLES2::light_directional_set_blend_splits(RID p_light, bool p_enable) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_blend_splits = p_enable;
light->version++;
light->instance_change_notify(true, false);
}
bool RasterizerStorageGLES2::light_directional_get_blend_splits(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, false);
return light->directional_blend_splits;
}
RS::LightDirectionalShadowMode RasterizerStorageGLES2::light_directional_get_shadow_mode(RID p_light) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
return light->directional_shadow_mode;
}
void RasterizerStorageGLES2::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_range_mode = p_range_mode;
}
RS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES2::light_directional_get_shadow_depth_range_mode(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
return light->directional_range_mode;
}
RS::LightType RasterizerStorageGLES2::light_get_type(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return light->type;
}
float RasterizerStorageGLES2::light_get_param(RID p_light, RS::LightParam p_param) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0.0);
ERR_FAIL_INDEX_V(p_param, RS::LIGHT_PARAM_MAX, 0.0);
return light->param[p_param];
}
Color RasterizerStorageGLES2::light_get_color(RID p_light) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, Color());
return light->color;
}
bool RasterizerStorageGLES2::light_has_shadow(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, false);
return light->shadow;
}
uint64_t RasterizerStorageGLES2::light_get_version(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->version;
}
AABB RasterizerStorageGLES2::light_get_aabb(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, AABB());
switch (light->type) {
case RS::LIGHT_SPOT: {
float len = light->param[RS::LIGHT_PARAM_RANGE];
float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case RS::LIGHT_OMNI: {
float r = light->param[RS::LIGHT_PARAM_RANGE];
return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
};
case RS::LIGHT_DIRECTIONAL: {
return AABB();
};
}
ERR_FAIL_V(AABB());
}
////////
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
@ -3813,10 +3562,6 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene
inst = multimesh_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
case RS::INSTANCE_LIGHT: {
inst = light_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
default: {
ERR_FAIL();
}
@ -3837,10 +3582,6 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
inst = multimesh_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
case RS::INSTANCE_LIGHT: {
inst = light_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
default: {
ERR_FAIL();
}
@ -4739,8 +4480,6 @@ void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder,
RS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return RS::INSTANCE_MESH;
} else if (light_owner.owns(p_rid)) {
return RS::INSTANCE_LIGHT;
} else if (multimesh_owner.owns(p_rid)) {
return RS::INSTANCE_MULTIMESH;
} else {
@ -4879,14 +4618,6 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
multimesh_owner.free(p_rid);
memdelete(multimesh);
return true;
} else if (light_owner.owns(p_rid)) {
Light *light = light_owner.get(p_rid);
light->instance_remove_deps();
light_owner.free(p_rid);
memdelete(light);
return true;
} else if (canvas_occluder_owner.owns(p_rid)) {
CanvasOccluder *co = canvas_occluder_owner.get(p_rid);

View File

@ -818,69 +818,6 @@ public:
void update_dirty_multimeshes();
/* Light API */
struct Light : Instantiable {
RS::LightType type;
float param[RS::LIGHT_PARAM_MAX];
Color color;
Color shadow_color;
RID projector;
bool shadow;
bool negative;
bool reverse_cull;
uint32_t cull_mask;
RS::LightOmniShadowMode omni_shadow_mode;
RS::LightOmniShadowDetail omni_shadow_detail;
RS::LightDirectionalShadowMode directional_shadow_mode;
RS::LightDirectionalShadowDepthRangeMode directional_range_mode;
bool directional_blend_splits;
uint64_t version;
};
mutable RID_Owner<Light> light_owner;
virtual RID light_create(RS::LightType p_type);
virtual void light_set_color(RID p_light, const Color &p_color);
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
virtual void light_set_shadow(RID p_light, bool p_enabled);
virtual void light_set_shadow_color(RID p_light, const Color &p_color);
virtual void light_set_projector(RID p_light, RID p_texture);
virtual void light_set_negative(RID p_light, bool p_enable);
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask);
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode);
virtual void light_omni_set_shadow_detail(RID p_light, RS::LightOmniShadowDetail p_detail);
virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode);
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable);
virtual bool light_directional_get_blend_splits(RID p_light) const;
virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode);
virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
virtual bool light_has_shadow(RID p_light) const;
virtual RS::LightType light_get_type(RID p_light) const;
virtual float light_get_param(RID p_light, RS::LightParam p_param);
virtual Color light_get_color(RID p_light);
virtual AABB light_get_aabb(RID p_light) const;
virtual uint64_t light_get_version(RID p_light) const;
/* INSTANCE */
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);

View File

@ -118,12 +118,6 @@ public:
}
};
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const { return true; }
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID p_shadow_atlas) = 0;
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
@ -352,43 +346,6 @@ private:
void _multimesh_add_to_interpolation_lists(RID p_multimesh, MMInterpolator &r_mmi);
public:
/* Light API */
virtual RID light_create(RS::LightType p_type) = 0;
RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_projector(RID p_light, RID p_texture) = 0;
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
virtual void light_omni_set_shadow_detail(RID p_light, RS::LightOmniShadowDetail p_detail) = 0;
virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0;
virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
virtual bool light_has_shadow(RID p_light) const = 0;
virtual RS::LightType light_get_type(RID p_light) const = 0;
virtual AABB light_get_aabb(RID p_light) const = 0;
virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
virtual Color light_get_color(RID p_light) = 0;
virtual uint64_t light_get_version(RID p_light) const = 0;
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) = 0;

View File

@ -42,7 +42,6 @@ class RenderingServerRaster : public RenderingServer {
enum {
MAX_INSTANCE_CULL = 8192,
MAX_INSTANCE_LIGHTS = 4,
LIGHT_CACHE_DIRTY = -1,
MAX_LIGHTS_CULLED = 256,
MAX_LIGHT_SAMPLERS = 256,
@ -283,28 +282,6 @@ public:
BIND2(multimesh_set_visible_instances, RID, int)
BIND1RC(int, multimesh_get_visible_instances, RID)
/* Light API */
BIND0R(RID, directional_light_create)
BIND0R(RID, omni_light_create)
BIND0R(RID, spot_light_create)
BIND2(light_set_color, RID, const Color &)
BIND3(light_set_param, RID, LightParam, float)
BIND2(light_set_shadow, RID, bool)
BIND2(light_set_shadow_color, RID, const Color &)
BIND2(light_set_projector, RID, RID)
BIND2(light_set_negative, RID, bool)
BIND2(light_set_cull_mask, RID, uint32_t)
BIND2(light_set_reverse_cull_face_mode, RID, bool)
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
BIND2(light_directional_set_blend_splits, RID, bool)
BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
#undef BINDBASE
//from now on, calls forwarded to this singleton
#define BINDBASE RSG::scene

View File

@ -304,24 +304,6 @@ void *RenderingServerScene::_instance_pair(void *p_self, SpatialPartitionID, Ins
SWAP(A, B); //lesser always first
}
if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
InstanceLightData::PairInfo pinfo;
pinfo.geometry = A;
pinfo.L = geom->lighting.push_back(B);
List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
if (geom->can_cast_shadows) {
light->shadow_dirty = true;
}
geom->lighting_dirty = true;
return E; //this element should make freeing faster
}
return nullptr;
}
@ -334,22 +316,6 @@ void RenderingServerScene::_instance_unpair(void *p_self, SpatialPartitionID, In
if (A->base_type > B->base_type) {
SWAP(A, B); //lesser always first
}
if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element *>(udata);
geom->lighting.erase(E->get().L);
light->geometries.erase(E);
if (geom->can_cast_shadows) {
light->shadow_dirty = true;
}
geom->lighting_dirty = true;
}
}
RID RenderingServerScene::scenario_create() {
@ -455,20 +421,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
instance->spatial_partition_id = 0;
}
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
if (instance->scenario && light->D) {
instance->scenario->directional_lights.erase(light->D);
light->D = nullptr;
}
RSG::scene_render->free(light->instance);
} break;
default: {
}
}
if (instance->base_data) {
memdelete(instance->base_data);
instance->base_data = nullptr;
@ -492,17 +444,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE);
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = memnew(InstanceLightData);
if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
light->instance = RSG::scene_render->light_instance_create(p_base);
instance->base_data = light;
} break;
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH: {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
@ -540,19 +481,6 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
// remove any interpolation data associated with the instance in this scenario
_interpolation_data.notify_free_instance(p_instance, *instance);
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
if (light->D) {
instance->scenario->directional_lights.erase(light->D);
light->D = nullptr;
}
} break;
default: {
}
}
instance->scenario = nullptr;
}
@ -564,18 +492,6 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
scenario->instances.add(&instance->scenario_item);
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
} break;
default: {
}
}
_instance_queue_update(instance, true, true);
}
}
@ -588,18 +504,6 @@ void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_ma
}
instance->layer_mask = p_mask;
// update lights to show / hide shadows according to the new mask
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
if (geom->can_cast_shadows) {
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
}
}
}
void RenderingServerScene::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) {
@ -957,25 +861,7 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible)
}
}
// when showing or hiding geometry, lights must be kept up to date to show / hide shadows
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
if (geom->can_cast_shadows) {
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
}
}
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->spatial_partition_id && instance->scenario) {
instance->scenario->sps->set_pairable(instance, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
}
} break;
default: {
// if we haven't called set_pairable, we STILL need to do a collision check
// for activated items because we deferred it earlier in the call to activate.
@ -1188,29 +1074,10 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
// However it does seem that using the interpolated transform (transform) works for keeping AABBs
// up to date to avoid culling errors.
if (p_instance->base_type == RS::INSTANCE_LIGHT) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
RSG::scene_render->light_instance_set_transform(light->instance, *instance_xform);
light->shadow_dirty = true;
}
if (p_instance->aabb.has_no_surface()) {
return;
}
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
//make sure lights are updated if it casts shadow
if (geom->can_cast_shadows) {
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
}
}
p_instance->mirror = instance_xform->basis.determinant() < 0.0;
AABB new_aabb;
@ -1228,11 +1095,6 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
uint32_t pairable_mask = 0;
bool pairable = false;
if (p_instance->base_type == RS::INSTANCE_LIGHT) {
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
pairable = true;
}
// not inside octree
p_instance->spatial_partition_id = p_instance->scenario->sps->create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask);
@ -1272,10 +1134,6 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
}
} break;
case RenderingServer::INSTANCE_LIGHT: {
new_aabb = RSG::storage->light_get_aabb(p_instance->base);
} break;
default: {
}
@ -1389,12 +1247,6 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
}
if (can_cast_shadows != geom->can_cast_shadows) {
//ability to cast shadows change, let lights now
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
geom->can_cast_shadows = can_cast_shadows;
}
@ -1410,376 +1262,6 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
p_instance->update_materials = false;
}
bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
bool animated_material_found = false;
switch (RSG::storage->light_get_type(p_instance->base)) {
case RS::LIGHT_DIRECTIONAL: {
float max_distance = p_cam_projection.get_z_far();
float shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
max_distance = MIN(shadow_max, max_distance);
}
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
float min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
//optimize min/max
Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
int cull_count = p_scenario->sps->cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2));
//check distance max and min
bool found_items = false;
float z_max = -1e20;
float z_min = 1e20;
for (int i = 0; i < cull_count; i++) {
Instance *instance = instance_shadow_cull_result[i];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
continue;
}
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
animated_material_found = true;
}
float max, min;
instance->transformed_aabb.project_range_in_plane(base, min, max);
if (max > z_max) {
z_max = max;
}
if (min < z_min) {
z_min = min;
}
found_items = true;
}
if (found_items) {
min_distance = MAX(min_distance, z_min);
max_distance = MIN(max_distance, z_max);
}
}
float range = max_distance - min_distance;
int splits = 0;
switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
splits = 1;
break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
splits = 2;
break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS:
splits = 3;
break;
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
splits = 4;
break;
}
float distances[5];
distances[0] = min_distance;
for (int i = 0; i < splits; i++) {
distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
};
distances[splits] = max_distance;
float texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
float first_radius = 0.0;
for (int i = 0; i < splits; i++) {
// setup a camera matrix for that range!
Projection camera_matrix;
float aspect = p_cam_projection.get_aspect();
if (p_cam_orthogonal) {
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
} else {
float fov = p_cam_projection.get_fov();
camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
}
//obtain the frustum endpoints
Vector3 endpoints[8]; // frustum plane endpoints
bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints);
ERR_CONTINUE(!res);
// obtain the light frustm ranges (given endpoints)
Transform transform = light_transform; //discard scale and stabilize light
Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized();
Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized();
Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
//z_vec points agsint the camera, like in default opengl
float x_min = 0.f, x_max = 0.f;
float y_min = 0.f, y_max = 0.f;
float z_min = 0.f, z_max = 0.f;
// FIXME: z_max_cam is defined, computed, but not used below when setting up
// ortho_camera. Commented out for now to fix warnings but should be investigated.
float x_min_cam = 0.f, x_max_cam = 0.f;
float y_min_cam = 0.f, y_max_cam = 0.f;
float z_min_cam = 0.f;
//float z_max_cam = 0.f;
float bias_scale = 1.0;
//used for culling
for (int j = 0; j < 8; j++) {
float d_x = x_vec.dot(endpoints[j]);
float d_y = y_vec.dot(endpoints[j]);
float d_z = z_vec.dot(endpoints[j]);
if (j == 0 || d_x < x_min) {
x_min = d_x;
}
if (j == 0 || d_x > x_max) {
x_max = d_x;
}
if (j == 0 || d_y < y_min) {
y_min = d_y;
}
if (j == 0 || d_y > y_max) {
y_max = d_y;
}
if (j == 0 || d_z < z_min) {
z_min = d_z;
}
if (j == 0 || d_z > z_max) {
z_max = d_z;
}
}
{
//camera viewport stuff
Vector3 center;
for (int j = 0; j < 8; j++) {
center += endpoints[j];
}
center /= 8.0;
//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
float radius = 0;
for (int j = 0; j < 8; j++) {
float d = center.distance_to(endpoints[j]);
if (d > radius) {
radius = d;
}
}
radius *= texture_size / (texture_size - 2.0); //add a texel by each side
if (i == 0) {
first_radius = radius;
} else {
bias_scale = radius / first_radius;
}
x_max_cam = x_vec.dot(center) + radius;
x_min_cam = x_vec.dot(center) - radius;
y_max_cam = y_vec.dot(center) + radius;
y_min_cam = y_vec.dot(center) - radius;
//z_max_cam = z_vec.dot(center) + radius;
z_min_cam = z_vec.dot(center) - radius;
if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
//this trick here is what stabilizes the shadow (make potential jaggies to not move)
//at the cost of some wasted resolution. Still the quality increase is very well worth it
float unit = radius * 2.0 / texture_size;
x_max_cam = Math::stepify(x_max_cam, unit);
x_min_cam = Math::stepify(x_min_cam, unit);
y_max_cam = Math::stepify(y_max_cam, unit);
y_min_cam = Math::stepify(y_min_cam, unit);
}
}
//now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
Vector<Plane> light_frustum_planes;
light_frustum_planes.resize(6);
//right/left
light_frustum_planes.write[0] = Plane(x_vec, x_max);
light_frustum_planes.write[1] = Plane(-x_vec, -x_min);
//top/bottom
light_frustum_planes.write[2] = Plane(y_vec, y_max);
light_frustum_planes.write[3] = Plane(-y_vec, -y_min);
//near/far
light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);
light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
int cull_count = p_scenario->sps->cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
// a pre pass will need to be needed to determine the actual z-near to be used
Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
for (int j = 0; j < cull_count; j++) {
float min, max;
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
cull_count--;
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
continue;
}
instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
if (max > z_max) {
z_max = max;
}
}
{
Projection ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));
Transform ortho_transform;
ortho_transform.basis = transform.basis;
ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, 0, distances[i + 1], i, bias_scale);
}
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
}
} break;
case RS::LIGHT_OMNI: {
RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::scene_render->light_instances_can_render_shadow_cube()) {
for (int i = 0; i < 2; i++) {
//using this one ensures that raster deferred will have it
float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
float z = i == 0 ? -1 : 1;
Vector<Plane> planes;
planes.resize(6);
planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
int cull_count = p_scenario->sps->cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
for (int j = 0; j < cull_count; j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
cull_count--;
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
animated_material_found = true;
}
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
}
RSG::scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
}
} else { //shadow cube
float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
Projection cm;
cm.set_perspective(90, 1, 0.01, radius);
for (int i = 0; i < 6; i++) {
//using this one ensures that raster deferred will have it
static const Vector3 view_normals[6] = {
Vector3(-1, 0, 0),
Vector3(+1, 0, 0),
Vector3(0, -1, 0),
Vector3(0, +1, 0),
Vector3(0, 0, -1),
Vector3(0, 0, +1)
};
static const Vector3 view_up[6] = {
Vector3(0, -1, 0),
Vector3(0, -1, 0),
Vector3(0, 0, -1),
Vector3(0, 0, +1),
Vector3(0, -1, 0),
Vector3(0, -1, 0)
};
Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
Vector<Plane> planes = cm.get_projection_planes(xform);
RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, 0);
}
//restore the regular DP matrix
RSG::scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0);
}
} break;
case RS::LIGHT_SPOT: {
float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
float angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
Projection cm;
cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
Vector<Plane> planes = cm.get_projection_planes(light_transform);
RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, 0);
} break;
}
return animated_material_found;
}
void RenderingServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
// render to mono camera
#ifndef _3D_DISABLED
@ -1874,21 +1356,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
if ((camera_layer_mask & ins->layer_mask) == 0) {
//failure
} else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
if (light_cull_count < MAX_LIGHTS_CULLED) {
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
if (!light->geometries.empty()) {
//do not add this light if no geometry is affected by it..
light_cull_result[light_cull_count] = ins;
light_instance_cull_result[light_cull_count] = light->instance;
if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) {
RSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
}
light_cull_count++;
}
}
} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
keep = true;
@ -1902,13 +1369,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
int l = 0;
//only called when lights AABB enter/exit this geometry
ins->light_instances.resize(geom->lighting.size());
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
ins->light_instances.write[l++] = light->instance;
}
geom->lighting_dirty = false;
}
@ -1930,137 +1390,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
directional_light_count = 0;
// directional lights
{
Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
int directional_shadow_count = 0;
for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) {
break;
}
if (!E->get()->visible) {
continue;
}
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
//check shadow..
if (light) {
if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base)) {
lights_with_shadow[directional_shadow_count++] = E->get();
}
//add to list
directional_light_ptr[directional_light_count++] = light->instance;
}
}
RSG::scene_render->set_directional_shadow_count(directional_shadow_count);
for (int i = 0; i < directional_shadow_count; i++) {
_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario, p_visible_layers);
}
}
{ //setup shadow maps
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
for (int i = 0; i < light_cull_count; i++) {
Instance *ins = light_cull_result[i];
if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
continue;
}
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
float coverage = 0.f;
{ //compute coverage
Transform cam_xf = p_cam_transform;
float zn = p_cam_projection.get_z_near();
Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
switch (RSG::storage->light_get_type(ins->base)) {
case RS::LIGHT_OMNI: {
float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
//get two points parallel to near plane
Vector3 points[2] = {
ins->transform.origin,
ins->transform.origin + cam_xf.basis.get_axis(0) * radius
};
if (!p_cam_orthogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
points[j].z = -zn; //small hack to keep size constant when hitting the screen
}
p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
}
}
float screen_diameter = points[0].distance_to(points[1]) * 2;
coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
} break;
case RS::LIGHT_SPOT: {
float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
float w = radius * Math::sin(Math::deg2rad(angle));
float d = radius * Math::cos(Math::deg2rad(angle));
Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d;
Vector3 points[2] = {
base,
base + cam_xf.basis.get_axis(0) * w
};
if (!p_cam_orthogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
points[j].z = -zn; //small hack to keep size constant when hitting the screen
}
p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
}
}
float screen_diameter = points[0].distance_to(points[1]) * 2;
coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
} break;
default: {
ERR_PRINT("Invalid Light Type");
}
}
}
if (light->shadow_dirty) {
light->last_version++;
light->shadow_dirty = false;
}
bool redraw = RSG::scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
if (redraw) {
//must redraw!
light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario, p_visible_layers);
}
}
}
// Calculate instance->depth from the camera, after shadow calculation has stopped overwriting instance->depth
for (int i = 0; i < instance_cull_count; i++) {
Instance *ins = instance_cull_result[i];

View File

@ -448,30 +448,6 @@ public:
}
};
struct InstanceLightData : public InstanceBaseData {
struct PairInfo {
List<Instance *>::Element *L; //light iterator in geometry
Instance *geometry;
};
RID instance;
uint64_t last_version;
List<Instance *>::Element *D; // directional light in scenario
bool shadow_dirty;
List<PairInfo> geometries;
int32_t previous_room_id_hint;
InstanceLightData() {
shadow_dirty = true;
D = nullptr;
last_version = 0;
previous_room_id_hint = -1;
}
};
int instance_cull_count;
Instance *instance_cull_result[MAX_INSTANCE_CULL];
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
@ -526,8 +502,6 @@ public:
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers = 0xFFFFFF);
void _prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int32_t &r_previous_room_id_hint);
void _render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas);
void render_empty_scene(RID p_scenario, RID p_shadow_atlas);

View File

@ -145,9 +145,6 @@ void RenderingServerWrapMT::finish() {
material_free_cached_ids();
mesh_free_cached_ids();
multimesh_free_cached_ids();
directional_light_free_cached_ids();
omni_light_free_cached_ids();
spot_light_free_cached_ids();
camera_free_cached_ids();
viewport_free_cached_ids();
scenario_free_cached_ids();

View File

@ -209,28 +209,6 @@ public:
FUNC2(multimesh_set_visible_instances, RID, int)
FUNC1RC(int, multimesh_get_visible_instances, RID)
/* Light API */
FUNCRID(directional_light)
FUNCRID(omni_light)
FUNCRID(spot_light)
FUNC2(light_set_color, RID, const Color &)
FUNC3(light_set_param, RID, LightParam, float)
FUNC2(light_set_shadow, RID, bool)
FUNC2(light_set_shadow_color, RID, const Color &)
FUNC2(light_set_projector, RID, RID)
FUNC2(light_set_negative, RID, bool)
FUNC2(light_set_cull_mask, RID, uint32_t)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* CAMERA API */
FUNCRID(camera)

View File

@ -1920,29 +1920,6 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("multimesh_set_physics_interpolation_quality", "multimesh", "quality"), &RenderingServer::multimesh_set_physics_interpolation_quality);
ClassDB::bind_method(D_METHOD("multimesh_instance_reset_physics_interpolation", "multimesh", "index"), &RenderingServer::multimesh_instance_reset_physics_interpolation);
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("directional_light_create"), &RenderingServer::directional_light_create);
ClassDB::bind_method(D_METHOD("omni_light_create"), &RenderingServer::omni_light_create);
ClassDB::bind_method(D_METHOD("spot_light_create"), &RenderingServer::spot_light_create);
ClassDB::bind_method(D_METHOD("light_set_color", "light", "color"), &RenderingServer::light_set_color);
ClassDB::bind_method(D_METHOD("light_set_param", "light", "param", "value"), &RenderingServer::light_set_param);
ClassDB::bind_method(D_METHOD("light_set_shadow", "light", "enabled"), &RenderingServer::light_set_shadow);
ClassDB::bind_method(D_METHOD("light_set_shadow_color", "light", "color"), &RenderingServer::light_set_shadow_color);
ClassDB::bind_method(D_METHOD("light_set_projector", "light", "texture"), &RenderingServer::light_set_projector);
ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &RenderingServer::light_set_negative);
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &RenderingServer::light_omni_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_detail", "light", "detail"), &RenderingServer::light_omni_set_shadow_detail);
ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits);
ClassDB::bind_method(D_METHOD("light_directional_set_shadow_depth_range_mode", "light", "range_mode"), &RenderingServer::light_directional_set_shadow_depth_range_mode);
#endif
ClassDB::bind_method(D_METHOD("camera_create"), &RenderingServer::camera_create);
ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &RenderingServer::camera_set_perspective);
ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &RenderingServer::camera_set_orthogonal);
@ -2219,40 +2196,6 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
BIND_ENUM_CONSTANT(LIGHT_OMNI);
BIND_ENUM_CONSTANT(LIGHT_SPOT);
BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_VERTICAL);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE);
@ -2298,7 +2241,6 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(INSTANCE_NONE);
BIND_ENUM_CONSTANT(INSTANCE_MESH);
BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH);
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
BIND_ENUM_CONSTANT(INSTANCE_MAX);
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);

View File

@ -387,83 +387,6 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
/* Light API */
enum LightType {
LIGHT_DIRECTIONAL,
LIGHT_OMNI,
LIGHT_SPOT
};
enum LightParam {
LIGHT_PARAM_ENERGY,
LIGHT_PARAM_INDIRECT_ENERGY,
LIGHT_PARAM_SIZE,
LIGHT_PARAM_SPECULAR,
LIGHT_PARAM_RANGE,
LIGHT_PARAM_ATTENUATION,
LIGHT_PARAM_SPOT_ANGLE,
LIGHT_PARAM_SPOT_ATTENUATION,
LIGHT_PARAM_CONTACT_SHADOW_SIZE,
LIGHT_PARAM_SHADOW_MAX_DISTANCE,
LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
LIGHT_PARAM_MAX
};
virtual RID directional_light_create() = 0;
virtual RID omni_light_create() = 0;
virtual RID spot_light_create() = 0;
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, LightParam p_param, float p_value) = 0;
virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_projector(RID p_light, RID p_texture) = 0;
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
// omni light
enum LightOmniShadowMode {
LIGHT_OMNI_SHADOW_DUAL_PARABOLOID,
LIGHT_OMNI_SHADOW_CUBE,
};
virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0;
// omni light
enum LightOmniShadowDetail {
LIGHT_OMNI_SHADOW_DETAIL_VERTICAL,
LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL
};
virtual void light_omni_set_shadow_detail(RID p_light, LightOmniShadowDetail p_detail) = 0;
// directional light
enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS
};
virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
enum LightDirectionalShadowDepthRangeMode {
LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE,
LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED,
};
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
/* CAMERA API */
virtual RID camera_create() = 0;
@ -616,7 +539,6 @@ public:
INSTANCE_NONE,
INSTANCE_MESH,
INSTANCE_MULTIMESH,
INSTANCE_LIGHT,
INSTANCE_MAX,
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH)
@ -923,8 +845,6 @@ VARIANT_ENUM_CAST(RenderingServer::ArrayType);
VARIANT_ENUM_CAST(RenderingServer::ArrayFormat);
VARIANT_ENUM_CAST(RenderingServer::PrimitiveType);
VARIANT_ENUM_CAST(RenderingServer::BlendShapeMode);
VARIANT_ENUM_CAST(RenderingServer::LightType);
VARIANT_ENUM_CAST(RenderingServer::LightParam);
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA);
@ -943,10 +863,6 @@ VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat);
VARIANT_ENUM_CAST(RenderingServer::MultimeshColorFormat);
VARIANT_ENUM_CAST(RenderingServer::MultimeshCustomDataFormat);
VARIANT_ENUM_CAST(RenderingServer::MultimeshPhysicsInterpolationQuality);
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowDetail);
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode);
VARIANT_ENUM_CAST(RenderingServer::InstanceFlags);
VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting);
VARIANT_ENUM_CAST(RenderingServer::TextureType);