1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-12 13:20:55 +00:00

Refactored shadowmapping.

- Made shadow bias size independent, so it will remain when changing light or camera size.
- Implemented normal offset bias, which greatly enhances quality.
- Added transmission to subsurface scattering
- Reimplemented shadow filter modes

Closes #17260
This commit is contained in:
Juan Linietsky
2020-04-07 22:51:52 -03:00
parent b2f79cac9a
commit 4ffc0d6b3f
34 changed files with 1032 additions and 291 deletions

View File

@@ -170,17 +170,15 @@ public:
_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
} break;
case LIGHT_TYPE_SPOT: {
Vector3 v(0, 0, -1);
v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z
v.normalize();
v *= ld.radius;
v.y = v.x;
float r = ld.radius;
real_t len = Math::tan(Math::deg2rad(ld.spot_aperture)) * r;
aabb.position = xform.origin;
aabb.expand_to(xform.xform(v));
aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z)));
aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z)));
aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z)));
aabb.expand_to(xform.xform(Vector3(len, len, -r)));
aabb.expand_to(xform.xform(Vector3(-len, len, -r)));
aabb.expand_to(xform.xform(Vector3(-len, -len, -r)));
aabb.expand_to(xform.xform(Vector3(len, -len, -r)));
_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
} break;
}

View File

@@ -204,6 +204,25 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1
return uniform_set;
}
void RasterizerEffectsRD::copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
if (p_flip_y) {
blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
}
blur.push_constant.camera_z_near = p_z_near;
blur.push_constant.camera_z_far = p_z_far;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_LINEARIZE_DEPTH].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -1127,6 +1146,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
blur_modes.push_back("\n#define MODE_MIPMAP\n");
blur_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
blur.shader.initialize(blur_modes);
zeromem(&blur.push_constant, sizeof(BlurPushConstant));

View File

@@ -71,6 +71,7 @@ class RasterizerEffectsRD {
BLUR_MODE_SSAO_MERGE,
BLUR_MODE_SIMPLY_COPY,
BLUR_MODE_MIPMAP,
BLUR_MODE_LINEARIZE_DEPTH,
BLUR_MODE_MAX,
};
@@ -540,6 +541,7 @@ public:
void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
void copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);

View File

