Several fixes to directional shadows, closes #10926
Added option to change directional light range mode, between optimized and stable. For Orthogonal, you might need to use optimized.
This commit is contained in:
parent
1eeda0f32f
commit
eedb39091a
|
@ -265,76 +265,28 @@ void CameraMatrix::get_viewport_size(real_t &r_width, real_t &r_height) const {
|
|||
|
||||
bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
|
||||
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
Vector<Plane> planes = get_projection_planes(Transform());
|
||||
const Planes intersections[8][3]={
|
||||
{PLANE_FAR,PLANE_LEFT,PLANE_TOP},
|
||||
{PLANE_FAR,PLANE_LEFT,PLANE_BOTTOM},
|
||||
{PLANE_FAR,PLANE_RIGHT,PLANE_TOP},
|
||||
{PLANE_FAR,PLANE_RIGHT,PLANE_BOTTOM},
|
||||
{PLANE_NEAR,PLANE_LEFT,PLANE_TOP},
|
||||
{PLANE_NEAR,PLANE_LEFT,PLANE_BOTTOM},
|
||||
{PLANE_NEAR,PLANE_RIGHT,PLANE_TOP},
|
||||
{PLANE_NEAR,PLANE_RIGHT,PLANE_BOTTOM},
|
||||
};
|
||||
|
||||
///////--- Near Plane ---///////
|
||||
Plane near_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
-matrix[15] - matrix[14]);
|
||||
near_plane.normalize();
|
||||
for(int i=0;i<8;i++) {
|
||||
|
||||
///////--- Far Plane ---///////
|
||||
Plane far_plane = Plane(matrix[2] - matrix[3],
|
||||
matrix[6] - matrix[7],
|
||||
matrix[10] - matrix[11],
|
||||
matrix[15] - matrix[14]);
|
||||
far_plane.normalize();
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
Plane right_plane = Plane(matrix[0] - matrix[3],
|
||||
matrix[4] - matrix[7],
|
||||
matrix[8] - matrix[11],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
///////--- Top Plane ---///////
|
||||
Plane top_plane = Plane(matrix[1] - matrix[3],
|
||||
matrix[5] - matrix[7],
|
||||
matrix[9] - matrix[11],
|
||||
-matrix[15] + matrix[13]);
|
||||
top_plane.normalize();
|
||||
|
||||
Vector3 near_endpoint_left, near_endpoint_right;
|
||||
Vector3 far_endpoint_left, far_endpoint_right;
|
||||
|
||||
bool res = near_plane.intersect_3(right_plane, top_plane, &near_endpoint_right);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
|
||||
res = far_plane.intersect_3(right_plane, top_plane, &far_endpoint_right);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
|
||||
if ((matrix[8] == 0) && (matrix[9] == 0)) {
|
||||
near_endpoint_left = near_endpoint_right;
|
||||
near_endpoint_left.x = -near_endpoint_left.x;
|
||||
|
||||
far_endpoint_left = far_endpoint_right;
|
||||
far_endpoint_left.x = -far_endpoint_left.x;
|
||||
} else {
|
||||
///////--- Left Plane ---///////
|
||||
Plane left_plane = Plane(matrix[0] + matrix[3],
|
||||
matrix[4] + matrix[7],
|
||||
matrix[8] + matrix[11],
|
||||
-matrix[15] - matrix[12]);
|
||||
left_plane.normalize();
|
||||
|
||||
res = near_plane.intersect_3(left_plane, top_plane, &near_endpoint_left);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
|
||||
res = far_plane.intersect_3(left_plane, top_plane, &far_endpoint_left);
|
||||
Vector3 point;
|
||||
bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]],planes[intersections[i][2]], &point);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
p_8points[i]=p_transform.xform(point);
|
||||
}
|
||||
|
||||
p_8points[0] = p_transform.xform(Vector3(near_endpoint_right.x, near_endpoint_right.y, near_endpoint_right.z));
|
||||
p_8points[1] = p_transform.xform(Vector3(near_endpoint_right.x, -near_endpoint_right.y, near_endpoint_right.z));
|
||||
p_8points[2] = p_transform.xform(Vector3(near_endpoint_left.x, near_endpoint_left.y, near_endpoint_left.z));
|
||||
p_8points[3] = p_transform.xform(Vector3(near_endpoint_left.x, -near_endpoint_left.y, near_endpoint_left.z));
|
||||
p_8points[4] = p_transform.xform(Vector3(far_endpoint_right.x, far_endpoint_right.y, far_endpoint_right.z));
|
||||
p_8points[5] = p_transform.xform(Vector3(far_endpoint_right.x, -far_endpoint_right.y, far_endpoint_right.z));
|
||||
p_8points[6] = p_transform.xform(Vector3(far_endpoint_left.x, far_endpoint_left.y, far_endpoint_left.z));
|
||||
p_8points[7] = p_transform.xform(Vector3(far_endpoint_left.x, -far_endpoint_left.y, far_endpoint_left.z));
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
|
||||
|
@ -610,6 +562,12 @@ int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
|
|||
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
|
||||
}
|
||||
|
||||
bool CameraMatrix::is_orthogonal() const {
|
||||
|
||||
return matrix[3][3]==1.0;
|
||||
}
|
||||
|
||||
|
||||
real_t CameraMatrix::get_fov() const {
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ struct CameraMatrix {
|
|||
real_t get_z_near() const;
|
||||
real_t get_aspect() const;
|
||||
real_t get_fov() const;
|
||||
bool is_orthogonal() const;
|
||||
|
||||
Vector<Plane> get_projection_planes(const Transform &p_transform) const;
|
||||
|
||||
|
@ -83,6 +84,7 @@ struct CameraMatrix {
|
|||
Plane xform4(const Plane &p_vec4) const;
|
||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
|
||||
|
||||
|
||||
operator String() const;
|
||||
|
||||
void scale_translate_to_fit(const Rect3 &p_aabb);
|
||||
|
|
|
@ -2599,7 +2599,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
|
|||
}
|
||||
}
|
||||
|
||||
ubo_data.shadow_split_offsets[j] = 1.0 / li->shadow_transform[j].split;
|
||||
ubo_data.shadow_split_offsets[j] = li->shadow_transform[j].split;
|
||||
|
||||
Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse();
|
||||
|
||||
|
@ -4331,7 +4331,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
|||
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
|
||||
}
|
||||
|
||||
if (false && directional_shadow.fbo) {
|
||||
if (true && directional_shadow.fbo) {
|
||||
|
||||
//_copy_texture_to_front_buffer(shadow_atlas->depth);
|
||||
storage->canvas->canvas_begin();
|
||||
|
|
|
@ -4473,6 +4473,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
|
|||
light->omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
|
||||
light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
|
||||
light->directional_blend_splits = false;
|
||||
light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
|
||||
light->reverse_cull = false;
|
||||
light->version = 0;
|
||||
|
||||
|
@ -4625,6 +4626,22 @@ VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_sha
|
|||
return light->directional_shadow_mode;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
|
||||
|
||||
Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND(!light);
|
||||
|
||||
light->directional_range_mode=p_range_mode;
|
||||
}
|
||||
|
||||
VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES3::light_directional_get_shadow_depth_range_mode(RID p_light) const {
|
||||
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
|
||||
|
||||
return light->directional_range_mode;
|
||||
}
|
||||
|
||||
VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
|
||||
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
|
|
|
@ -879,6 +879,7 @@ public:
|
|||
VS::LightOmniShadowMode omni_shadow_mode;
|
||||
VS::LightOmniShadowDetail omni_shadow_detail;
|
||||
VS::LightDirectionalShadowMode directional_shadow_mode;
|
||||
VS::LightDirectionalShadowDepthRangeMode directional_range_mode;
|
||||
bool directional_blend_splits;
|
||||
uint64_t version;
|
||||
};
|
||||
|
@ -906,6 +907,9 @@ public:
|
|||
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
|
||||
virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
|
||||
|
||||
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
|
||||
virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
|
||||
|
||||
virtual bool light_has_shadow(RID p_light) const;
|
||||
|
||||
virtual VS::LightType light_get_type(RID p_light) const;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -230,7 +230,6 @@ void Light::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_max_distance", PROPERTY_HINT_RANGE, "0,65536,0.1"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
|
||||
ADD_GROUP("Editor", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
|
||||
|
@ -308,6 +307,18 @@ DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const {
|
|||
return shadow_mode;
|
||||
}
|
||||
|
||||
void DirectionalLight::set_shadow_depth_range(ShadowDepthRange p_range) {
|
||||
shadow_depth_range=p_range;
|
||||
VS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, VS::LightDirectionalShadowDepthRangeMode(p_range));
|
||||
|
||||
}
|
||||
|
||||
DirectionalLight::ShadowDepthRange DirectionalLight::get_shadow_depth_range() const {
|
||||
|
||||
return shadow_depth_range;
|
||||
}
|
||||
|
||||
|
||||
void DirectionalLight::set_blend_splits(bool p_enable) {
|
||||
|
||||
blend_splits = p_enable;
|
||||
|
@ -324,6 +335,9 @@ void DirectionalLight::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight::set_shadow_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight::get_shadow_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight::set_shadow_depth_range);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight::get_shadow_depth_range);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight::set_blend_splits);
|
||||
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled);
|
||||
|
||||
|
@ -335,10 +349,15 @@ void DirectionalLight::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_max_distance", PROPERTY_HINT_RANGE, "0,65536,0.1"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
|
||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
|
||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS);
|
||||
|
||||
BIND_ENUM_CONSTANT( SHADOW_DEPTH_RANGE_STABLE );
|
||||
BIND_ENUM_CONSTANT( SHADOW_DEPTH_RANGE_OPTIMIZED );
|
||||
}
|
||||
|
||||
DirectionalLight::DirectionalLight()
|
||||
|
@ -349,6 +368,8 @@ DirectionalLight::DirectionalLight()
|
|||
set_param(PARAM_SHADOW_MAX_DISTANCE, 200);
|
||||
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
|
||||
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
|
||||
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
|
||||
|
||||
|
||||
blend_splits = false;
|
||||
}
|
||||
|
|
|
@ -133,9 +133,15 @@ public:
|
|||
SHADOW_PARALLEL_4_SPLITS
|
||||
};
|
||||
|
||||
enum ShadowDepthRange {
|
||||
SHADOW_DEPTH_RANGE_STABLE = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE,
|
||||
SHADOW_DEPTH_RANGE_OPTIMIZED = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED,
|
||||
};
|
||||
|
||||
private:
|
||||
bool blend_splits;
|
||||
ShadowMode shadow_mode;
|
||||
ShadowDepthRange shadow_depth_range;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -144,6 +150,9 @@ public:
|
|||
void set_shadow_mode(ShadowMode p_mode);
|
||||
ShadowMode get_shadow_mode() const;
|
||||
|
||||
void set_shadow_depth_range(ShadowDepthRange p_mode);
|
||||
ShadowDepthRange get_shadow_depth_range() const;
|
||||
|
||||
void set_blend_splits(bool p_enable);
|
||||
bool is_blend_splits_enabled() const;
|
||||
|
||||
|
@ -151,6 +160,7 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(DirectionalLight::ShadowMode)
|
||||
VARIANT_ENUM_CAST(DirectionalLight::ShadowDepthRange)
|
||||
|
||||
class OmniLight : public Light {
|
||||
|
||||
|
|
|
@ -335,6 +335,9 @@ public:
|
|||
virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0;
|
||||
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
|
||||
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
|
||||
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
|
||||
virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0;
|
||||
|
||||
|
||||
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
|
||||
virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
|
||||
|
|
|
@ -795,6 +795,7 @@ public:
|
|||
|
||||
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)
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
|
|
|
@ -886,12 +886,55 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
|
||||
float max_distance = p_cam_projection.get_z_far();
|
||||
float shadow_max = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
|
||||
if (shadow_max > 0) {
|
||||
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);
|
||||
|
||||
float range = max_distance - p_cam_projection.get_z_near();
|
||||
VS::LightDirectionalShadowDepthRangeMode depth_range_mode = VSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
|
||||
|
||||
if (depth_range_mode==VS::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->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::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) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
|
||||
|
@ -902,9 +945,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
|
||||
float distances[5];
|
||||
|
||||
distances[0] = p_cam_projection.get_z_near();
|
||||
distances[0] = min_distance;
|
||||
for (int i = 0; i < splits; i++) {
|
||||
distances[i + 1] = p_cam_projection.get_z_near() + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
|
||||
distances[i + 1] = min_distance + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
|
||||
};
|
||||
|
||||
distances[splits] = max_distance;
|
||||
|
@ -984,8 +1027,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
|
||||
{
|
||||
//camera viewport stuff
|
||||
//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
|
||||
|
||||
Vector3 center;
|
||||
|
||||
|
@ -1006,7 +1047,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
radius = d;
|
||||
}
|
||||
|
||||
radius *= texture_size / (texture_size - 2.0); //add a texel by each side, so stepified texture will always fit
|
||||
radius *= texture_size / (texture_size - 2.0); //add a texel by each side
|
||||
|
||||
if (i == 0) {
|
||||
first_radius = radius;
|
||||
|
@ -1021,12 +1062,19 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
z_max_cam = z_vec.dot(center) + radius;
|
||||
z_min_cam = z_vec.dot(center) - radius;
|
||||
|
||||
float unit = radius * 2.0 / texture_size;
|
||||
if (depth_range_mode==VS::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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -1069,6 +1117,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
}
|
||||
|
||||
{
|
||||
|
||||
|
||||
CameraMatrix 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;
|
||||
|
|
|
@ -233,6 +233,7 @@ public:
|
|||
|
||||
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)
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
|
|
|
@ -406,6 +406,14 @@ public:
|
|||
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;
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
virtual RID reflection_probe_create() = 0;
|
||||
|
|
Loading…
Reference in New Issue