Merge pull request #40616 from reduz/refactor-light-clustering
Refactor light clustering
This commit is contained in:
commit
e38ad5d3de
7 changed files with 842 additions and 793 deletions
|
@ -33,69 +33,6 @@
|
|||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering/rendering_server_raster.h"
|
||||
|
||||
static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.basis.elements[0][0];
|
||||
p_array[1] = p_mtx.basis.elements[1][0];
|
||||
p_array[2] = p_mtx.basis.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.basis.elements[0][1];
|
||||
p_array[5] = p_mtx.basis.elements[1][1];
|
||||
p_array[6] = p_mtx.basis.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.basis.elements[0][2];
|
||||
p_array[9] = p_mtx.basis.elements[1][2];
|
||||
p_array[10] = p_mtx.basis.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
p_array[12] = p_mtx.origin.x;
|
||||
p_array[13] = p_mtx.origin.y;
|
||||
p_array[14] = p_mtx.origin.z;
|
||||
p_array[15] = 1;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.elements[0][0];
|
||||
p_array[1] = p_mtx.elements[1][0];
|
||||
p_array[2] = p_mtx.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.elements[0][1];
|
||||
p_array[5] = p_mtx.elements[1][1];
|
||||
p_array[6] = p_mtx.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.elements[0][2];
|
||||
p_array[9] = p_mtx.elements[1][2];
|
||||
p_array[10] = p_mtx.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.elements[0][0];
|
||||
p_array[1] = p_mtx.elements[1][0];
|
||||
p_array[2] = p_mtx.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.elements[0][1];
|
||||
p_array[5] = p_mtx.elements[1][1];
|
||||
p_array[6] = p_mtx.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.elements[0][2];
|
||||
p_array[9] = p_mtx.elements[1][2];
|
||||
p_array[10] = p_mtx.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
p_array[i * 4 + j] = p_mtx.matrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
|
||||
for (int i = 0; i < 128; i++) {
|
||||
p_array[i] = p_kernel[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* SCENE SHADER */
|
||||
void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
||||
//compile
|
||||
|
@ -845,8 +782,8 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
|
|||
for (int i = 0; i < p_element_count; i++) {
|
||||
const RenderList::Element *e = p_elements[i];
|
||||
InstanceData &id = scene_state.instances[i];
|
||||
store_transform(e->instance->transform, id.transform);
|
||||
store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
|
||||
RasterizerStorageRD::store_transform(e->instance->transform, id.transform);
|
||||
RasterizerStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
|
||||
id.flags = 0;
|
||||
id.mask = e->instance->layer_mask;
|
||||
id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
|
||||
|
@ -1171,20 +1108,20 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende
|
|||
CameraMatrix projection = correction * p_cam_projection;
|
||||
|
||||
//store camera into ubo
|
||||
store_camera(projection, scene_state.ubo.projection_matrix);
|
||||
store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
|
||||
store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
|
||||
store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
|
||||
RasterizerStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
|
||||
RasterizerStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
|
||||
RasterizerStorageRD::store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
|
||||
RasterizerStorageRD::store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
|
||||
|
||||
scene_state.ubo.z_far = p_zfar;
|
||||
scene_state.ubo.z_near = p_znear;
|
||||
|
||||
scene_state.ubo.pancake_shadows = p_pancake_shadows;
|
||||
|
||||
store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
|
||||
store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
|
||||
store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
|
||||
store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
|
||||
RasterizerStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
|
||||
RasterizerStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
|
||||
RasterizerStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
|
||||
RasterizerStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
|
||||
|
||||
scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
|
||||
scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
|
||||
|
@ -1310,7 +1247,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende
|
|||
|
||||
Basis sky_transform = environment_get_sky_orientation(p_environment);
|
||||
sky_transform = sky_transform.inverse() * p_cam_transform.basis;
|
||||
store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
|
||||
RasterizerStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
|
||||
|
||||
scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
|
||||
scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
|
||||
|
@ -1582,66 +1519,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
|
||||
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
|
||||
RID rpi = p_reflection_probe_cull_result[i];
|
||||
|
||||
if (i >= (int)scene_state.max_reflections) {
|
||||
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
|
||||
continue;
|
||||
}
|
||||
|
||||
reflection_probe_instance_set_render_index(rpi, i);
|
||||
|
||||
RID base_probe = reflection_probe_instance_get_probe(rpi);
|
||||
|
||||
ReflectionData &reflection_ubo = scene_state.reflections[i];
|
||||
|
||||
Vector3 extents = storage->reflection_probe_get_extents(base_probe);
|
||||
|
||||
reflection_ubo.box_extents[0] = extents.x;
|
||||
reflection_ubo.box_extents[1] = extents.y;
|
||||
reflection_ubo.box_extents[2] = extents.z;
|
||||
reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi);
|
||||
|
||||
Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
|
||||
|
||||
reflection_ubo.box_offset[0] = origin_offset.x;
|
||||
reflection_ubo.box_offset[1] = origin_offset.y;
|
||||
reflection_ubo.box_offset[2] = origin_offset.z;
|
||||
reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
|
||||
|
||||
float intensity = storage->reflection_probe_get_intensity(base_probe);
|
||||
bool interior = storage->reflection_probe_is_interior(base_probe);
|
||||
bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
|
||||
|
||||
reflection_ubo.params[0] = intensity;
|
||||
reflection_ubo.params[1] = 0;
|
||||
reflection_ubo.params[2] = interior ? 1.0 : 0.0;
|
||||
reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
|
||||
|
||||
Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
|
||||
float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
|
||||
uint32_t ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
|
||||
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
|
||||
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
|
||||
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
|
||||
reflection_ubo.ambient_mode = ambient_mode;
|
||||
|
||||
Transform transform = reflection_probe_instance_get_transform(rpi);
|
||||
Transform proj = (p_camera_inverse_transform * transform).inverse();
|
||||
store_transform(proj, reflection_ubo.local_matrix);
|
||||
|
||||
cluster_builder.add_reflection_probe(transform, extents);
|
||||
|
||||
reflection_probe_instance_set_render_pass(rpi, render_pass);
|
||||
}
|
||||
|
||||
if (p_reflection_probe_cull_count) {
|
||||
RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) {
|
||||
uint32_t lightmaps_used = 0;
|
||||
for (int i = 0; i < p_lightmap_cull_count; i++) {
|
||||
|
@ -1652,7 +1529,7 @@ void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_r
|
|||
InstanceBase *lm = p_lightmap_cull_result[i];
|
||||
Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
|
||||
to_lm = to_lm.inverse().transposed(); //will transform normals
|
||||
store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
||||
RasterizerStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
||||
lm->lightmap_cull_index = i;
|
||||
lightmaps_used++;
|
||||
}
|
||||
|
@ -1661,480 +1538,7 @@ void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_r
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneHighEndRD::_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) {
|
||||
uint32_t light_count = 0;
|
||||
scene_state.ubo.directional_light_count = 0;
|
||||
sky_scene_state.directional_light_count = 0;
|
||||
|
||||
for (int i = 0; i < p_light_cull_count; i++) {
|
||||
RID li = p_light_cull_result[i];
|
||||
RID base = light_instance_get_base_light(li);
|
||||
|
||||
ERR_CONTINUE(base.is_null());
|
||||
|
||||
RS::LightType type = storage->light_get_type(base);
|
||||
switch (type) {
|
||||
case RS::LIGHT_DIRECTIONAL: {
|
||||
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
|
||||
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, RS::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, RS::LIGHT_PARAM_SPECULAR);
|
||||
light_data.mask = storage->light_get_cull_mask(base);
|
||||
|
||||
float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
|
||||
light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
|
||||
|
||||
Color shadow_col = storage->light_get_shadow_color(base).to_linear();
|
||||
|
||||
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);
|
||||
|
||||
float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
if (angular_diameter > 0.0) {
|
||||
// I know tan(0) is 0, but let's not risk it with numerical precision.
|
||||
// technically this will keep expanding until reaching the sun, but all we care
|
||||
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
|
||||
angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
|
||||
} else {
|
||||
angular_diameter = 0.0;
|
||||
}
|
||||
|
||||
if (light_data.shadow_enabled) {
|
||||
RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
|
||||
|
||||
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::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;
|
||||
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);
|
||||
light_data.shadow_range_begin[j] = light_instance_get_shadow_range_begin(li, j);
|
||||
store_camera(shadow_mtx, light_data.shadow_matrices[j]);
|
||||
|
||||
Vector2 uv_scale = light_instance_get_shadow_uv_scale(li, j);
|
||||
uv_scale *= atlas_rect.size; //adapt to atlas size
|
||||
switch (j) {
|
||||
case 0: {
|
||||
light_data.uv_scale1[0] = uv_scale.x;
|
||||
light_data.uv_scale1[1] = uv_scale.y;
|
||||
} break;
|
||||
case 1: {
|
||||
light_data.uv_scale2[0] = uv_scale.x;
|
||||
light_data.uv_scale2[1] = uv_scale.y;
|
||||
} break;
|
||||
case 2: {
|
||||
light_data.uv_scale3[0] = uv_scale.x;
|
||||
light_data.uv_scale3[1] = uv_scale.y;
|
||||
} break;
|
||||
case 3: {
|
||||
light_data.uv_scale4[0] = uv_scale.x;
|
||||
light_data.uv_scale4[1] = uv_scale.y;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
|
||||
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
|
||||
light_data.fade_to = -light_data.shadow_split_offsets[3];
|
||||
|
||||
light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
|
||||
light_data.softshadow_angle = angular_diameter;
|
||||
|
||||
if (angular_diameter <= 0.0) {
|
||||
light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
}
|
||||
|
||||
// Copy to SkyDirectionalLightData
|
||||
if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) {
|
||||
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count];
|
||||
|
||||
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
|
||||
|
||||
sky_light_data.direction[0] = world_direction.x;
|
||||
sky_light_data.direction[1] = world_direction.y;
|
||||
sky_light_data.direction[2] = -world_direction.z;
|
||||
|
||||
sky_light_data.energy = light_data.energy / Math_PI;
|
||||
|
||||
sky_light_data.color[0] = light_data.color[0];
|
||||
sky_light_data.color[1] = light_data.color[1];
|
||||
sky_light_data.color[2] = light_data.color[2];
|
||||
|
||||
sky_light_data.enabled = true;
|
||||
sky_light_data.size = angular_diameter;
|
||||
sky_scene_state.directional_light_count++;
|
||||
}
|
||||
|
||||
scene_state.ubo.directional_light_count++;
|
||||
} break;
|
||||
case RS::LIGHT_SPOT:
|
||||
case RS::LIGHT_OMNI: {
|
||||
if (light_count >= scene_state.max_lights) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Transform light_transform = light_instance_get_base_transform(li);
|
||||
|
||||
LightData &light_data = scene_state.lights[light_count];
|
||||
|
||||
float sign = storage->light_is_negative(base) ? -1 : 1;
|
||||
Color linear_col = storage->light_get_color(base).to_linear();
|
||||
|
||||
light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION));
|
||||
light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI);
|
||||
|
||||
light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255);
|
||||
light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255);
|
||||
light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255);
|
||||
light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 255), 255);
|
||||
|
||||
float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
|
||||
light_data.inv_radius = 1.0 / radius;
|
||||
|
||||
Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
|
||||
|
||||
light_data.position[0] = pos.x;
|
||||
light_data.position[1] = pos.y;
|
||||
light_data.position[2] = pos.z;
|
||||
|
||||
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 size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
|
||||
light_data.size = size;
|
||||
|
||||
light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION));
|
||||
float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
|
||||
light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
|
||||
|
||||
light_data.mask = storage->light_get_cull_mask(base);
|
||||
|
||||
light_data.atlas_rect[0] = 0;
|
||||
light_data.atlas_rect[1] = 0;
|
||||
light_data.atlas_rect[2] = 0;
|
||||
light_data.atlas_rect[3] = 0;
|
||||
|
||||
RID projector = storage->light_get_projector(base);
|
||||
|
||||
if (projector.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
|
||||
|
||||
if (type == RS::LIGHT_SPOT) {
|
||||
light_data.projector_rect[0] = rect.position.x;
|
||||
light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
|
||||
light_data.projector_rect[2] = rect.size.width;
|
||||
light_data.projector_rect[3] = -rect.size.height;
|
||||
} else {
|
||||
light_data.projector_rect[0] = rect.position.x;
|
||||
light_data.projector_rect[1] = rect.position.y;
|
||||
light_data.projector_rect[2] = rect.size.width;
|
||||
light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
|
||||
}
|
||||
} else {
|
||||
light_data.projector_rect[0] = 0;
|
||||
light_data.projector_rect[1] = 0;
|
||||
light_data.projector_rect[2] = 0;
|
||||
light_data.projector_rect[3] = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
light_data.atlas_rect[0] = rect.position.x;
|
||||
light_data.atlas_rect[1] = rect.position.y;
|
||||
light_data.atlas_rect[2] = rect.size.width;
|
||||
light_data.atlas_rect[3] = rect.size.height;
|
||||
|
||||
light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
|
||||
|
||||
if (type == RS::LIGHT_OMNI) {
|
||||
light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
|
||||
Transform proj = (p_camera_inverse_transform * light_transform).inverse();
|
||||
|
||||
store_transform(proj, light_data.shadow_matrix);
|
||||
|
||||
if (size > 0.0) {
|
||||
light_data.soft_shadow_size = size;
|
||||
} else {
|
||||
light_data.soft_shadow_size = 0.0;
|
||||
light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
|
||||
} else if (type == RS::LIGHT_SPOT) {
|
||||
Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
|
||||
CameraMatrix bias;
|
||||
bias.set_light_bias();
|
||||
|
||||
CameraMatrix shadow_mtx = bias * light_instance_get_shadow_camera(li, 0) * modelview;
|
||||
store_camera(shadow_mtx, light_data.shadow_matrix);
|
||||
|
||||
if (size > 0.0) {
|
||||
CameraMatrix cm = light_instance_get_shadow_camera(li, 0);
|
||||
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
|
||||
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
|
||||
} else {
|
||||
light_data.soft_shadow_size = 0.0;
|
||||
light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
}
|
||||
} else {
|
||||
light_data.shadow_color_enabled[3] = 0;
|
||||
}
|
||||
|
||||
light_instance_set_index(li, light_count);
|
||||
|
||||
cluster_builder.add_light(type == RS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
|
||||
|
||||
light_count++;
|
||||
} break;
|
||||
}
|
||||
|
||||
light_instance_set_render_pass(li, render_pass);
|
||||
|
||||
//update UBO for forward rendering, blit to texture for clustered
|
||||
}
|
||||
|
||||
if (light_count) {
|
||||
RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true);
|
||||
}
|
||||
|
||||
if (scene_state.ubo.directional_light_count) {
|
||||
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneHighEndRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
|
||||
Transform uv_xform;
|
||||
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
|
||||
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
|
||||
|
||||
p_decal_count = MIN((uint32_t)p_decal_count, scene_state.max_decals);
|
||||
int idx = 0;
|
||||
for (int i = 0; i < p_decal_count; i++) {
|
||||
RID di = p_decal_instances[i];
|
||||
RID decal = decal_instance_get_base(di);
|
||||
|
||||
Transform xform = decal_instance_get_transform(di);
|
||||
|
||||
float fade = 1.0;
|
||||
|
||||
if (storage->decal_is_distance_fade_enabled(decal)) {
|
||||
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
|
||||
float fade_begin = storage->decal_get_distance_fade_begin(decal);
|
||||
float fade_length = storage->decal_get_distance_fade_length(decal);
|
||||
|
||||
if (distance > fade_begin) {
|
||||
if (distance > fade_begin + fade_length) {
|
||||
continue; // do not use this decal, its invisible
|
||||
}
|
||||
|
||||
fade = 1.0 - (distance - fade_begin) / fade_length;
|
||||
}
|
||||
}
|
||||
|
||||
DecalData &dd = scene_state.decals[idx];
|
||||
|
||||
Vector3 decal_extents = storage->decal_get_extents(decal);
|
||||
|
||||
Transform scale_xform;
|
||||
scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
|
||||
Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse();
|
||||
store_transform(to_decal_xform, dd.xform);
|
||||
|
||||
Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
|
||||
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
|
||||
|
||||
dd.normal[0] = normal.x;
|
||||
dd.normal[1] = normal.y;
|
||||
dd.normal[2] = normal.z;
|
||||
dd.normal_fade = storage->decal_get_normal_fade(decal);
|
||||
|
||||
RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
|
||||
RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
|
||||
if (albedo_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
|
||||
dd.albedo_rect[0] = rect.position.x;
|
||||
dd.albedo_rect[1] = rect.position.y;
|
||||
dd.albedo_rect[2] = rect.size.x;
|
||||
dd.albedo_rect[3] = rect.size.y;
|
||||
} else {
|
||||
if (!emission_tex.is_valid()) {
|
||||
continue; //no albedo, no emission, no decal.
|
||||
}
|
||||
dd.albedo_rect[0] = 0;
|
||||
dd.albedo_rect[1] = 0;
|
||||
dd.albedo_rect[2] = 0;
|
||||
dd.albedo_rect[3] = 0;
|
||||
}
|
||||
|
||||
RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
|
||||
|
||||
if (normal_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
|
||||
dd.normal_rect[0] = rect.position.x;
|
||||
dd.normal_rect[1] = rect.position.y;
|
||||
dd.normal_rect[2] = rect.size.x;
|
||||
dd.normal_rect[3] = rect.size.y;
|
||||
|
||||
Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
|
||||
store_basis_3x4(normal_xform, dd.normal_xform);
|
||||
} else {
|
||||
dd.normal_rect[0] = 0;
|
||||
dd.normal_rect[1] = 0;
|
||||
dd.normal_rect[2] = 0;
|
||||
dd.normal_rect[3] = 0;
|
||||
}
|
||||
|
||||
RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
|
||||
if (orm_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
|
||||
dd.orm_rect[0] = rect.position.x;
|
||||
dd.orm_rect[1] = rect.position.y;
|
||||
dd.orm_rect[2] = rect.size.x;
|
||||
dd.orm_rect[3] = rect.size.y;
|
||||
} else {
|
||||
dd.orm_rect[0] = 0;
|
||||
dd.orm_rect[1] = 0;
|
||||
dd.orm_rect[2] = 0;
|
||||
dd.orm_rect[3] = 0;
|
||||
}
|
||||
|
||||
if (emission_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
|
||||
dd.emission_rect[0] = rect.position.x;
|
||||
dd.emission_rect[1] = rect.position.y;
|
||||
dd.emission_rect[2] = rect.size.x;
|
||||
dd.emission_rect[3] = rect.size.y;
|
||||
} else {
|
||||
dd.emission_rect[0] = 0;
|
||||
dd.emission_rect[1] = 0;
|
||||
dd.emission_rect[2] = 0;
|
||||
dd.emission_rect[3] = 0;
|
||||
}
|
||||
|
||||
Color modulate = storage->decal_get_modulate(decal);
|
||||
dd.modulate[0] = modulate.r;
|
||||
dd.modulate[1] = modulate.g;
|
||||
dd.modulate[2] = modulate.b;
|
||||
dd.modulate[3] = modulate.a * fade;
|
||||
dd.emission_energy = storage->decal_get_emission_energy(decal) * fade;
|
||||
dd.albedo_mix = storage->decal_get_albedo_mix(decal);
|
||||
dd.mask = storage->decal_get_cull_mask(decal);
|
||||
dd.upper_fade = storage->decal_get_upper_fade(decal);
|
||||
dd.lower_fade = storage->decal_get_lower_fade(decal);
|
||||
|
||||
cluster_builder.add_decal(xform, decal_extents);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx > 0) {
|
||||
RD::get_singleton()->buffer_update(scene_state.decal_buffer, 0, sizeof(DecalData) * idx, scene_state.decals, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneHighEndRD::_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_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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) {
|
||||
void RasterizerSceneHighEndRD::_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, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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) {
|
||||
RenderBufferDataHighEnd *render_buffer = nullptr;
|
||||
if (p_render_buffer.is_valid()) {
|
||||
render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer);
|
||||
|
@ -2147,19 +1551,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
|
||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
|
||||
p_light_cull_count = 0;
|
||||
p_reflection_probe_cull_count = 0;
|
||||
p_gi_probe_cull_count = 0;
|
||||
}
|
||||
|
||||
bool using_shadows = true;
|
||||
|
||||
if (p_reflection_probe.is_valid()) {
|
||||
scene_state.ubo.reflection_multiplier = 0.0;
|
||||
if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) {
|
||||
using_shadows = false;
|
||||
}
|
||||
} else {
|
||||
scene_state.ubo.reflection_multiplier = 1.0;
|
||||
}
|
||||
|
@ -2169,6 +1562,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
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;
|
||||
scene_state.ubo.directional_light_count = p_directional_light_count;
|
||||
|
||||
Size2 screen_pixel_size;
|
||||
Size2i screen_size;
|
||||
|
@ -2259,16 +1653,9 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
ERR_FAIL(); //bug?
|
||||
}
|
||||
|
||||
cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
|
||||
|
||||
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
|
||||
_setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
|
||||
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
|
||||
_setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform);
|
||||
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
|
||||
|
||||
cluster_builder.bake_cluster(); //bake to cluster
|
||||
|
||||
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
|
||||
|
||||
render_list.clear();
|
||||
|
@ -2745,7 +2132,7 @@ void RasterizerSceneHighEndRD::_render_sdfgi(RID p_render_buffers, const Vector3
|
|||
to_bounds.origin = p_bounds.position;
|
||||
to_bounds.basis.scale(p_bounds.size);
|
||||
|
||||
store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds);
|
||||
RasterizerStorageRD::store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds);
|
||||
|
||||
_setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
|
||||
|
||||
|
@ -2826,22 +2213,22 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
|||
RD::Uniform u;
|
||||
u.binding = 5;
|
||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.ids.push_back(scene_state.light_buffer);
|
||||
u.ids.push_back(get_positional_light_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 6;
|
||||
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.ids.push_back(scene_state.reflection_buffer);
|
||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.ids.push_back(get_reflection_probe_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 7;
|
||||
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.ids.push_back(scene_state.directional_light_buffer);
|
||||
u.ids.push_back(get_directional_light_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
|
@ -2885,7 +2272,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
|||
RD::Uniform u;
|
||||
u.binding = 15;
|
||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.ids.push_back(scene_state.decal_buffer);
|
||||
u.ids.push_back(get_decal_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
|
@ -2893,14 +2280,14 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
|||
RD::Uniform u;
|
||||
u.binding = 16;
|
||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.ids.push_back(cluster_builder.get_cluster_texture());
|
||||
u.ids.push_back(get_cluster_builder_texture());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 17;
|
||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.ids.push_back(cluster_builder.get_cluster_indices_buffer());
|
||||
u.ids.push_back(get_cluster_builder_indices_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
|
@ -3141,37 +2528,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
|
||||
}
|
||||
defines += "\n#define SDFGI_OCT_SIZE " + itos(sdfgi_get_lightprobe_octahedron_size()) + "\n";
|
||||
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(get_max_directional_lights()) + "\n";
|
||||
|
||||
uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
|
||||
|
||||
{ //reflections
|
||||
uint32_t reflection_buffer_size;
|
||||
if (uniform_max_size < 65536) {
|
||||
//Yes, you guessed right, ARM again
|
||||
reflection_buffer_size = uniform_max_size;
|
||||
} else {
|
||||
reflection_buffer_size = 65536;
|
||||
}
|
||||
|
||||
scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData);
|
||||
scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections);
|
||||
scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size);
|
||||
defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n";
|
||||
}
|
||||
|
||||
{ //lights
|
||||
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()->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);
|
||||
scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights);
|
||||
scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
|
||||
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n";
|
||||
}
|
||||
{
|
||||
//lightmaps
|
||||
scene_state.max_lightmaps = storage->lightmap_array_get_size();
|
||||
|
@ -3187,13 +2545,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
scene_state.lightmap_captures = memnew_arr(LightmapCaptureData, scene_state.max_lightmap_captures);
|
||||
scene_state.lightmap_capture_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapCaptureData) * scene_state.max_lightmap_captures);
|
||||
}
|
||||
{ //decals
|
||||
scene_state.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(DecalData); //1mb of decals
|
||||
uint32_t decal_buffer_size = scene_state.max_decals * sizeof(DecalData);
|
||||
scene_state.decals = memnew_arr(DecalData, scene_state.max_decals);
|
||||
scene_state.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
|
||||
}
|
||||
|
||||
{
|
||||
defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
|
||||
}
|
||||
|
@ -3467,8 +2818,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
|
||||
default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET);
|
||||
}
|
||||
|
||||
cluster_builder.setup(16, 8, 24);
|
||||
}
|
||||
|
||||
RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() {
|
||||
|
@ -3495,19 +2844,11 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() {
|
|||
{
|
||||
RD::get_singleton()->free(scene_state.uniform_buffer);
|
||||
RD::get_singleton()->free(scene_state.instance_buffer);
|
||||
RD::get_singleton()->free(scene_state.directional_light_buffer);
|
||||
RD::get_singleton()->free(scene_state.light_buffer);
|
||||
RD::get_singleton()->free(scene_state.lightmap_buffer);
|
||||
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
|
||||
RD::get_singleton()->free(scene_state.reflection_buffer);
|
||||
RD::get_singleton()->free(scene_state.decal_buffer);
|
||||
memdelete_arr(scene_state.instances);
|
||||
memdelete_arr(scene_state.directional_lights);
|
||||
memdelete_arr(scene_state.lights);
|
||||
memdelete_arr(scene_state.lightmaps);
|
||||
memdelete_arr(scene_state.lightmap_captures);
|
||||
memdelete_arr(scene_state.reflections);
|
||||
memdelete_arr(scene_state.decals);
|
||||
}
|
||||
|
||||
while (sdfgi_framebuffer_size_cache.front()) {
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#ifndef RASTERIZER_SCENE_HIGHEND_RD_H
|
||||
#define RASTERIZER_SCENE_HIGHEND_RD_H
|
||||
|
||||
#include "servers/rendering/rasterizer_rd/light_cluster_builder.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_scene_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
|
||||
|
@ -264,92 +263,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
|
||||
void _update_render_buffers_uniform_set(RID p_render_buffers);
|
||||
|
||||
/* Scene State UBO */
|
||||
|
||||
struct ReflectionData { //should always be 128 bytes
|
||||
float box_extents[3];
|
||||
float index;
|
||||
float box_offset[3];
|
||||
uint32_t mask;
|
||||
float params[4]; // intensity, 0, interior , boxproject
|
||||
float ambient[3]; // ambient color,
|
||||
uint32_t ambient_mode;
|
||||
float local_matrix[16]; // up to here for spot and omni, rest is for directional
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
float position[3];
|
||||
float inv_radius;
|
||||
float direction[3];
|
||||
float size;
|
||||
uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
|
||||
uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
|
||||
uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
|
||||
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;
|
||||
float soft_shadow_size;
|
||||
float soft_shadow_scale;
|
||||
uint32_t mask;
|
||||
uint32_t pad[2];
|
||||
float projector_rect[4];
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
float direction[3];
|
||||
float energy;
|
||||
float color[3];
|
||||
float size;
|
||||
float specular;
|
||||
uint32_t mask;
|
||||
float softshadow_angle;
|
||||
float soft_shadow_scale;
|
||||
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_range_begin[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];
|
||||
float uv_scale1[2];
|
||||
float uv_scale2[2];
|
||||
float uv_scale3[2];
|
||||
float uv_scale4[2];
|
||||
};
|
||||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
};
|
||||
|
||||
struct DecalData {
|
||||
float xform[16];
|
||||
float inv_extents[3];
|
||||
float albedo_mix;
|
||||
float albedo_rect[4];
|
||||
float normal_rect[4];
|
||||
float orm_rect[4];
|
||||
float emission_rect[4];
|
||||
float modulate[4];
|
||||
float emission_energy;
|
||||
uint32_t mask;
|
||||
float upper_fade;
|
||||
float lower_fade;
|
||||
float normal_xform[12];
|
||||
float normal[3];
|
||||
float normal_fade;
|
||||
};
|
||||
|
||||
struct LightmapCaptureData {
|
||||
float sh[9 * 4];
|
||||
};
|
||||
|
@ -448,27 +365,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
|
||||
RID uniform_buffer;
|
||||
|
||||
ReflectionData *reflections;
|
||||
uint32_t max_reflections;
|
||||
RID reflection_buffer;
|
||||
uint32_t max_reflection_probes_per_instance;
|
||||
|
||||
LightmapData *lightmaps;
|
||||
uint32_t max_lightmaps;
|
||||
RID lightmap_buffer;
|
||||
|
||||
DecalData *decals;
|
||||
uint32_t max_decals;
|
||||
RID decal_buffer;
|
||||
|
||||
LightData *lights;
|
||||
uint32_t max_lights;
|
||||
RID light_buffer;
|
||||
|
||||
DirectionalLightData *directional_lights;
|
||||
uint32_t max_directional_lights;
|
||||
RID directional_light_buffer;
|
||||
|
||||
LightmapCaptureData *lightmap_captures;
|
||||
uint32_t max_lightmap_captures;
|
||||
RID lightmap_capture_buffer;
|
||||
|
@ -635,8 +535,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
RID default_vec4_xform_buffer;
|
||||
RID default_vec4_xform_uniform_set;
|
||||
|
||||
LightClusterBuilder cluster_builder;
|
||||
|
||||
enum PassMode {
|
||||
PASS_MODE_COLOR,
|
||||
PASS_MODE_COLOR_SPECULAR,
|
||||
|
@ -651,9 +549,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
};
|
||||
|
||||
void _setup_environment(RID p_environment, RID p_render_buffers, 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_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
|
||||
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_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
|
||||
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
|
||||
|
@ -666,7 +561,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
Map<Size2i, RID> sdfgi_framebuffer_size_cache;
|
||||
|
||||
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_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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_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, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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, 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);
|
||||
virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
|
|
|
@ -5619,6 +5619,539 @@ RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(
|
|||
return rb->data;
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
|
||||
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
|
||||
RID rpi = p_reflection_probe_cull_result[i];
|
||||
|
||||
if (i >= (int)cluster.max_reflections) {
|
||||
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
|
||||
continue;
|
||||
}
|
||||
|
||||
reflection_probe_instance_set_render_index(rpi, i);
|
||||
|
||||
RID base_probe = reflection_probe_instance_get_probe(rpi);
|
||||
|
||||
Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
|
||||
|
||||
Vector3 extents = storage->reflection_probe_get_extents(base_probe);
|
||||
|
||||
reflection_ubo.box_extents[0] = extents.x;
|
||||
reflection_ubo.box_extents[1] = extents.y;
|
||||
reflection_ubo.box_extents[2] = extents.z;
|
||||
reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi);
|
||||
|
||||
Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
|
||||
|
||||
reflection_ubo.box_offset[0] = origin_offset.x;
|
||||
reflection_ubo.box_offset[1] = origin_offset.y;
|
||||
reflection_ubo.box_offset[2] = origin_offset.z;
|
||||
reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
|
||||
|
||||
float intensity = storage->reflection_probe_get_intensity(base_probe);
|
||||
bool interior = storage->reflection_probe_is_interior(base_probe);
|
||||
bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
|
||||
|
||||
reflection_ubo.params[0] = intensity;
|
||||
reflection_ubo.params[1] = 0;
|
||||
reflection_ubo.params[2] = interior ? 1.0 : 0.0;
|
||||
reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
|
||||
|
||||
Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
|
||||
float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
|
||||
uint32_t ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
|
||||
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
|
||||
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
|
||||
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
|
||||
reflection_ubo.ambient_mode = ambient_mode;
|
||||
|
||||
Transform transform = reflection_probe_instance_get_transform(rpi);
|
||||
Transform proj = (p_camera_inverse_transform * transform).inverse();
|
||||
RasterizerStorageRD::store_transform(proj, reflection_ubo.local_matrix);
|
||||
|
||||
cluster.builder.add_reflection_probe(transform, extents);
|
||||
|
||||
reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number());
|
||||
}
|
||||
|
||||
if (p_reflection_probe_cull_count) {
|
||||
RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), cluster.reflections, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_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, uint32_t &r_directional_light_count) {
|
||||
uint32_t light_count = 0;
|
||||
r_directional_light_count = 0;
|
||||
sky_scene_state.directional_light_count = 0;
|
||||
|
||||
for (int i = 0; i < p_light_cull_count; i++) {
|
||||
RID li = p_light_cull_result[i];
|
||||
RID base = light_instance_get_base_light(li);
|
||||
|
||||
ERR_CONTINUE(base.is_null());
|
||||
|
||||
RS::LightType type = storage->light_get_type(base);
|
||||
switch (type) {
|
||||
case RS::LIGHT_DIRECTIONAL: {
|
||||
if (r_directional_light_count >= cluster.max_directional_lights) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cluster::DirectionalLightData &light_data = cluster.directional_lights[r_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, RS::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, RS::LIGHT_PARAM_SPECULAR);
|
||||
light_data.mask = storage->light_get_cull_mask(base);
|
||||
|
||||
float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
|
||||
light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
|
||||
|
||||
Color shadow_col = storage->light_get_shadow_color(base).to_linear();
|
||||
|
||||
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);
|
||||
|
||||
float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
if (angular_diameter > 0.0) {
|
||||
// I know tan(0) is 0, but let's not risk it with numerical precision.
|
||||
// technically this will keep expanding until reaching the sun, but all we care
|
||||
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
|
||||
angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
|
||||
} else {
|
||||
angular_diameter = 0.0;
|
||||
}
|
||||
|
||||
if (light_data.shadow_enabled) {
|
||||
RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
|
||||
|
||||
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::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;
|
||||
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);
|
||||
light_data.shadow_range_begin[j] = light_instance_get_shadow_range_begin(li, j);
|
||||
RasterizerStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
|
||||
|
||||
Vector2 uv_scale = light_instance_get_shadow_uv_scale(li, j);
|
||||
uv_scale *= atlas_rect.size; //adapt to atlas size
|
||||
switch (j) {
|
||||
case 0: {
|
||||
light_data.uv_scale1[0] = uv_scale.x;
|
||||
light_data.uv_scale1[1] = uv_scale.y;
|
||||
} break;
|
||||
case 1: {
|
||||
light_data.uv_scale2[0] = uv_scale.x;
|
||||
light_data.uv_scale2[1] = uv_scale.y;
|
||||
} break;
|
||||
case 2: {
|
||||
light_data.uv_scale3[0] = uv_scale.x;
|
||||
light_data.uv_scale3[1] = uv_scale.y;
|
||||
} break;
|
||||
case 3: {
|
||||
light_data.uv_scale4[0] = uv_scale.x;
|
||||
light_data.uv_scale4[1] = uv_scale.y;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
|
||||
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
|
||||
light_data.fade_to = -light_data.shadow_split_offsets[3];
|
||||
|
||||
light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
|
||||
light_data.softshadow_angle = angular_diameter;
|
||||
|
||||
if (angular_diameter <= 0.0) {
|
||||
light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
}
|
||||
|
||||
// Copy to SkyDirectionalLightData
|
||||
if (r_directional_light_count < sky_scene_state.max_directional_lights) {
|
||||
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count];
|
||||
|
||||
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
|
||||
|
||||
sky_light_data.direction[0] = world_direction.x;
|
||||
sky_light_data.direction[1] = world_direction.y;
|
||||
sky_light_data.direction[2] = -world_direction.z;
|
||||
|
||||
sky_light_data.energy = light_data.energy / Math_PI;
|
||||
|
||||
sky_light_data.color[0] = light_data.color[0];
|
||||
sky_light_data.color[1] = light_data.color[1];
|
||||
sky_light_data.color[2] = light_data.color[2];
|
||||
|
||||
sky_light_data.enabled = true;
|
||||
sky_light_data.size = angular_diameter;
|
||||
sky_scene_state.directional_light_count++;
|
||||
}
|
||||
|
||||
r_directional_light_count++;
|
||||
} break;
|
||||
case RS::LIGHT_SPOT:
|
||||
case RS::LIGHT_OMNI: {
|
||||
if (light_count >= cluster.max_lights) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Transform light_transform = light_instance_get_base_transform(li);
|
||||
|
||||
Cluster::LightData &light_data = cluster.lights[light_count];
|
||||
|
||||
float sign = storage->light_is_negative(base) ? -1 : 1;
|
||||
Color linear_col = storage->light_get_color(base).to_linear();
|
||||
|
||||
light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION));
|
||||
light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI);
|
||||
|
||||
light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255);
|
||||
light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255);
|
||||
light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255);
|
||||
light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 255), 255);
|
||||
|
||||
float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
|
||||
light_data.inv_radius = 1.0 / radius;
|
||||
|
||||
Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
|
||||
|
||||
light_data.position[0] = pos.x;
|
||||
light_data.position[1] = pos.y;
|
||||
light_data.position[2] = pos.z;
|
||||
|
||||
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 size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||
|
||||
light_data.size = size;
|
||||
|
||||
light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION));
|
||||
float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
|
||||
light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
|
||||
|
||||
light_data.mask = storage->light_get_cull_mask(base);
|
||||
|
||||
light_data.atlas_rect[0] = 0;
|
||||
light_data.atlas_rect[1] = 0;
|
||||
light_data.atlas_rect[2] = 0;
|
||||
light_data.atlas_rect[3] = 0;
|
||||
|
||||
RID projector = storage->light_get_projector(base);
|
||||
|
||||
if (projector.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
|
||||
|
||||
if (type == RS::LIGHT_SPOT) {
|
||||
light_data.projector_rect[0] = rect.position.x;
|
||||
light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
|
||||
light_data.projector_rect[2] = rect.size.width;
|
||||
light_data.projector_rect[3] = -rect.size.height;
|
||||
} else {
|
||||
light_data.projector_rect[0] = rect.position.x;
|
||||
light_data.projector_rect[1] = rect.position.y;
|
||||
light_data.projector_rect[2] = rect.size.width;
|
||||
light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
|
||||
}
|
||||
} else {
|
||||
light_data.projector_rect[0] = 0;
|
||||
light_data.projector_rect[1] = 0;
|
||||
light_data.projector_rect[2] = 0;
|
||||
light_data.projector_rect[3] = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
light_data.atlas_rect[0] = rect.position.x;
|
||||
light_data.atlas_rect[1] = rect.position.y;
|
||||
light_data.atlas_rect[2] = rect.size.width;
|
||||
light_data.atlas_rect[3] = rect.size.height;
|
||||
|
||||
light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
|
||||
|
||||
if (type == RS::LIGHT_OMNI) {
|
||||
light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
|
||||
Transform proj = (p_camera_inverse_transform * light_transform).inverse();
|
||||
|
||||
RasterizerStorageRD::store_transform(proj, light_data.shadow_matrix);
|
||||
|
||||
if (size > 0.0) {
|
||||
light_data.soft_shadow_size = size;
|
||||
} else {
|
||||
light_data.soft_shadow_size = 0.0;
|
||||
light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
|
||||
} else if (type == RS::LIGHT_SPOT) {
|
||||
Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
|
||||
CameraMatrix bias;
|
||||
bias.set_light_bias();
|
||||
|
||||
CameraMatrix shadow_mtx = bias * light_instance_get_shadow_camera(li, 0) * modelview;
|
||||
RasterizerStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
|
||||
|
||||
if (size > 0.0) {
|
||||
CameraMatrix cm = light_instance_get_shadow_camera(li, 0);
|
||||
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
|
||||
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
|
||||
} else {
|
||||
light_data.soft_shadow_size = 0.0;
|
||||
light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
|
||||
}
|
||||
}
|
||||
} else {
|
||||
light_data.shadow_color_enabled[3] = 0;
|
||||
}
|
||||
|
||||
light_instance_set_index(li, light_count);
|
||||
|
||||
cluster.builder.add_light(type == RS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
|
||||
|
||||
light_count++;
|
||||
} break;
|
||||
}
|
||||
|
||||
light_instance_set_render_pass(li, RSG::rasterizer->get_frame_number());
|
||||
|
||||
//update UBO for forward rendering, blit to texture for clustered
|
||||
}
|
||||
|
||||
if (light_count) {
|
||||
RD::get_singleton()->buffer_update(cluster.light_buffer, 0, sizeof(Cluster::LightData) * light_count, cluster.lights, true);
|
||||
}
|
||||
|
||||
if (r_directional_light_count) {
|
||||
RD::get_singleton()->buffer_update(cluster.directional_light_buffer, 0, sizeof(Cluster::DirectionalLightData) * r_directional_light_count, cluster.directional_lights, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
|
||||
Transform uv_xform;
|
||||
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
|
||||
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
|
||||
|
||||
p_decal_count = MIN((uint32_t)p_decal_count, cluster.max_decals);
|
||||
int idx = 0;
|
||||
for (int i = 0; i < p_decal_count; i++) {
|
||||
RID di = p_decal_instances[i];
|
||||
RID decal = decal_instance_get_base(di);
|
||||
|
||||
Transform xform = decal_instance_get_transform(di);
|
||||
|
||||
float fade = 1.0;
|
||||
|
||||
if (storage->decal_is_distance_fade_enabled(decal)) {
|
||||
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
|
||||
float fade_begin = storage->decal_get_distance_fade_begin(decal);
|
||||
float fade_length = storage->decal_get_distance_fade_length(decal);
|
||||
|
||||
if (distance > fade_begin) {
|
||||
if (distance > fade_begin + fade_length) {
|
||||
continue; // do not use this decal, its invisible
|
||||
}
|
||||
|
||||
fade = 1.0 - (distance - fade_begin) / fade_length;
|
||||
}
|
||||
}
|
||||
|
||||
Cluster::DecalData &dd = cluster.decals[idx];
|
||||
|
||||
Vector3 decal_extents = storage->decal_get_extents(decal);
|
||||
|
||||
Transform scale_xform;
|
||||
scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
|
||||
Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse();
|
||||
RasterizerStorageRD::store_transform(to_decal_xform, dd.xform);
|
||||
|
||||
Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
|
||||
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
|
||||
|
||||
dd.normal[0] = normal.x;
|
||||
dd.normal[1] = normal.y;
|
||||
dd.normal[2] = normal.z;
|
||||
dd.normal_fade = storage->decal_get_normal_fade(decal);
|
||||
|
||||
RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
|
||||
RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
|
||||
if (albedo_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
|
||||
dd.albedo_rect[0] = rect.position.x;
|
||||
dd.albedo_rect[1] = rect.position.y;
|
||||
dd.albedo_rect[2] = rect.size.x;
|
||||
dd.albedo_rect[3] = rect.size.y;
|
||||
} else {
|
||||
if (!emission_tex.is_valid()) {
|
||||
continue; //no albedo, no emission, no decal.
|
||||
}
|
||||
dd.albedo_rect[0] = 0;
|
||||
dd.albedo_rect[1] = 0;
|
||||
dd.albedo_rect[2] = 0;
|
||||
dd.albedo_rect[3] = 0;
|
||||
}
|
||||
|
||||
RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
|
||||
|
||||
if (normal_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
|
||||
dd.normal_rect[0] = rect.position.x;
|
||||
dd.normal_rect[1] = rect.position.y;
|
||||
dd.normal_rect[2] = rect.size.x;
|
||||
dd.normal_rect[3] = rect.size.y;
|
||||
|
||||
Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
|
||||
RasterizerStorageRD::store_basis_3x4(normal_xform, dd.normal_xform);
|
||||
} else {
|
||||
dd.normal_rect[0] = 0;
|
||||
dd.normal_rect[1] = 0;
|
||||
dd.normal_rect[2] = 0;
|
||||
dd.normal_rect[3] = 0;
|
||||
}
|
||||
|
||||
RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
|
||||
if (orm_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
|
||||
dd.orm_rect[0] = rect.position.x;
|
||||
dd.orm_rect[1] = rect.position.y;
|
||||
dd.orm_rect[2] = rect.size.x;
|
||||
dd.orm_rect[3] = rect.size.y;
|
||||
} else {
|
||||
dd.orm_rect[0] = 0;
|
||||
dd.orm_rect[1] = 0;
|
||||
dd.orm_rect[2] = 0;
|
||||
dd.orm_rect[3] = 0;
|
||||
}
|
||||
|
||||
if (emission_tex.is_valid()) {
|
||||
Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
|
||||
dd.emission_rect[0] = rect.position.x;
|
||||
dd.emission_rect[1] = rect.position.y;
|
||||
dd.emission_rect[2] = rect.size.x;
|
||||
dd.emission_rect[3] = rect.size.y;
|
||||
} else {
|
||||
dd.emission_rect[0] = 0;
|
||||
dd.emission_rect[1] = 0;
|
||||
dd.emission_rect[2] = 0;
|
||||
dd.emission_rect[3] = 0;
|
||||
}
|
||||
|
||||
Color modulate = storage->decal_get_modulate(decal);
|
||||
dd.modulate[0] = modulate.r;
|
||||
dd.modulate[1] = modulate.g;
|
||||
dd.modulate[2] = modulate.b;
|
||||
dd.modulate[3] = modulate.a * fade;
|
||||
dd.emission_energy = storage->decal_get_emission_energy(decal) * fade;
|
||||
dd.albedo_mix = storage->decal_get_albedo_mix(decal);
|
||||
dd.mask = storage->decal_get_cull_mask(decal);
|
||||
dd.upper_fade = storage->decal_get_upper_fade(decal);
|
||||
dd.lower_fade = storage->decal_get_lower_fade(decal);
|
||||
|
||||
cluster.builder.add_decal(xform, decal_extents);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx > 0) {
|
||||
RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * idx, cluster.decals, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::render_scene(RID p_render_buffers, 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_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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) {
|
||||
Color clear_color;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
|
@ -5637,7 +6170,31 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca
|
|||
}
|
||||
}
|
||||
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_decal_cull_result, p_decal_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
|
||||
p_light_cull_count = 0;
|
||||
p_reflection_probe_cull_count = 0;
|
||||
p_gi_probe_cull_count = 0;
|
||||
}
|
||||
|
||||
cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
|
||||
|
||||
bool using_shadows = true;
|
||||
|
||||
if (p_reflection_probe.is_valid()) {
|
||||
if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) {
|
||||
using_shadows = false;
|
||||
}
|
||||
} else {
|
||||
//do not render reflections when rendering a reflection probe
|
||||
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
|
||||
}
|
||||
|
||||
uint32_t directional_light_count = 0;
|
||||
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count);
|
||||
_setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
|
||||
cluster.builder.bake_cluster(); //bake to cluster
|
||||
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
@ -6496,6 +7053,30 @@ void RasterizerSceneRD::sdfgi_set_debug_probe_select(const Vector3 &p_position,
|
|||
|
||||
RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr;
|
||||
|
||||
RID RasterizerSceneRD::get_cluster_builder_texture() {
|
||||
return cluster.builder.get_cluster_texture();
|
||||
}
|
||||
|
||||
RID RasterizerSceneRD::get_cluster_builder_indices_buffer() {
|
||||
return cluster.builder.get_cluster_indices_buffer();
|
||||
}
|
||||
|
||||
RID RasterizerSceneRD::get_reflection_probe_buffer() {
|
||||
return cluster.reflection_buffer;
|
||||
}
|
||||
RID RasterizerSceneRD::get_positional_light_buffer() {
|
||||
return cluster.light_buffer;
|
||||
}
|
||||
RID RasterizerSceneRD::get_directional_light_buffer() {
|
||||
return cluster.directional_light_buffer;
|
||||
}
|
||||
RID RasterizerSceneRD::get_decal_buffer() {
|
||||
return cluster.decal_buffer;
|
||||
}
|
||||
int RasterizerSceneRD::get_max_directional_lights() const {
|
||||
return cluster.max_directional_lights;
|
||||
}
|
||||
|
||||
RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
||||
storage = p_storage;
|
||||
singleton = this;
|
||||
|
@ -6802,6 +7383,45 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
|||
}
|
||||
}
|
||||
|
||||
//cluster setup
|
||||
uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
|
||||
|
||||
{ //reflections
|
||||
uint32_t reflection_buffer_size;
|
||||
if (uniform_max_size < 65536) {
|
||||
//Yes, you guessed right, ARM again
|
||||
reflection_buffer_size = uniform_max_size;
|
||||
} else {
|
||||
reflection_buffer_size = 65536;
|
||||
}
|
||||
|
||||
cluster.max_reflections = reflection_buffer_size / sizeof(Cluster::ReflectionData);
|
||||
cluster.reflections = memnew_arr(Cluster::ReflectionData, cluster.max_reflections);
|
||||
cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(reflection_buffer_size);
|
||||
}
|
||||
|
||||
{ //lights
|
||||
cluster.max_lights = MIN(1024 * 1024, uniform_max_size) / sizeof(Cluster::LightData); //1mb of lights
|
||||
uint32_t light_buffer_size = cluster.max_lights * sizeof(Cluster::LightData);
|
||||
cluster.lights = memnew_arr(Cluster::LightData, cluster.max_lights);
|
||||
cluster.light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
|
||||
//defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(cluster.max_lights) + "\n";
|
||||
|
||||
cluster.max_directional_lights = 8;
|
||||
uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData);
|
||||
cluster.directional_lights = memnew_arr(Cluster::DirectionalLightData, cluster.max_directional_lights);
|
||||
cluster.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
|
||||
}
|
||||
|
||||
{ //decals
|
||||
cluster.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(Cluster::DecalData); //1mb of decals
|
||||
uint32_t decal_buffer_size = cluster.max_decals * sizeof(Cluster::DecalData);
|
||||
cluster.decals = memnew_arr(Cluster::DecalData, cluster.max_decals);
|
||||
cluster.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
|
||||
}
|
||||
|
||||
cluster.builder.setup(16, 8, 24);
|
||||
|
||||
default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);
|
||||
|
||||
camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape"))));
|
||||
|
@ -6863,4 +7483,15 @@ RasterizerSceneRD::~RasterizerSceneRD() {
|
|||
memdelete_arr(directional_soft_shadow_kernel);
|
||||
memdelete_arr(penumbra_shadow_kernel);
|
||||
memdelete_arr(soft_shadow_kernel);
|
||||
|
||||
{
|
||||
RD::get_singleton()->free(cluster.directional_light_buffer);
|
||||
RD::get_singleton()->free(cluster.light_buffer);
|
||||
RD::get_singleton()->free(cluster.reflection_buffer);
|
||||
RD::get_singleton()->free(cluster.decal_buffer);
|
||||
memdelete_arr(cluster.directional_lights);
|
||||
memdelete_arr(cluster.lights);
|
||||
memdelete_arr(cluster.reflections);
|
||||
memdelete_arr(cluster.decals);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/local_vector.h"
|
||||
#include "core/rid_owner.h"
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering/rasterizer_rd/light_cluster_builder.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/gi.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/giprobe.glsl.gen.h"
|
||||
|
@ -77,7 +78,11 @@ 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_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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;
|
||||
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, uint32_t &r_directional_light_count);
|
||||
void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
|
||||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||
|
||||
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, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_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, 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 _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
|
@ -1181,6 +1186,112 @@ private:
|
|||
void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection);
|
||||
void _sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform);
|
||||
|
||||
/* Cluster */
|
||||
|
||||
struct Cluster {
|
||||
/* Scene State UBO */
|
||||
|
||||
struct ReflectionData { //should always be 128 bytes
|
||||
float box_extents[3];
|
||||
float index;
|
||||
float box_offset[3];
|
||||
uint32_t mask;
|
||||
float params[4]; // intensity, 0, interior , boxproject
|
||||
float ambient[3]; // ambient color,
|
||||
uint32_t ambient_mode;
|
||||
float local_matrix[16]; // up to here for spot and omni, rest is for directional
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
float position[3];
|
||||
float inv_radius;
|
||||
float direction[3];
|
||||
float size;
|
||||
uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
|
||||
uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
|
||||
uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
|
||||
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;
|
||||
float soft_shadow_size;
|
||||
float soft_shadow_scale;
|
||||
uint32_t mask;
|
||||
uint32_t pad[2];
|
||||
float projector_rect[4];
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
float direction[3];
|
||||
float energy;
|
||||
float color[3];
|
||||
float size;
|
||||
float specular;
|
||||
uint32_t mask;
|
||||
float softshadow_angle;
|
||||
float soft_shadow_scale;
|
||||
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_range_begin[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];
|
||||
float uv_scale1[2];
|
||||
float uv_scale2[2];
|
||||
float uv_scale3[2];
|
||||
float uv_scale4[2];
|
||||
};
|
||||
|
||||
struct DecalData {
|
||||
float xform[16];
|
||||
float inv_extents[3];
|
||||
float albedo_mix;
|
||||
float albedo_rect[4];
|
||||
float normal_rect[4];
|
||||
float orm_rect[4];
|
||||
float emission_rect[4];
|
||||
float modulate[4];
|
||||
float emission_energy;
|
||||
uint32_t mask;
|
||||
float upper_fade;
|
||||
float lower_fade;
|
||||
float normal_xform[12];
|
||||
float normal[3];
|
||||
float normal_fade;
|
||||
};
|
||||
|
||||
ReflectionData *reflections;
|
||||
uint32_t max_reflections;
|
||||
RID reflection_buffer;
|
||||
uint32_t max_reflection_probes_per_instance;
|
||||
|
||||
DecalData *decals;
|
||||
uint32_t max_decals;
|
||||
RID decal_buffer;
|
||||
|
||||
LightData *lights;
|
||||
uint32_t max_lights;
|
||||
RID light_buffer;
|
||||
|
||||
DirectionalLightData *directional_lights;
|
||||
uint32_t max_directional_lights;
|
||||
RID directional_light_buffer;
|
||||
|
||||
LightClusterBuilder builder;
|
||||
|
||||
} cluster;
|
||||
|
||||
uint64_t scene_pass = 0;
|
||||
uint64_t shadow_atlas_realloc_tolerance_msec = 500;
|
||||
|
||||
|
@ -1655,6 +1766,14 @@ public:
|
|||
|
||||
virtual void set_time(double p_time, double p_step);
|
||||
|
||||
RID get_cluster_builder_texture();
|
||||
RID get_cluster_builder_indices_buffer();
|
||||
RID get_reflection_probe_buffer();
|
||||
RID get_positional_light_buffer();
|
||||
RID get_directional_light_buffer();
|
||||
RID get_decal_buffer();
|
||||
int get_max_directional_lights() const;
|
||||
|
||||
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
|
||||
|
||||
RasterizerSceneRD(RasterizerStorageRD *p_storage);
|
||||
|
|
|
@ -40,6 +40,69 @@
|
|||
|
||||
class RasterizerStorageRD : public RasterizerStorage {
|
||||
public:
|
||||
static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.basis.elements[0][0];
|
||||
p_array[1] = p_mtx.basis.elements[1][0];
|
||||
p_array[2] = p_mtx.basis.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.basis.elements[0][1];
|
||||
p_array[5] = p_mtx.basis.elements[1][1];
|
||||
p_array[6] = p_mtx.basis.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.basis.elements[0][2];
|
||||
p_array[9] = p_mtx.basis.elements[1][2];
|
||||
p_array[10] = p_mtx.basis.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
p_array[12] = p_mtx.origin.x;
|
||||
p_array[13] = p_mtx.origin.y;
|
||||
p_array[14] = p_mtx.origin.z;
|
||||
p_array[15] = 1;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.elements[0][0];
|
||||
p_array[1] = p_mtx.elements[1][0];
|
||||
p_array[2] = p_mtx.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.elements[0][1];
|
||||
p_array[5] = p_mtx.elements[1][1];
|
||||
p_array[6] = p_mtx.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.elements[0][2];
|
||||
p_array[9] = p_mtx.elements[1][2];
|
||||
p_array[10] = p_mtx.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.elements[0][0];
|
||||
p_array[1] = p_mtx.elements[1][0];
|
||||
p_array[2] = p_mtx.elements[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.elements[0][1];
|
||||
p_array[5] = p_mtx.elements[1][1];
|
||||
p_array[6] = p_mtx.elements[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.elements[0][2];
|
||||
p_array[9] = p_mtx.elements[1][2];
|
||||
p_array[10] = p_mtx.elements[2][2];
|
||||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
p_array[i * 4 + j] = p_mtx.matrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
|
||||
for (int i = 0; i < 128; i++) {
|
||||
p_array[i] = p_kernel[i];
|
||||
}
|
||||
}
|
||||
|
||||
enum ShaderType {
|
||||
SHADER_TYPE_2D,
|
||||
SHADER_TYPE_3D,
|
||||
|
|
|
@ -2685,7 +2685,7 @@ FRAGMENT_SHADER_CODE
|
|||
frag_color = vec4(albedo, alpha);
|
||||
#else
|
||||
frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
|
||||
//frag_color = vec4(1.0);
|
||||
//frag_color = vec4(1.0);;;
|
||||
|
||||
#endif //USE_NO_SHADING
|
||||
|
||||
|
|
|
@ -205,8 +205,8 @@ struct ReflectionData {
|
|||
// notes: for ambientblend, use distance to edge to blend between already existing global environment
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 6, std140) uniform ReflectionProbeData {
|
||||
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
|
||||
layout(set = 0, binding = 6) buffer restrict readonly ReflectionProbeData {
|
||||
ReflectionData data[];
|
||||
}
|
||||
reflections;
|
||||
|
||||
|
|
Loading…
Reference in a new issue