@@ -109,6 +109,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
unshaded = false;
uses_vertex = false;
uses_sss = false;
uses_transmittance = false;
uses_screen_texture = false;
uses_depth_texture = false;
uses_normal_texture = false;
@@ -142,6 +143,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
@@ -944,7 +946,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) {
void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -960,6 +962,9 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.z_far = p_zfar;
scene_state.ubo.z_near = p_znear;
scene_state.ubo.shadow_filter_mode = shadow_filter_get();
scene_state.ubo.pancake_shadows = p_pancake_shadows;
scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
@@ -1481,9 +1486,43 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
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;
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
light_data.shadow_color1[0] = 1.0;
light_data.shadow_color1[1] = 0.0;
light_data.shadow_color1[2] = 0.0;
light_data.shadow_color1[3] = 1.0;
light_data.shadow_color2[0] = 0.0;
light_data.shadow_color2[1] = 1.0;
light_data.shadow_color2[2] = 0.0;
light_data.shadow_color2[3] = 1.0;
light_data.shadow_color3[0] = 0.0;
light_data.shadow_color3[1] = 0.0;
light_data.shadow_color3[2] = 1.0;
light_data.shadow_color3[3] = 1.0;
light_data.shadow_color4[0] = 1.0;
light_data.shadow_color4[1] = 1.0;
light_data.shadow_color4[2] = 0.0;
light_data.shadow_color4[3] = 1.0;
} else {
light_data.shadow_color1[0] = shadow_col.r;
light_data.shadow_color1[1] = shadow_col.g;
light_data.shadow_color1[2] = shadow_col.b;
light_data.shadow_color1[3] = 1.0;
light_data.shadow_color2[0] = shadow_col.r;
light_data.shadow_color2[1] = shadow_col.g;
light_data.shadow_color2[2] = shadow_col.b;
light_data.shadow_color2[3] = 1.0;
light_data.shadow_color3[0] = shadow_col.r;
light_data.shadow_color3[1] = shadow_col.g;
light_data.shadow_color3[2] = shadow_col.b;
light_data.shadow_color3[3] = 1.0;
light_data.shadow_color4[0] = shadow_col.r;
light_data.shadow_color4[1] = shadow_col.g;
light_data.shadow_color4[2] = shadow_col.b;
light_data.shadow_color4[3] = 1.0;
}
light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
@@ -1507,6 +1546,11 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = light_instance_get_shadow_bias_scale(li, j);
light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale;
light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * light_instance_get_directional_shadow_texel_size(li, j);
light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
light_data.shadow_transmittance_z_scale[j] = light_instance_get_shadow_range(li, j);
store_camera(shadow_mtx, light_data.shadow_matrices[j]);
}
@@ -1581,14 +1625,6 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.mask = storage->light_get_cull_mask(base);
Color shadow_color = storage->light_get_shadow_color(base);
bool has_shadow = p_using_shadows && storage->light_has_shadow(base);
light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
light_data.atlas_rect[0] = 0;
light_data.atlas_rect[1] = 0;
light_data.atlas_rect[2] = 0;
@@ -1597,6 +1633,27 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
// fill in the shadow information
Color shadow_color = storage->light_get_shadow_color(base);
light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
light_data.shadow_color_enabled[3] = 255;
if (type == RS::LIGHT_SPOT) {
light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
shadow_texel_size *= light_instance_get_shadow_texel_size(li, p_shadow_atlas);
light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
} else { //omni
light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
float shadow_texel_size = light_instance_get_shadow_texel_size(li, p_shadow_atlas);
light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
}
light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
if (type == RS::LIGHT_OMNI) {
@@ -1620,6 +1677,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
store_camera(shadow_mtx, light_data.shadow_matrix);
}
} else {
light_data.shadow_color_enabled[3] = 0;
}
light_instance_set_index(li, light_count);
@@ -1698,9 +1757,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
scene_state.ubo.shadow_z_offset = 0;
scene_state.ubo.shadow_z_slope_scale = 0;
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
@@ -2063,7 +2119,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
//disable all stuff
#endif
}
void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) {
void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake) {
RENDER_TIMESTAMP("Setup Rendering Shadow");
@@ -2071,11 +2127,9 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **
render_pass++;
scene_state.ubo.shadow_z_offset = p_bias;
scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar);
_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake);
render_list.clear();
@@ -2106,8 +2160,6 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform
render_pass++;
scene_state.ubo.shadow_z_offset = 0;
scene_state.ubo.shadow_z_slope_scale = 0;
scene_state.ubo.dual_paraboloid_side = 0;
_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
@@ -2204,7 +2256,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 5;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.light_buffer);
uniforms.push_back(u);
}
@@ -2463,11 +2515,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
}
{ //lights
scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
scene_state.max_lights = MIN(1024 * 1024, uniform_max_size) / sizeof(LightData); //1mb of lights
uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
scene_state.light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
//defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
scene_state.max_directional_lights = 8;
uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
@@ -2569,7 +2621,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.renames["ANISOTROPY"] = "anisotropy";
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
actions.renames["SSS_STRENGTH"] = "sss_strength";
actions.renames["TRANSMISSION"] = "transmission";
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
actions.renames["BACKLIGHT"] = "backlight";
actions.renames["AO"] = "ao";
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions.renames["EMISSION"] = "emission";
@@ -2609,7 +2665,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";

View File

@@ -138,6 +138,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
bool unshaded;
bool uses_vertex;
bool uses_sss;
bool uses_transmittance;
bool uses_screen_texture;
bool uses_depth_texture;
bool uses_normal_texture;
@@ -260,6 +261,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
float shadow_bias;
float shadow_normal_bias;
float transmittance_bias;
uint32_t pad;
};
struct DirectionalLightData {
@@ -268,14 +273,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float energy;
float color[3];
float specular;
float shadow_color[3];
uint32_t mask;
uint32_t pad[3];
uint32_t blend_splits;
uint32_t shadow_enabled;
float fade_from;
float fade_to;
float shadow_bias[4];
float shadow_normal_bias[4];
float shadow_transmittance_bias[4];
float shadow_transmittance_z_scale[4];
float shadow_split_offsets[4];
float shadow_matrices[4][16];
float shadow_color1[4];
float shadow_color2[4];
float shadow_color3[4];
float shadow_color4[4];
};
struct GIProbeData {
@@ -324,12 +337,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float viewport_size[2];
float screen_pixel_size[2];
float shadow_z_offset;
float shadow_z_slope_scale;
float time;
float reflection_multiplier;
uint32_t pancake_shadows;
uint32_t shadow_filter_mode;
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -558,7 +571,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
PASS_MODE_DEPTH_MATERIAL,
};
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false);
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
@@ -572,7 +585,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
protected:
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
public:

