|
@@ -969,6 +969,13 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) {
|
|
|
+ Instance *instance = instance_owner.getornull(p_instance);
|
|
|
+ ERR_FAIL_COND(!instance);
|
|
|
+
|
|
|
+ instance->lod_bias = p_lod_bias;
|
|
|
+}
|
|
|
+
|
|
|
void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
|
|
|
Instance *instance = instance_owner.getornull(p_instance);
|
|
|
ERR_FAIL_COND(!instance);
|
|
@@ -1325,7 +1332,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
|
|
|
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) {
|
|
|
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
|
|
|
|
|
|
Transform light_transform = p_instance->transform;
|
|
@@ -1335,6 +1342,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|
|
|
|
|
switch (RSG::storage->light_get_type(p_instance->base)) {
|
|
|
case RS::LIGHT_DIRECTIONAL: {
|
|
|
+ Plane camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
|
|
|
+
|
|
|
real_t max_distance = p_cam_projection.get_z_far();
|
|
|
real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
|
|
|
if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
|
|
@@ -1703,7 +1712,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|
|
|
|
|
RSG::storage->update_mesh_instances();
|
|
|
|
|
|
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
|
|
|
+ scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count, camera_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
|
|
|
}
|
|
|
|
|
|
} break;
|
|
@@ -1860,7 +1869,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|
|
return animated_material_found;
|
|
|
}
|
|
|
|
|
|
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
|
|
|
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
|
|
|
// render to mono camera
|
|
|
#ifndef _3D_DISABLED
|
|
|
|
|
@@ -1905,12 +1914,12 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
|
|
|
|
|
|
RID environment = _render_get_environment(p_camera, p_scenario);
|
|
|
|
|
|
- _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
|
|
- _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
|
|
+ _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
|
|
+ _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
|
|
|
+void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
|
|
|
// render for AR/VR interface
|
|
|
|
|
|
Camera *camera = camera_owner.getornull(p_camera);
|
|
@@ -1984,17 +1993,17 @@ void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_
|
|
|
mono_transform *= apply_z_shift;
|
|
|
|
|
|
// now prepare our scene with our adjusted transform projection matrix
|
|
|
- _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
|
|
+ _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
|
|
} else if (p_eye == XRInterface::EYE_MONO) {
|
|
|
// For mono render, prepare as per usual
|
|
|
- _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
|
|
+ _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
|
|
}
|
|
|
|
|
|
// And render our scene...
|
|
|
- _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
|
|
+ _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
|
|
|
};
|
|
|
|
|
|
-void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
|
|
|
+void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows) {
|
|
|
// Note, in stereo rendering:
|
|
|
// - p_cam_transform will be a transform in the middle of our two eyes
|
|
|
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
|
@@ -2250,7 +2259,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
|
|
|
for (int i = 0; i < directional_shadow_count; i++) {
|
|
|
RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
|
|
|
|
|
|
- _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
|
|
|
+ _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
|
|
|
|
|
|
RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
|
|
|
}
|
|
@@ -2349,7 +2358,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
|
|
|
if (redraw) {
|
|
|
//must redraw!
|
|
|
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
|
|
|
- light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
|
|
|
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
|
|
|
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
|
|
|
}
|
|
|
}
|
|
@@ -2447,7 +2456,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
|
|
|
return RID();
|
|
|
}
|
|
|
|
|
|
-void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
|
|
+void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
|
|
|
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
|
|
|
|
|
RID camera_effects;
|
|
@@ -2459,7 +2468,7 @@ void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_ca
|
|
|
/* PROCESS GEOMETRY AND DRAW SCENE */
|
|
|
|
|
|
RENDER_TIMESTAMP("Render Scene ");
|
|
|
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RendererSceneRender::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RendererSceneRender::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
|
|
+ scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RendererSceneRender::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RendererSceneRender::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
|
|
|
}
|
|
|
|
|
|
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
|
@@ -2474,7 +2483,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
|
|
|
environment = scenario->fallback_environment;
|
|
|
}
|
|
|
RENDER_TIMESTAMP("Render Empty Scene ");
|
|
|
- scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
|
|
|
+ scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -2512,6 +2521,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
|
|
|
Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
|
|
|
Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
|
|
|
float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
|
|
|
+ float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
|
|
|
+ float lod_threshold = RSG::storage->reflection_probe_get_lod_threshold(p_instance->base) / size;
|
|
|
|
|
|
Vector3 edge = view_normals[p_step] * extents;
|
|
|
float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
|
|
@@ -2535,8 +2546,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
|
|
|
}
|
|
|
|
|
|
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
|
|
|
- _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
|
|
|
- _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
|
|
|
+ _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, lod_threshold, use_shadows);
|
|
|
+ _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step, lod_threshold);
|
|
|
|
|
|
} else {
|
|
|
//do roughness postprocess step until it believes it's done
|