mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2024-11-17 22:17:19 +01:00
Removed 3d light api.
This commit is contained in:
parent
ef3511a544
commit
219534c1ae
@ -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(); }
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user