View File

@@ -2032,7 +2032,7 @@ void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const
light_instance->transform = p_transform;
}
void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -2048,6 +2048,7 @@ void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance
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;
light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;
}
void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
@@ -3580,6 +3581,10 @@ void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_
sss_depth_scale = p_depth_scale;
}
void RasterizerSceneRD::shadow_filter_set(RS::ShadowFilter p_filter) {
shadow_filter = p_filter;
}
int RasterizerSceneRD::get_roughness_layers() const {
return roughness_layers;
}
@@ -3625,12 +3630,15 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
bool using_dual_paraboloid = false;
bool using_dual_paraboloid_flip = false;
float znear = 0;
float zfar = 0;
RID render_fb;
RID render_texture;
float bias = 0;
float normal_bias = 0;
bool use_pancake = false;
bool use_linear_depth = false;
bool render_cubemap = false;
bool finalize_cubemap = false;
@@ -3645,6 +3653,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
light_instance->last_scene_shadow_pass = scene_pass;
}
use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
light_projection = light_instance->shadow_transform[p_pass].camera;
light_transform = light_instance->shadow_transform[p_pass].transform;
@@ -3683,7 +3692,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
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, RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
float bias_mult = light_instance->shadow_transform[p_pass].bias_scale;
zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
@@ -3762,26 +3771,33 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
render_fb = shadow_map->fb;
render_texture = shadow_map->depth;
znear = light_instance->shadow_transform[0].camera.get_z_near();
use_linear_depth = true;
}
}
if (render_cubemap) {
//rendering to cubemap
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false);
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake);
if (finalize_cubemap) {
//reblit
atlas_rect.size.height /= 2;
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false);
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
atlas_rect.position.y += atlas_rect.size.height;
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true);
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
}
} else {
//render shadow
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip);
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake);
//copy to atlas
storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
if (use_linear_depth) {
storage->get_effects()->copy_to_rect_and_linearize(render_texture, atlas_fb, atlas_rect, true, znear, zfar);
} else {
storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
}
//does not work from depth to color
//RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
@@ -4137,6 +4153,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
}
RasterizerSceneRD::~RasterizerSceneRD() {

View File

@@ -79,7 +79,7 @@ protected:
virtual RenderBufferData *_create_render_buffer_data() = 0;
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0;
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
@@ -527,6 +527,8 @@ private:
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
RS::ShadowFilter shadow_filter = RS::SHADOW_FILTER_NONE;
/* DIRECTIONAL SHADOW */
struct DirectionalShadow {
@@ -570,6 +572,7 @@ private:
float farplane;
float split;
float bias_scale;
float shadow_texel_size;
Rect2 atlas_rect;
};
@@ -880,7 +883,7 @@ public:
RID light_instance_create(RID p_light);
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0);
void light_instance_mark_visible(RID p_light_instance);
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -926,11 +929,44 @@ public:
return li->shadow_transform[p_index].camera;
}
_FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
_FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
#ifdef DEBUG_ENABLED
LightInstance *li = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
#endif
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
ERR_FAIL_COND_V(!shadow_atlas, 0);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
#endif
uint32_t key = shadow_atlas->shadow_owners[p_light_instance];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
uint32_t quadrant_size = shadow_atlas->size >> 1;
uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
return float(1.0) / shadow_size;
}
_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_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].bias_scale;
}
_FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].farplane;
}
_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
@@ -944,6 +980,12 @@ public:
return li->shadow_transform[p_index].split;
}
_FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].shadow_texel_size;
}
_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);
li->last_pass = p_pass;
@@ -1107,8 +1149,12 @@ public:
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
_FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
virtual void set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
}
_FORCE_INLINE_ uint64_t get_scene_pass() {
return scene_pass;
}
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
virtual bool screen_space_roughness_limiter_is_active() const;
@@ -1118,6 +1164,9 @@ public:
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
virtual void shadow_filter_set(RS::ShadowFilter p_filter);
_FORCE_INLINE_ RS::ShadowFilter shadow_filter_get() const { return shadow_filter; }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
@@ -1126,7 +1175,9 @@ public:
virtual void update();
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; }
_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const {
return debug_draw;
}
virtual void set_time(double p_time, double p_step);

