Directional lights and shadow mapping are functional.
This commit is contained in:
parent
920db604d2
commit
88a7debbbc
|
@ -281,6 +281,7 @@ void Light::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
|
||||||
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
||||||
|
@ -325,8 +326,10 @@ Light::Light(VisualServer::LightType p_type) {
|
||||||
set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
|
set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
|
||||||
set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
|
set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
|
||||||
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
|
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
|
||||||
|
set_param(PARAM_SHADOW_FADE_START, 0.8);
|
||||||
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
|
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
|
||||||
set_param(PARAM_SHADOW_BIAS, 0.15);
|
set_param(PARAM_SHADOW_BIAS, 0.15);
|
||||||
|
set_param(PARAM_SHADOW_FADE_START, 1);
|
||||||
set_disable_scale(true);
|
set_disable_scale(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +396,7 @@ void DirectionalLight::_bind_methods() {
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
|
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
|
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
|
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
|
||||||
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);
|
||||||
|
@ -413,6 +417,7 @@ DirectionalLight::DirectionalLight() :
|
||||||
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
|
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
|
||||||
set_param(PARAM_SHADOW_BIAS, 0.1);
|
set_param(PARAM_SHADOW_BIAS, 0.1);
|
||||||
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
|
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
|
||||||
|
set_param(PARAM_SHADOW_FADE_START, 0.8);
|
||||||
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);
|
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
|
PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
|
||||||
PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
|
PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
|
||||||
PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
|
PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
|
||||||
|
PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START,
|
||||||
PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
||||||
PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
|
PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
|
||||||
PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
|
PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
|
||||||
|
|
|
@ -1377,6 +1377,66 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
||||||
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
|
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectionalLightData &light_data = scene_state.directional_lights[scene_state.ubo.directional_light_count];
|
||||||
|
|
||||||
|
Transform light_transform = light_instance_get_base_transform(li);
|
||||||
|
|
||||||
|
Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
|
||||||
|
|
||||||
|
light_data.direction[0] = direction.x;
|
||||||
|
light_data.direction[1] = direction.y;
|
||||||
|
light_data.direction[2] = direction.z;
|
||||||
|
|
||||||
|
float sign = storage->light_is_negative(base) ? -1 : 1;
|
||||||
|
|
||||||
|
light_data.energy = sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI;
|
||||||
|
|
||||||
|
Color linear_col = storage->light_get_color(base).to_linear();
|
||||||
|
light_data.color[0] = linear_col.r;
|
||||||
|
light_data.color[1] = linear_col.g;
|
||||||
|
light_data.color[2] = linear_col.b;
|
||||||
|
|
||||||
|
light_data.specular = storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR);
|
||||||
|
light_data.mask = storage->light_get_cull_mask(base);
|
||||||
|
|
||||||
|
Color shadow_col = storage->light_get_shadow_color(base).to_linear();
|
||||||
|
|
||||||
|
light_data.shadow_color[0] = shadow_col.r;
|
||||||
|
light_data.shadow_color[1] = shadow_col.g;
|
||||||
|
light_data.shadow_color[2] = shadow_col.b;
|
||||||
|
|
||||||
|
light_data.shadow_enabled = storage->light_has_shadow(base);
|
||||||
|
|
||||||
|
if (light_data.shadow_enabled) {
|
||||||
|
|
||||||
|
VS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
|
||||||
|
|
||||||
|
int limit = smode == VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
|
||||||
|
light_data.blend_splits = storage->light_directional_get_blend_splits(base);
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j);
|
||||||
|
CameraMatrix matrix = light_instance_get_shadow_camera(li, j);
|
||||||
|
float split = light_instance_get_directional_shadow_split(li, MIN(limit, j));
|
||||||
|
|
||||||
|
CameraMatrix bias;
|
||||||
|
bias.set_light_bias();
|
||||||
|
CameraMatrix rectm;
|
||||||
|
rectm.set_light_atlas_rect(atlas_rect);
|
||||||
|
|
||||||
|
Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse();
|
||||||
|
|
||||||
|
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
|
||||||
|
light_data.shadow_split_offsets[j] = split;
|
||||||
|
store_camera(shadow_mtx, light_data.shadow_matrices[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fade_start = storage->light_get_param(base, VS::LIGHT_PARAM_SHADOW_FADE_START);
|
||||||
|
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999);
|
||||||
|
light_data.fade_to = -light_data.shadow_split_offsets[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_state.ubo.directional_light_count++;
|
||||||
} break;
|
} break;
|
||||||
case VS::LIGHT_SPOT:
|
case VS::LIGHT_SPOT:
|
||||||
case VS::LIGHT_OMNI: {
|
case VS::LIGHT_OMNI: {
|
||||||
|
@ -1476,7 +1536,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_state.ubo.directional_light_count) {
|
if (scene_state.ubo.directional_light_count) {
|
||||||
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
|
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2092,7 +2152,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
|
||||||
|
|
||||||
storage->render_target_disable_clear_request(render_buffer->render_target);
|
storage->render_target_disable_clear_request(render_buffer->render_target);
|
||||||
|
|
||||||
if (true) {
|
if (false) {
|
||||||
if (p_shadow_atlas.is_valid()) {
|
if (p_shadow_atlas.is_valid()) {
|
||||||
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
|
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
|
||||||
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
|
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
|
||||||
|
@ -2101,6 +2161,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
if (directional_shadow_get_texture().is_valid()) {
|
||||||
|
RID shadow_atlas_texture = directional_shadow_get_texture();
|
||||||
|
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
|
||||||
|
|
||||||
|
effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
_post_process(env, p_cam_projection);
|
_post_process(env, p_cam_projection);
|
||||||
// Needed only for debugging
|
// Needed only for debugging
|
||||||
|
|
|
@ -235,16 +235,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
|
||||||
float energy;
|
float energy;
|
||||||
float color[3];
|
float color[3];
|
||||||
float specular;
|
float specular;
|
||||||
uint32_t mask;
|
|
||||||
uint32_t pad[3];
|
|
||||||
float shadow_color[3];
|
float shadow_color[3];
|
||||||
|
uint32_t mask;
|
||||||
|
uint32_t blend_splits;
|
||||||
uint32_t shadow_enabled;
|
uint32_t shadow_enabled;
|
||||||
float shadow_atlas_rect[4];
|
float fade_from;
|
||||||
|
float fade_to;
|
||||||
float shadow_split_offsets[4];
|
float shadow_split_offsets[4];
|
||||||
float shadow_matrix1[16];
|
float shadow_matrices[4][16];
|
||||||
float shadow_matrix2[16];
|
|
||||||
float shadow_matrix3[16];
|
|
||||||
float shadow_matrix4[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstanceData {
|
struct InstanceData {
|
||||||
|
|
|
@ -898,6 +898,8 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
directional_shadow.size = p_size;
|
||||||
|
|
||||||
if (directional_shadow.depth.is_valid()) {
|
if (directional_shadow.depth.is_valid()) {
|
||||||
RD::get_singleton()->free(directional_shadow.depth);
|
RD::get_singleton()->free(directional_shadow.depth);
|
||||||
directional_shadow.depth = RID();
|
directional_shadow.depth = RID();
|
||||||
|
@ -925,17 +927,34 @@ void RasterizerSceneRD::set_directional_shadow_count(int p_count) {
|
||||||
directional_shadow.current_light = 0;
|
directional_shadow.current_light = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
|
||||||
|
|
||||||
|
int split_h = 1;
|
||||||
|
int split_v = 1;
|
||||||
|
|
||||||
|
while (split_h * split_v < p_shadow_count) {
|
||||||
|
if (split_h == split_v) {
|
||||||
|
split_h <<= 1;
|
||||||
|
} else {
|
||||||
|
split_v <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect2i rect(0, 0, p_size, p_size);
|
||||||
|
rect.size.width /= split_h;
|
||||||
|
rect.size.height /= split_v;
|
||||||
|
|
||||||
|
rect.position.x = rect.size.width * (p_shadow_index % split_h);
|
||||||
|
rect.position.y = rect.size.height * (p_shadow_index / split_h);
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
|
int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
|
ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
|
||||||
|
|
||||||
int shadow_size;
|
Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
|
||||||
|
|
||||||
if (directional_shadow.light_count == 1) {
|
|
||||||
shadow_size = directional_shadow.size;
|
|
||||||
} else {
|
|
||||||
shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
|
|
||||||
}
|
|
||||||
|
|
||||||
LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
|
LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
|
||||||
ERR_FAIL_COND_V(!light_instance, 0);
|
ERR_FAIL_COND_V(!light_instance, 0);
|
||||||
|
@ -943,11 +962,11 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
|
||||||
switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
|
switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
|
||||||
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
|
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
|
||||||
break; //none
|
break; //none
|
||||||
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
|
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break;
|
||||||
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break;
|
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shadow_size;
|
return MAX(r.size.width, r.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
|
@ -1112,27 +1131,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
|
||||||
if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) {
|
if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) {
|
||||||
//set pssm stuff
|
//set pssm stuff
|
||||||
if (light_instance->last_scene_shadow_pass != scene_pass) {
|
if (light_instance->last_scene_shadow_pass != scene_pass) {
|
||||||
//assign rect if unassigned
|
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
|
||||||
light_instance->light_directional_index = directional_shadow.current_light;
|
|
||||||
light_instance->last_scene_shadow_pass = scene_pass;
|
|
||||||
directional_shadow.current_light++;
|
directional_shadow.current_light++;
|
||||||
|
light_instance->last_scene_shadow_pass = scene_pass;
|
||||||
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.x += light_instance->directional_rect.size.x;
|
|
||||||
}
|
|
||||||
} else { //3 and 4
|
|
||||||
light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2);
|
|
||||||
if (light_instance->light_directional_index & 1) {
|
|
||||||
light_instance->directional_rect.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_projection = light_instance->shadow_transform[p_pass].camera;
|
||||||
|
@ -1168,6 +1169,11 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
|
||||||
|
|
||||||
|
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
|
||||||
|
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
|
||||||
|
|
||||||
float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
|
float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
|
||||||
zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
|
zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
|
||||||
bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
|
bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
|
||||||
|
|
|
@ -180,6 +180,7 @@ private:
|
||||||
float farplane;
|
float farplane;
|
||||||
float split;
|
float split;
|
||||||
float bias_scale;
|
float bias_scale;
|
||||||
|
Rect2 atlas_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
VS::LightType light_type;
|
VS::LightType light_type;
|
||||||
|
@ -409,6 +410,24 @@ public:
|
||||||
return li->shadow_transform[p_index].camera;
|
return li->shadow_transform[p_index].camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
|
||||||
|
|
||||||
|
LightInstance *li = light_instance_owner.getornull(p_light_instance);
|
||||||
|
return li->shadow_transform[p_index].transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
|
||||||
|
|
||||||
|
LightInstance *li = light_instance_owner.getornull(p_light_instance);
|
||||||
|
return li->shadow_transform[p_index].atlas_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
|
||||||
|
|
||||||
|
LightInstance *li = light_instance_owner.getornull(p_light_instance);
|
||||||
|
return li->shadow_transform[p_index].split;
|
||||||
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
|
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
|
||||||
LightInstance *li = light_instance_owner.getornull(p_light_instance);
|
LightInstance *li = light_instance_owner.getornull(p_light_instance);
|
||||||
li->last_pass = p_pass;
|
li->last_pass = p_pass;
|
||||||
|
|
|
@ -2104,6 +2104,7 @@ RID RasterizerStorageRD::light_create(VS::LightType p_type) {
|
||||||
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
|
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
|
||||||
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
|
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
|
||||||
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
|
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
|
||||||
|
light.param[VS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
|
||||||
light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
|
light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
|
||||||
light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
|
light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,11 @@ LIGHT_SHADER_CODE
|
||||||
|
|
||||||
#ifndef USE_NO_SHADOWS
|
#ifndef USE_NO_SHADOWS
|
||||||
|
|
||||||
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
|
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
|
||||||
|
|
||||||
|
//todo optimize
|
||||||
|
vec2 pos = coord.xy;
|
||||||
|
float depth = coord.z;
|
||||||
|
|
||||||
#ifdef SHADOW_MODE_PCF_13
|
#ifdef SHADOW_MODE_PCF_13
|
||||||
|
|
||||||
|
@ -657,7 +661,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||||
if (shadow_color_enabled.w > 0.5) {
|
if (shadow_color_enabled.w > 0.5) {
|
||||||
// there is a shadowmap
|
// there is a shadowmap
|
||||||
|
|
||||||
vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
|
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
||||||
float shadow_len = length(splane);
|
float shadow_len = length(splane);
|
||||||
splane = normalize(splane);
|
splane = normalize(splane);
|
||||||
vec4 clamp_rect = lights.data[idx].atlas_rect;
|
vec4 clamp_rect = lights.data[idx].atlas_rect;
|
||||||
|
@ -677,9 +681,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||||
splane.xy /= splane.z;
|
splane.xy /= splane.z;
|
||||||
splane.xy = splane.xy * 0.5 + 0.5;
|
splane.xy = splane.xy * 0.5 + 0.5;
|
||||||
splane.z = shadow_len * lights.data[idx].inv_radius;
|
splane.z = shadow_len * lights.data[idx].inv_radius;
|
||||||
|
|
||||||
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
|
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
|
||||||
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
|
splane.w = 1.0; //needed? i think it should be 1 already
|
||||||
|
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
|
||||||
|
|
||||||
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||||
}
|
}
|
||||||
|
@ -750,9 +754,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||||
if (shadow_color_enabled.w > 0.5) {
|
if (shadow_color_enabled.w > 0.5) {
|
||||||
//there is a shadowmap
|
//there is a shadowmap
|
||||||
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
||||||
splane.xyz /= splane.w;
|
splane /= splane.w;
|
||||||
|
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
|
||||||
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
|
|
||||||
|
|
||||||
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1135,84 @@ FRAGMENT_SHADER_CODE
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//directional light
|
{ //directional light
|
||||||
|
|
||||||
|
for (uint i = 0; i < scene_data.directional_light_count; i++) {
|
||||||
|
|
||||||
|
if (!bool(directional_lights.data[i].mask&instances.data[instance_index].layer_mask)) {
|
||||||
|
continue; //not masked
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 light_attenuation = vec3(1.0);
|
||||||
|
|
||||||
|
if (directional_lights.data[i].shadow_enabled) {
|
||||||
|
float depth_z = -vertex.z;
|
||||||
|
|
||||||
|
vec4 pssm_coord;
|
||||||
|
|
||||||
|
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
|
||||||
|
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
|
||||||
|
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
|
||||||
|
} else {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
pssm_coord/=pssm_coord.w;
|
||||||
|
|
||||||
|
float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
|
||||||
|
|
||||||
|
if (directional_lights.data[i].blend_splits) {
|
||||||
|
|
||||||
|
float pssm_blend;
|
||||||
|
|
||||||
|
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
|
||||||
|
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
|
||||||
|
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
|
||||||
|
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
|
||||||
|
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||||
|
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
|
||||||
|
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
|
||||||
|
} else {
|
||||||
|
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
|
||||||
|
}
|
||||||
|
|
||||||
|
pssm_coord/=pssm_coord.w;
|
||||||
|
|
||||||
|
float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
|
||||||
|
shadow = mix(shadow,shadow2,pssm_blend);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow = mix(shadow,1.0,smoothstep(directional_lights.data[i].fade_from,directional_lights.data[i].fade_to,vertex.z)); //done with negative values for performance
|
||||||
|
|
||||||
|
light_attenuation = vec3(shadow); //mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular,directional_lights.data[i].specular * specular_blob_intensity,
|
||||||
|
#ifdef LIGHT_TRANSMISSION_USED
|
||||||
|
transmission,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_RIM_USED
|
||||||
|
rim * omni_attenuation, rim_tint,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_CLEARCOAT_USED
|
||||||
|
clearcoat, clearcoat_gloss,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_ANISOTROPY_USED
|
||||||
|
binormal, tangent, anisotropy,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SHADOW_TO_OPACITY
|
||||||
|
alpha
|
||||||
|
#endif
|
||||||
|
diffuse_light, specular_light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{ //omni lights
|
{ //omni lights
|
||||||
uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
|
uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
|
||||||
|
|
|
@ -184,11 +184,12 @@ struct DirectionalLightData {
|
||||||
float energy;
|
float energy;
|
||||||
vec3 color;
|
vec3 color;
|
||||||
float specular;
|
float specular;
|
||||||
uint mask;
|
|
||||||
uint pad0,pad1,pad2;
|
|
||||||
vec3 shadow_color;
|
vec3 shadow_color;
|
||||||
|
uint mask;
|
||||||
|
bool blend_splits;
|
||||||
bool shadow_enabled;
|
bool shadow_enabled;
|
||||||
vec4 shadow_atlas_rect;
|
float fade_from;
|
||||||
|
float fade_to;
|
||||||
vec4 shadow_split_offsets;
|
vec4 shadow_split_offsets;
|
||||||
mat4 shadow_matrix1;
|
mat4 shadow_matrix1;
|
||||||
mat4 shadow_matrix2;
|
mat4 shadow_matrix2;
|
||||||
|
|
|
@ -2047,6 +2047,7 @@ void VisualServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
|
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_2_OFFSET);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
||||||
|
|
|
@ -404,6 +404,7 @@ public:
|
||||||
LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
|
LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
|
||||||
LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
|
LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
|
||||||
LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
|
LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
|
||||||
|
LIGHT_PARAM_SHADOW_FADE_START,
|
||||||
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
||||||
LIGHT_PARAM_SHADOW_BIAS,
|
LIGHT_PARAM_SHADOW_BIAS,
|
||||||
LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
|
LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
|
||||||
|
|
Loading…
Reference in New Issue