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 {
|
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 ---///////
|
for(int i=0;i<8;i++) {
|
||||||
Plane near_plane = Plane(matrix[3] + matrix[2],
|
|
||||||
matrix[7] + matrix[6],
|
|
||||||
matrix[11] + matrix[10],
|
|
||||||
-matrix[15] - matrix[14]);
|
|
||||||
near_plane.normalize();
|
|
||||||
|
|
||||||
///////--- Far Plane ---///////
|
Vector3 point;
|
||||||
Plane far_plane = Plane(matrix[2] - matrix[3],
|
bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]],planes[intersections[i][2]], &point);
|
||||||
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);
|
|
||||||
ERR_FAIL_COND_V(!res, false);
|
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;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
|
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);
|
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 {
|
real_t CameraMatrix::get_fov() const {
|
||||||
const real_t *matrix = (const real_t *)this->matrix;
|
const real_t *matrix = (const real_t *)this->matrix;
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct CameraMatrix {
|
||||||
real_t get_z_near() const;
|
real_t get_z_near() const;
|
||||||
real_t get_aspect() const;
|
real_t get_aspect() const;
|
||||||
real_t get_fov() const;
|
real_t get_fov() const;
|
||||||
|
bool is_orthogonal() const;
|
||||||
|
|
||||||
Vector<Plane> get_projection_planes(const Transform &p_transform) const;
|
Vector<Plane> get_projection_planes(const Transform &p_transform) const;
|
||||||
|
|
||||||
|
@ -83,6 +84,7 @@ struct CameraMatrix {
|
||||||
Plane xform4(const Plane &p_vec4) const;
|
Plane xform4(const Plane &p_vec4) const;
|
||||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
|
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
|
||||||
|
|
||||||
|
|
||||||
operator String() const;
|
operator String() const;
|
||||||
|
|
||||||
void scale_translate_to_fit(const Rect3 &p_aabb);
|
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();
|
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));
|
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);
|
//_copy_texture_to_front_buffer(shadow_atlas->depth);
|
||||||
storage->canvas->canvas_begin();
|
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_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
|
||||||
light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
|
light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
|
||||||
light->directional_blend_splits = false;
|
light->directional_blend_splits = false;
|
||||||
|
light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
|
||||||
light->reverse_cull = false;
|
light->reverse_cull = false;
|
||||||
light->version = 0;
|
light->version = 0;
|
||||||
|
|
||||||
|
@ -4625,6 +4626,22 @@ VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_sha
|
||||||
return light->directional_shadow_mode;
|
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 {
|
VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
|
||||||
|
|
||||||
const Light *light = light_owner.getornull(p_light);
|
const Light *light = light_owner.getornull(p_light);
|
||||||
|
|
|
@ -879,6 +879,7 @@ public:
|
||||||
VS::LightOmniShadowMode omni_shadow_mode;
|
VS::LightOmniShadowMode omni_shadow_mode;
|
||||||
VS::LightOmniShadowDetail omni_shadow_detail;
|
VS::LightOmniShadowDetail omni_shadow_detail;
|
||||||
VS::LightDirectionalShadowMode directional_shadow_mode;
|
VS::LightDirectionalShadowMode directional_shadow_mode;
|
||||||
|
VS::LightDirectionalShadowDepthRangeMode directional_range_mode;
|
||||||
bool directional_blend_splits;
|
bool directional_blend_splits;
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
};
|
};
|
||||||
|
@ -906,6 +907,9 @@ public:
|
||||||
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
|
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
|
||||||
virtual VS::LightOmniShadowMode light_omni_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 bool light_has_shadow(RID p_light) const;
|
||||||
|
|
||||||
virtual VS::LightType light_get_type(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_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_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_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_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
|
||||||
ADD_GROUP("Editor", "");
|
ADD_GROUP("Editor", "");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
|
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;
|
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) {
|
void DirectionalLight::set_blend_splits(bool p_enable) {
|
||||||
|
|
||||||
blend_splits = 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("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("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("set_blend_splits", "enabled"), &DirectionalLight::set_blend_splits);
|
||||||
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled);
|
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_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_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_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_ORTHOGONAL);
|
||||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
|
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
|
||||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS);
|
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT( SHADOW_DEPTH_RANGE_STABLE );
|
||||||
|
BIND_ENUM_CONSTANT( SHADOW_DEPTH_RANGE_OPTIMIZED );
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectionalLight::DirectionalLight()
|
DirectionalLight::DirectionalLight()
|
||||||
|
@ -349,6 +368,8 @@ DirectionalLight::DirectionalLight()
|
||||||
set_param(PARAM_SHADOW_MAX_DISTANCE, 200);
|
set_param(PARAM_SHADOW_MAX_DISTANCE, 200);
|
||||||
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
|
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
|
||||||
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
|
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
|
||||||
|
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
|
||||||
|
|
||||||
|
|
||||||
blend_splits = false;
|
blend_splits = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,9 +133,15 @@ public:
|
||||||
SHADOW_PARALLEL_4_SPLITS
|
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:
|
private:
|
||||||
bool blend_splits;
|
bool blend_splits;
|
||||||
ShadowMode shadow_mode;
|
ShadowMode shadow_mode;
|
||||||
|
ShadowDepthRange shadow_depth_range;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
@ -144,6 +150,9 @@ public:
|
||||||
void set_shadow_mode(ShadowMode p_mode);
|
void set_shadow_mode(ShadowMode p_mode);
|
||||||
ShadowMode get_shadow_mode() const;
|
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);
|
void set_blend_splits(bool p_enable);
|
||||||
bool is_blend_splits_enabled() const;
|
bool is_blend_splits_enabled() const;
|
||||||
|
|
||||||
|
@ -151,6 +160,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(DirectionalLight::ShadowMode)
|
VARIANT_ENUM_CAST(DirectionalLight::ShadowMode)
|
||||||
|
VARIANT_ENUM_CAST(DirectionalLight::ShadowDepthRange)
|
||||||
|
|
||||||
class OmniLight : public Light {
|
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_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 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 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::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
|
||||||
virtual VS::LightOmniShadowMode light_omni_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_shadow_mode, RID, LightDirectionalShadowMode)
|
||||||
BIND2(light_directional_set_blend_splits, RID, bool)
|
BIND2(light_directional_set_blend_splits, RID, bool)
|
||||||
|
BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
|
||||||
|
|
||||||
/* PROBE API */
|
/* 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 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);
|
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 = MIN(shadow_max, max_distance);
|
||||||
}
|
}
|
||||||
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
|
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;
|
int splits = 0;
|
||||||
switch (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
|
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];
|
float distances[5];
|
||||||
|
|
||||||
distances[0] = p_cam_projection.get_z_near();
|
distances[0] = min_distance;
|
||||||
for (int i = 0; i < splits; i++) {
|
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;
|
distances[splits] = max_distance;
|
||||||
|
@ -984,8 +1027,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
||||||
|
|
||||||
{
|
{
|
||||||
//camera viewport stuff
|
//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;
|
Vector3 center;
|
||||||
|
|
||||||
|
@ -1006,7 +1047,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
||||||
radius = d;
|
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) {
|
if (i == 0) {
|
||||||
first_radius = radius;
|
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_max_cam = z_vec.dot(center) + radius;
|
||||||
z_min_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
|
//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;
|
CameraMatrix ortho_camera;
|
||||||
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
|
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
|
||||||
real_t half_y = (y_max_cam - y_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_shadow_mode, RID, LightDirectionalShadowMode)
|
||||||
FUNC2(light_directional_set_blend_splits, RID, bool)
|
FUNC2(light_directional_set_blend_splits, RID, bool)
|
||||||
|
FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
|
||||||
|
|
||||||
/* PROBE API */
|
/* 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_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0;
|
||||||
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 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 */
|
/* PROBE API */
|
||||||
|
|
||||||
virtual RID reflection_probe_create() = 0;
|
virtual RID reflection_probe_create() = 0;
|
||||||
|
|
Loading…
Reference in a new issue