View File

@@ -3105,14 +3105,15 @@ RID RasterizerStorageRD::light_create(RS::LightType p_type) {
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_FADE_START] = 0.8;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
return light_owner.make_rid(light);
}
@@ -3138,6 +3139,7 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f
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_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;

View File

@@ -926,6 +926,14 @@ public:
return light->negative;
}
_FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0.0);
return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
}
bool light_get_use_gi(RID p_light);
uint64_t light_get_version(RID p_light) const;

View File

@@ -285,6 +285,13 @@ void main() {
frag_color = color;
#endif
#ifdef MODE_LINEARIZE_DEPTH_COPY
float depth = texture(source_color, uv_interp, 0.0).r;
depth = depth * 2.0 - 1.0;
depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
frag_color = vec4(depth / blur.camera_z_far);
#endif
#ifdef MODE_SSAO_MERGE
vec4 color = texture(source_color, uv_interp, 0.0);
float ssao = texture(source_ssao, uv_interp, 0.0).r;

View File

@@ -57,6 +57,7 @@ void main() {
}
float depth = texture(source_cube, normal).r;
depth_buffer = depth;
// absolute values for direction cosines, bigger value equals closer to basis axis
vec3 unorm = abs(normal);
@@ -80,7 +81,7 @@ void main() {
depth = 2.0 * depth - 1.0;
float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
depth_buffer = (linear_depth * depth_fix) / params.z_far;
#endif
}

View File

@@ -244,19 +244,13 @@ VERTEX_SHADER_CODE
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
vec3 vtx = vertex_interp;
float distance = length(vtx);
vtx = normalize(vtx);
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
vertex_interp = vtx;
#else
float z_ofs = scene_data.z_offset;
z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale;
vertex_interp.z -= z_ofs;
#endif
@@ -267,6 +261,14 @@ VERTEX_SHADER_CODE
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
#ifdef MODE_RENDER_DEPTH
if (scene_data.pancake_shadows) {
if (gl_Position.z <= 0.00001) {
gl_Position.z = 0.00001;
}
}
#endif
}
/* clang-format off */
@@ -315,6 +317,11 @@ layout(location = 8) in float dp_clip;
#define world_normal_matrix instances.data[instance_index].normal_transform
#define projection_matrix scene_data.projection_matrix
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
//both required for transmittance to be enabled
#define LIGHT_TRANSMITTANCE_USED
#endif
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
@@ -434,9 +441,16 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
float transmittance_curve,
float transmittance_boost,
float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -538,16 +552,48 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
#if defined(LIGHT_TRANSMISSION_USED)
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
#if defined(LIGHT_BACKLIGHT_USED)
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
#endif
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
#ifdef SSS_MODE_SKIN
{
float scale = 8.25 / transmittance_depth;
float d = scale * abs(transmittance_z);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
}
#else
if (transmittance_depth > 0.0) {
float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
}
#endif //SSS_MODE_SKIN
#endif //LIGHT_TRANSMITTANCE_USED
}
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
@@ -562,7 +608,7 @@ LIGHT_SHADER_CODE
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = blinn;
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_PHONG)
@@ -573,7 +619,7 @@ LIGHT_SHADER_CODE
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_TOON)
@@ -582,7 +628,7 @@ LIGHT_SHADER_CODE
float mid = 1.0 - roughness;
mid *= mid;
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
#elif defined(SPECULAR_DISABLED)
// none..
@@ -613,7 +659,7 @@ LIGHT_SHADER_CODE
vec3 specular_brdf_NL = cNdotL * D * F * G;
specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
#if defined(LIGHT_CLEARCOAT_USED)
@@ -627,12 +673,12 @@ LIGHT_SHADER_CODE
float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
}
#ifdef USE_SHADOW_TO_OPACITY
alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
#endif
#endif //defined(USE_LIGHT_SHADER_CODE)
@@ -642,51 +688,54 @@ LIGHT_SHADER_CODE
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
switch (scene_data.shadow_filter_mode) {
case SHADOW_MODE_NO_FILTER: {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
};
case SHADOW_MODE_PCF5: {
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
return avg * (1.0 / 5.0);
};
case SHADOW_MODE_PCF13: {
float avg = textureProj(shadow, vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
return avg * (1.0 / 13.0);
#endif
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
return avg * (1.0 / 13.0);
};
}
#ifdef SHADOW_MODE_PCF_5
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
return avg * (1.0 / 5.0);
#endif
#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
#endif
return 0;
}
#endif //USE_NO_SHADOWS
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
float transmittance_curve,
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -707,18 +756,33 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float normalized_distance = light_length * lights.data[idx].inv_radius;
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
vec3 light_attenuation = vec3(omni_attenuation);
float light_attenuation = omni_attenuation;
vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth; //no transmittance by default
#endif
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
// there is a shadowmap
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
float shadow_len = length(splane);
splane = normalize(splane);
vec4 v = vec4(vertex, 1.0);
vec4 splane = (lights.data[idx].shadow_matrix * v);
float shadow_len = length(splane.xyz);
{
vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
v.xyz += nofs;
splane = (lights.data[idx].shadow_matrix * v);
}
splane.xyz = normalize(splane.xyz);
vec4 clamp_rect = lights.data[idx].atlas_rect;
if (splane.z >= 0.0) {
@@ -728,24 +792,60 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
clamp_rect.y += clamp_rect.w;
} else {
splane.z = 1.0 - splane.z;
}
splane.xy /= splane.z;
splane.xy = splane.xy * 0.5 + 0.5;
splane.z = shadow_len * lights.data[idx].inv_radius;
splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
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);
#ifdef LIGHT_TRANSMITTANCE_USED
{
//redo shadowmapping, but shrink the model a bit to avoid arctifacts
splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
shadow_len = length(splane);
splane = normalize(splane);
if (splane.z >= 0.0) {
splane.z += 1.0;
} else {
splane.z = 1.0 - splane.z;
}
splane.xy /= splane.z;
splane.xy = splane.xy * 0.5 + 0.5;
splane.z = shadow_len * lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
splane.w = 1.0; //needed? i think it should be 1 already
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
}
#endif
shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
}
#endif //USE_NO_SHADOWS
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
@@ -764,8 +864,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
}
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
float transmittance_curve,
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -792,7 +898,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
vec3 light_attenuation = vec3(spot_attenuation);
float light_attenuation = spot_attenuation;
vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
@@ -801,22 +908,58 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
//use projector texture
}
*/
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
#endif
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
//there is a shadowmap
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
v.xyz -= spot_dir * lights.data[idx].shadow_bias;
float depth_bias_scale = 1.0 / (max(0.0001, dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius)); //the closer to the light origin, the more you have to offset to reach 1px in the map
vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
v.xyz += normal_bias;
vec4 splane = (lights.data[idx].shadow_matrix * v);
splane /= splane.w;
splane.z = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
#ifdef LIGHT_TRANSMITTANCE_USED
{
splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
splane /= splane.w;
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
//reconstruct depth
shadow_z / lights.data[idx].inv_radius;
//distance to light plane
float z = dot(spot_dir, -light_rel_vec);
transmittance_z = z - shadow_z;
}
#endif //LIGHT_TRANSMITTANCE_USED
}
#endif //USE_NO_SHADOWS
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * spot_attenuation, rim_tint,
@@ -1185,7 +1328,11 @@ void main() {
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
vec3 transmission = vec3(0.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0);
float transmittance_depth = 0.0;
float transmittance_curve = 1.0;
float transmittance_boost = 0.0;
float metallic = 0.0;
float specular = 0.5;
vec3 emission = vec3(0.0);
@@ -1254,6 +1401,14 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
}
#if defined(LIGHT_TRANSMITTANCE_USED)
#ifdef SSS_MODE_SKIN
transmittance_color.a = sss_strength;
#else
transmittance_color.a *= sss_strength;
#endif
#endif
#if !defined(USE_SHADOW_TO_OPACITY)
#if defined(ALPHA_SCISSOR_USED)
@@ -1462,21 +1617,109 @@ FRAGMENT_SHADER_CODE
continue; //not masked
}
vec3 light_attenuation = vec3(1.0);
vec3 shadow_attenuation = vec3(1.0);
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
#endif
if (directional_lights.data[i].shadow_enabled) {
float depth_z = -vertex.z;
vec4 pssm_coord;
vec3 shadow_color = vec3(0.0);
vec3 light_dir = directional_lights.data[i].direction;
#define BIAS_FUNC(m_var, m_idx) \
m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 0)
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
shadow_color = directional_lights.data[i].shadow_color1.rgb;
#ifdef LIGHT_TRANSMITTANCE_USED
{
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
transmittance_z = z - shadow_z;
}
#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
shadow_color = directional_lights.data[i].shadow_color2.rgb;
#ifdef LIGHT_TRANSMITTANCE_USED
{
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
transmittance_z = z - shadow_z;
}
#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
shadow_color = directional_lights.data[i].shadow_color3.rgb;
#ifdef LIGHT_TRANSMITTANCE_USED
{
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
transmittance_z = z - shadow_z;
}
#endif
} else {
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
shadow_color = directional_lights.data[i].shadow_color4.rgb;
#ifdef LIGHT_TRANSMITTANCE_USED
{
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
transmittance_z = z - shadow_z;
}
#endif
}
pssm_coord /= pssm_coord.w;
@@ -1485,17 +1728,27 @@ FRAGMENT_SHADER_CODE
if (directional_lights.data[i].blend_splits) {
vec3 shadow_color_blend = vec3(0.0);
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));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
@@ -1504,16 +1757,26 @@ FRAGMENT_SHADER_CODE
float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
shadow_color = mix(shadow_color, shadow_color_blend, 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 = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
#undef BIAS_FUNC
}
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,
light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim, rim_tint,
@@ -1546,8 +1809,14 @@ FRAGMENT_SHADER_CODE
}
light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
transmittance_curve,
transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1579,8 +1848,14 @@ FRAGMENT_SHADER_CODE
}
light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
transmittance_curve,
transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,

