|
|
|
@ -1535,106 +1535,102 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
|
|
|
|
|
|
|
|
|
|
VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base);
|
|
|
|
|
|
|
|
|
|
switch (shadow_mode) {
|
|
|
|
|
case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: {
|
|
|
|
|
if (shadow_mode == VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !VSG::scene_render->light_instances_can_render_shadow_cube()) {
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
|
|
|
|
|
|
//using this one ensures that raster deferred will have it
|
|
|
|
|
|
|
|
|
|
float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
|
|
|
|
|
|
|
|
|
|
float z = i == 0 ? -1 : 1;
|
|
|
|
|
Vector<Plane> planes;
|
|
|
|
|
planes.resize(5);
|
|
|
|
|
planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
|
|
|
|
|
planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
|
|
|
|
|
planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
|
|
|
|
|
planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
|
|
|
|
|
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
|
|
|
|
|
|
|
|
|
|
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
|
|
|
|
|
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < cull_count; j++) {
|
|
|
|
|
|
|
|
|
|
Instance *instance = instance_shadow_cull_result[j];
|
|
|
|
|
if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
|
|
|
|
|
cull_count--;
|
|
|
|
|
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
|
|
|
|
|
j--;
|
|
|
|
|
} else {
|
|
|
|
|
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
|
|
|
|
|
animated_material_found = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instance->depth = near_plane.distance_to(instance->transform.origin);
|
|
|
|
|
instance->depth_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
|
|
|
|
|
VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
|
|
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
case VS::LIGHT_OMNI_SHADOW_CUBE: {
|
|
|
|
|
//using this one ensures that raster deferred will have it
|
|
|
|
|
|
|
|
|
|
float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
|
|
|
|
|
CameraMatrix cm;
|
|
|
|
|
cm.set_perspective(90, 1, 0.01, radius);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
|
float z = i == 0 ? -1 : 1;
|
|
|
|
|
Vector<Plane> planes;
|
|
|
|
|
planes.resize(5);
|
|
|
|
|
planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
|
|
|
|
|
planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
|
|
|
|
|
planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
|
|
|
|
|
planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
|
|
|
|
|
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
|
|
|
|
|
|
|
|
|
|
//using this one ensures that raster deferred will have it
|
|
|
|
|
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
|
|
|
|
|
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
|
|
|
|
|
|
|
|
|
|
static const Vector3 view_normals[6] = {
|
|
|
|
|
Vector3(-1, 0, 0),
|
|
|
|
|
Vector3(+1, 0, 0),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, +1, 0),
|
|
|
|
|
Vector3(0, 0, -1),
|
|
|
|
|
Vector3(0, 0, +1)
|
|
|
|
|
};
|
|
|
|
|
static const Vector3 view_up[6] = {
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, 0, -1),
|
|
|
|
|
Vector3(0, 0, +1),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, -1, 0)
|
|
|
|
|
};
|
|
|
|
|
for (int j = 0; j < cull_count; j++) {
|
|
|
|
|
|
|
|
|
|
Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
|
|
|
|
|
|
|
|
|
|
Vector<Plane> planes = cm.get_projection_planes(xform);
|
|
|
|
|
|
|
|
|
|
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
|
|
|
|
|
|
|
|
|
|
Plane near_plane(xform.origin, -xform.basis.get_axis(2));
|
|
|
|
|
for (int j = 0; j < cull_count; j++) {
|
|
|
|
|
|
|
|
|
|
Instance *instance = instance_shadow_cull_result[j];
|
|
|
|
|
if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
|
|
|
|
|
cull_count--;
|
|
|
|
|
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
|
|
|
|
|
j--;
|
|
|
|
|
} else {
|
|
|
|
|
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
|
|
|
|
|
animated_material_found = true;
|
|
|
|
|
}
|
|
|
|
|
instance->depth = near_plane.distance_to(instance->transform.origin);
|
|
|
|
|
instance->depth_layer = 0;
|
|
|
|
|
Instance *instance = instance_shadow_cull_result[j];
|
|
|
|
|
if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
|
|
|
|
|
cull_count--;
|
|
|
|
|
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
|
|
|
|
|
j--;
|
|
|
|
|
} else {
|
|
|
|
|
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
|
|
|
|
|
animated_material_found = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
|
|
|
|
|
VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
|
|
|
|
|
instance->depth = near_plane.distance_to(instance->transform.origin);
|
|
|
|
|
instance->depth_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//restore the regular DP matrix
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
|
|
|
|
|
VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
|
|
|
|
|
}
|
|
|
|
|
} else { //shadow cube
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
|
|
|
|
|
CameraMatrix cm;
|
|
|
|
|
cm.set_perspective(90, 1, 0.01, radius);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
|
|
|
|
|
|
//using this one ensures that raster deferred will have it
|
|
|
|
|
|
|
|
|
|
static const Vector3 view_normals[6] = {
|
|
|
|
|
Vector3(-1, 0, 0),
|
|
|
|
|
Vector3(+1, 0, 0),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, +1, 0),
|
|
|
|
|
Vector3(0, 0, -1),
|
|
|
|
|
Vector3(0, 0, +1)
|
|
|
|
|
};
|
|
|
|
|
static const Vector3 view_up[6] = {
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, 0, -1),
|
|
|
|
|
Vector3(0, 0, +1),
|
|
|
|
|
Vector3(0, -1, 0),
|
|
|
|
|
Vector3(0, -1, 0)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
|
|
|
|
|
|
|
|
|
|
Vector<Plane> planes = cm.get_projection_planes(xform);
|
|
|
|
|
|
|
|
|
|
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
|
|
|
|
|
|
|
|
|
|
Plane near_plane(xform.origin, -xform.basis.get_axis(2));
|
|
|
|
|
for (int j = 0; j < cull_count; j++) {
|
|
|
|
|
|
|
|
|
|
Instance *instance = instance_shadow_cull_result[j];
|
|
|
|
|
if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
|
|
|
|
|
cull_count--;
|
|
|
|
|
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
|
|
|
|
|
j--;
|
|
|
|
|
} else {
|
|
|
|
|
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
|
|
|
|
|
animated_material_found = true;
|
|
|
|
|
}
|
|
|
|
|
instance->depth = near_plane.distance_to(instance->transform.origin);
|
|
|
|
|
instance->depth_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
|
|
|
|
|
VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//restore the regular DP matrix
|
|
|
|
|
VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|