View File

@@ -22,6 +22,10 @@ draw_call;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
#define SHADOW_MODE_NO_FILTER 0
#define SHADOW_MODE_PCF5 1
#define SHADOW_MODE_PCF13 2
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
@@ -37,13 +41,12 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
vec2 viewport_size;
vec2 screen_pixel_size;
//used for shadow mapping only
float z_offset;
float z_slope_scale;
float time;
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
uint shadow_filter_mode;
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
@@ -134,7 +137,7 @@ layout(set = 0, binding = 4, std430) buffer Instances {
}
instances;
struct LightData { //this structure needs to be 128 bits
struct LightData { //this structure needs to be as packed as possible
vec3 position;
float inv_radius;
vec3 direction;
@@ -143,12 +146,16 @@ struct LightData { //this structure needs to be 128 bits
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
uint mask;
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
vec4 atlas_rect; // used for spot
mat4 shadow_matrix;
float shadow_bias;
float shadow_normal_bias;
float transmittance_bias;
uint pad;
};
layout(set = 0, binding = 5, std140) uniform Lights {
LightData data[MAX_LIGHT_DATA_STRUCTS];
layout(set = 0, binding = 5, std430) buffer Lights {
LightData data[];
}
lights;
@@ -174,17 +181,27 @@ struct DirectionalLightData {
float energy;
vec3 color;
float specular;
vec3 shadow_color;
uint mask;
uint pad0;
uint pad1;
uint pad2;
bool blend_splits;
bool shadow_enabled;
float fade_from;
float fade_to;
vec4 shadow_bias;
vec4 shadow_normal_bias;
vec4 shadow_transmittance_bias;
vec4 shadow_transmittance_z_scale;
vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
vec4 shadow_color1;
vec4 shadow_color2;
vec4 shadow_color3;
vec4 shadow_color4;
};
layout(set = 0, binding = 7, std140) uniform DirectionalLights {