Reflection probes working
This commit is contained in:
parent
69e83e4815
commit
9d7b7f931b
|
@ -512,7 +512,7 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
|
|||
return new_matrix;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_depth_correction() {
|
||||
void CameraMatrix::set_depth_correction(bool p_flip_y) {
|
||||
|
||||
real_t *m = &matrix[0][0];
|
||||
|
||||
|
@ -521,7 +521,7 @@ void CameraMatrix::set_depth_correction() {
|
|||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = -1;
|
||||
m[5] = p_flip_y ? -1 : 1;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
|
|
|
@ -50,7 +50,7 @@ struct CameraMatrix {
|
|||
void set_identity();
|
||||
void set_zero();
|
||||
void set_light_bias();
|
||||
void set_depth_correction();
|
||||
void set_depth_correction(bool p_flip_y = true);
|
||||
void set_light_atlas_rect(const Rect2 &p_rect);
|
||||
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
|
||||
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "core/self_list.h"
|
||||
|
||||
class RasterizerScene {
|
||||
|
||||
public:
|
||||
/* SHADOW ATLAS API */
|
||||
|
||||
|
@ -218,10 +219,15 @@ public:
|
|||
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
|
||||
virtual bool light_instances_can_render_shadow_cube() const { return true; }
|
||||
|
||||
virtual RID reflection_atlas_create() = 0;
|
||||
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
|
||||
|
||||
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
|
||||
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
|
||||
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
|
||||
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
|
||||
virtual void reflection_probe_instance_begin_render(RID p_instance) = 0;
|
||||
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
|
||||
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
|
||||
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
|
||||
|
||||
virtual RID gi_probe_instance_create() = 0;
|
||||
|
@ -229,7 +235,7 @@ public:
|
|||
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
|
||||
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0;
|
||||
|
||||
virtual void 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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
|
||||
virtual void set_scene_pass(uint64_t p_pass) = 0;
|
||||
|
@ -246,6 +252,9 @@ public:
|
|||
};
|
||||
|
||||
class RasterizerStorage {
|
||||
|
||||
Color default_clear_color;
|
||||
|
||||
public:
|
||||
/* TEXTURE API */
|
||||
|
||||
|
@ -620,6 +629,14 @@ public:
|
|||
|
||||
static RasterizerStorage *base_singleton;
|
||||
|
||||
void set_default_clear_color(const Color &p_color) {
|
||||
default_clear_color = p_color;
|
||||
}
|
||||
|
||||
Color get_default_clear_color() const {
|
||||
return default_clear_color;
|
||||
}
|
||||
|
||||
RasterizerStorage();
|
||||
virtual ~RasterizerStorage() {}
|
||||
};
|
||||
|
|
|
@ -614,6 +614,30 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
|
|||
uint32_t spot_count = 0;
|
||||
uint32_t decal_count = 0;
|
||||
|
||||
if (!e->instance->reflection_probe_instances.empty()) {
|
||||
|
||||
uint32_t rpi_count = e->instance->reflection_probe_instances.size();
|
||||
const RID *rpi_ptrs = e->instance->reflection_probe_instances.ptr();
|
||||
|
||||
for (uint32_t j = 0; j < rpi_count; j++) {
|
||||
if (render_pass != reflection_probe_instance_get_render_pass(rpi_ptrs[j])) {
|
||||
continue; //not rendered this frame
|
||||
}
|
||||
|
||||
RID base = reflection_probe_instance_get_probe(rpi_ptrs[j]);
|
||||
|
||||
uint32_t mask = storage->reflection_probe_get_cull_mask(base);
|
||||
if (!(mask & id.mask)) {
|
||||
continue; //masked
|
||||
}
|
||||
|
||||
if (reflection_count < 8) {
|
||||
id.omni_light_indices[omni_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]);
|
||||
reflection_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!e->instance->light_instances.empty()) {
|
||||
uint32_t light_count = e->instance->light_instances.size();
|
||||
const RID *light_ptrs = e->instance->light_instances.ptr();
|
||||
|
@ -832,12 +856,12 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
|
||||
void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
|
||||
|
||||
//CameraMatrix projection = p_cam_projection;
|
||||
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
|
||||
CameraMatrix correction;
|
||||
correction.set_depth_correction();
|
||||
correction.set_depth_correction(!p_reflection_probe.is_valid());
|
||||
CameraMatrix projection = correction * p_cam_projection;
|
||||
|
||||
//store camera into ubo
|
||||
|
@ -909,7 +933,17 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
|
|||
}
|
||||
|
||||
} else {
|
||||
if (p_render_target.is_valid()) {
|
||||
|
||||
if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
|
||||
scene_state.ubo.use_ambient_light = true;
|
||||
Color clear_color = storage->get_default_clear_color();
|
||||
clear_color = clear_color.to_linear();
|
||||
scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
|
||||
scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
|
||||
scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
|
||||
scene_state.ubo.ambient_light_color_energy[3] = 1.0;
|
||||
|
||||
} else if (p_render_target.is_valid()) {
|
||||
scene_state.ubo.use_ambient_light = true;
|
||||
Color clear_color = storage->render_target_get_clear_request_color(p_render_target);
|
||||
clear_color = clear_color.to_linear();
|
||||
|
@ -1284,11 +1318,11 @@ void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu
|
|||
|
||||
void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
|
||||
|
||||
for (uint32_t i = 0; i < p_reflection_probe_cull_count; i++) {
|
||||
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
|
||||
|
||||
RID rpi = p_reflection_probe_cull_result[i];
|
||||
|
||||
if (i >= scene_state.max_reflections) {
|
||||
if (i >= (int)scene_state.max_reflections) {
|
||||
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
|
||||
continue;
|
||||
}
|
||||
|
@ -1304,14 +1338,14 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
|
|||
reflection_ubo.box_extents[0] = extents.x;
|
||||
reflection_ubo.box_extents[1] = extents.y;
|
||||
reflection_ubo.box_extents[2] = extents.z;
|
||||
reflection_ubo.box_extents[3] = 0;
|
||||
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.box_offset[3] = 0;
|
||||
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);
|
||||
|
@ -1350,6 +1384,8 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
|
|||
Transform transform = reflection_probe_instance_get_transform(rpi);
|
||||
Transform proj = (p_camera_inverse_transform * transform).inverse();
|
||||
store_transform(proj, reflection_ubo.local_matrix);
|
||||
|
||||
reflection_probe_instance_set_render_pass(rpi, render_pass);
|
||||
}
|
||||
|
||||
if (p_reflection_probe_cull_count) {
|
||||
|
@ -1357,7 +1393,7 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas) {
|
||||
void RasterizerSceneForwardRD::_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;
|
||||
|
@ -1406,7 +1442,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
|||
light_data.shadow_color[1] = shadow_col.g;
|
||||
light_data.shadow_color[2] = shadow_col.b;
|
||||
|
||||
light_data.shadow_enabled = storage->light_has_shadow(base);
|
||||
light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
|
||||
|
||||
if (light_data.shadow_enabled) {
|
||||
|
||||
|
@ -1481,7 +1517,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
|||
|
||||
Color shadow_color = storage->light_get_shadow_color(base);
|
||||
|
||||
bool has_shadow = storage->light_has_shadow(base);
|
||||
bool has_shadow = p_using_shadows && storage->light_has_shadow(base);
|
||||
light_data.shadow_color_enabled[0] = CLAMP(uint32_t(shadow_color.r * 255), 0, 255);
|
||||
light_data.shadow_color_enabled[1] = CLAMP(uint32_t(shadow_color.g * 255), 0, 255);
|
||||
light_data.shadow_color_enabled[2] = CLAMP(uint32_t(shadow_color.b * 255), 0, 255);
|
||||
|
@ -1492,7 +1528,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
|||
light_data.atlas_rect[2] = 0;
|
||||
light_data.atlas_rect[3] = 0;
|
||||
|
||||
if (storage->light_has_shadow(base) && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
|
||||
if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
|
||||
// fill in the shadow information
|
||||
|
||||
Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
|
||||
|
@ -1540,7 +1576,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
|
||||
RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
|
||||
|
||||
|
@ -1569,8 +1605,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
|
|||
glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1605,13 +1647,17 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
|
|||
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
|
||||
alpha_framebuffer = opaque_framebuffer;
|
||||
|
||||
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
|
||||
p_environment = RID(); //no environment on interiors
|
||||
}
|
||||
|
||||
} else {
|
||||
ERR_FAIL(); //bug?
|
||||
}
|
||||
|
||||
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas);
|
||||
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
|
||||
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
|
||||
_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
|
||||
_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < p_light_cull_count; i++) {
|
||||
|
@ -1983,12 +2029,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
|
|||
} break;
|
||||
}
|
||||
} else {
|
||||
if (render_target.is_valid()) {
|
||||
|
||||
if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
|
||||
clear_color = storage->get_default_clear_color();
|
||||
} else if (render_target.is_valid()) {
|
||||
clear_color = storage->render_target_get_clear_request_color(render_target);
|
||||
}
|
||||
}
|
||||
|
||||
_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, RID());
|
||||
_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas);
|
||||
|
||||
render_list.sort_by_key(false);
|
||||
|
||||
|
@ -2236,7 +2285,7 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **
|
|||
scene_state.ubo.z_far = p_zfar;
|
||||
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
|
||||
|
||||
_setup_environment(RID(), RID(), p_projection, p_transform, true, Vector2(1, 1), RID());
|
||||
_setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID());
|
||||
|
||||
render_list.clear();
|
||||
|
||||
|
@ -2363,8 +2412,22 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
|
|||
}
|
||||
|
||||
{
|
||||
|
||||
RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID();
|
||||
RD::Uniform u;
|
||||
u.binding = 11;
|
||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
if (ref_texture.is_valid()) {
|
||||
u.ids.push_back(ref_texture);
|
||||
} else {
|
||||
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 12;
|
||||
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.ids.push_back(scene_state.light_buffer);
|
||||
uniforms.push_back(u);
|
||||
|
@ -2372,7 +2435,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
|
|||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 12;
|
||||
u.binding = 13;
|
||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
if (p_shadow_atlas.is_valid()) {
|
||||
u.ids.push_back(shadow_atlas_get_texture(p_shadow_atlas));
|
||||
|
@ -2384,7 +2447,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
|
|||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 13;
|
||||
u.binding = 14;
|
||||
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.ids.push_back(scene_state.directional_light_buffer);
|
||||
uniforms.push_back(u);
|
||||
|
@ -2392,7 +2455,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
|
|||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 14;
|
||||
u.binding = 15;
|
||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
if (directional_shadow_get_texture().is_valid()) {
|
||||
u.ids.push_back(directional_shadow_get_texture());
|
||||
|
@ -2425,18 +2488,6 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
|
|||
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
|
||||
}
|
||||
|
||||
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
|
||||
|
||||
if (textures_per_stage <= 16) {
|
||||
//ARM pretty much, and very old Intel GPUs under Linux
|
||||
scene_state.max_reflection_probes_per_instance = 4; //sad
|
||||
} else {
|
||||
//maximum 8
|
||||
scene_state.max_reflection_probes_per_instance = 8;
|
||||
}
|
||||
|
||||
defines += "\n#define MAX_REFLECTION_PROBES " + itos(scene_state.max_reflection_probes_per_instance) + "\n";
|
||||
|
||||
uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
|
||||
|
||||
{ //reflections
|
||||
|
|
|
@ -209,8 +209,10 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
|
|||
/* Scene State UBO */
|
||||
|
||||
struct ReflectionData { //should always be 128 bytes
|
||||
float box_extents[4];
|
||||
float box_offset[4];
|
||||
float box_extents[3];
|
||||
float index;
|
||||
float box_offset[3];
|
||||
uint32_t mask;
|
||||
float params[4]; // intensity, 0, interior , boxproject
|
||||
float ambient[4]; // ambient color, energy
|
||||
float local_matrix[16]; // up to here for spot and omni, rest is for directional
|
||||
|
@ -480,8 +482,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
|
|||
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
|
||||
};
|
||||
|
||||
void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
|
||||
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas);
|
||||
void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
|
||||
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
|
||||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count);
|
||||
|
@ -494,7 +496,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
|
|||
void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
|
||||
|
||||
protected:
|
||||
virtual void _render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
virtual void _render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
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);
|
||||
|
||||
public:
|
||||
|
|
|
@ -4,38 +4,17 @@
|
|||
|
||||
void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) {
|
||||
|
||||
if (rd.radiance.is_valid()) {
|
||||
//if size changes, everything must be cleared
|
||||
RD::get_singleton()->free(rd.radiance);
|
||||
//everything else gets dependency, erase, so just clean it up
|
||||
rd.radiance = RID();
|
||||
rd.layers.clear();
|
||||
rd.radiance_base_cubemap = RID();
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, bool p_quality) {
|
||||
void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer) {
|
||||
//recreate radiance and all data
|
||||
int mipmaps = Image::get_image_required_mipmaps(p_size, p_size, Image::FORMAT_RGBAH) + 1;
|
||||
if (!p_quality) {
|
||||
//use less mipmaps
|
||||
mipmaps = MIN(8, mipmaps);
|
||||
}
|
||||
|
||||
int mipmaps = p_mipmaps;
|
||||
uint32_t w = p_size, h = p_size;
|
||||
|
||||
if (sky_use_cubemap_array) {
|
||||
//array (higher quality, 6 times more memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = roughness_layers * 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.width = w;
|
||||
tf.height = h;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
rd.radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
if (p_use_array) {
|
||||
|
||||
for (int i = 0; i < roughness_layers; i++) {
|
||||
ReflectionData::Layer layer;
|
||||
|
@ -47,7 +26,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
|
|||
mm.size.width = mmw;
|
||||
mm.size.height = mmh;
|
||||
for (int k = 0; k < 6; k++) {
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, i * 6 + k, j);
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j);
|
||||
Vector<RID> fbtex;
|
||||
fbtex.push_back(mm.views[k]);
|
||||
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
|
||||
|
@ -62,17 +41,6 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
|
|||
|
||||
} else {
|
||||
//regular cubemap, lower quality (aliasing, less memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.type = RD::TEXTURE_TYPE_CUBE;
|
||||
tf.mipmaps = roughness_layers;
|
||||
tf.width = w;
|
||||
tf.height = h;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
rd.radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
ReflectionData::Layer layer;
|
||||
uint32_t mmw = w;
|
||||
uint32_t mmh = h;
|
||||
|
@ -82,7 +50,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
|
|||
mm.size.width = mmw;
|
||||
mm.size.height = mmh;
|
||||
for (int k = 0; k < 6; k++) {
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, k, j);
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j);
|
||||
Vector<RID> fbtex;
|
||||
fbtex.push_back(mm.views[k]);
|
||||
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
|
||||
|
@ -95,11 +63,14 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
|
|||
rd.layers.push_back(layer);
|
||||
}
|
||||
|
||||
rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, 0, 0, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality) {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#warning TODO, should probably use this algorithm instead. Volunteers? - https://www.ppsloan.org/publications/ggx_filtering.pdf / https://github.com/dariomanesku/cmft
|
||||
#endif
|
||||
if (sky_use_cubemap_array) {
|
||||
|
||||
if (p_quality) {
|
||||
|
@ -148,9 +119,9 @@ void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side) {
|
||||
void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side) {
|
||||
|
||||
if (sky_use_cubemap_array) {
|
||||
if (p_use_arrays) {
|
||||
|
||||
if (p_quality) {
|
||||
//render directly to the layers
|
||||
|
@ -220,6 +191,10 @@ void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
|
|||
}
|
||||
sky->radiance_size = p_radiance_size;
|
||||
_sky_invalidate(sky);
|
||||
if (sky->radiance.is_valid()) {
|
||||
RD::get_singleton()->free(sky->radiance);
|
||||
sky->radiance = RID();
|
||||
}
|
||||
_clear_reflection_data(sky->reflection);
|
||||
}
|
||||
|
||||
|
@ -242,6 +217,10 @@ void RasterizerSceneRD::sky_set_texture(RID p_sky, RID p_panorama) {
|
|||
|
||||
if (sky->panorama.is_valid()) {
|
||||
sky->panorama = RID();
|
||||
if (sky->radiance.is_valid()) {
|
||||
RD::get_singleton()->free(sky->radiance);
|
||||
sky->radiance = RID();
|
||||
}
|
||||
_clear_reflection_data(sky->reflection);
|
||||
}
|
||||
|
||||
|
@ -260,8 +239,45 @@ void RasterizerSceneRD::_update_dirty_skys() {
|
|||
|
||||
//update sky configuration if texture is missing
|
||||
|
||||
if (sky->reflection.radiance.is_null()) {
|
||||
_update_reflection_data(sky->reflection, sky->radiance_size, sky->mode == VS::SKY_MODE_QUALITY);
|
||||
if (sky->radiance.is_null()) {
|
||||
int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
|
||||
if (sky->mode != VS::SKY_MODE_QUALITY) {
|
||||
//use less mipmaps
|
||||
mipmaps = MIN(8, mipmaps);
|
||||
}
|
||||
|
||||
uint32_t w = sky->radiance_size, h = sky->radiance_size;
|
||||
|
||||
if (sky_use_cubemap_array) {
|
||||
//array (higher quality, 6 times more memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = roughness_layers * 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.width = w;
|
||||
tf.height = h;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
_update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, true, sky->radiance, 0);
|
||||
|
||||
} else {
|
||||
//regular cubemap, lower quality (aliasing, less memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.type = RD::TEXTURE_TYPE_CUBE;
|
||||
tf.mipmaps = roughness_layers;
|
||||
tf.width = w;
|
||||
tf.height = h;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
_update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, false, sky->radiance, 0);
|
||||
}
|
||||
}
|
||||
|
||||
RID panorama_texture = storage->texture_get_rd_texture(sky->panorama);
|
||||
|
@ -295,7 +311,7 @@ RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const {
|
|||
Sky *sky = sky_owner.getornull(p_sky);
|
||||
ERR_FAIL_COND_V(!sky, RID());
|
||||
|
||||
return sky->reflection.radiance;
|
||||
return sky->radiance;
|
||||
}
|
||||
|
||||
RID RasterizerSceneRD::environment_create() {
|
||||
|
@ -469,6 +485,42 @@ bool RasterizerSceneRD::is_environment(RID p_env) const {
|
|||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
RID RasterizerSceneRD::reflection_atlas_create() {
|
||||
|
||||
ReflectionAtlas ra;
|
||||
ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count");
|
||||
ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size");
|
||||
|
||||
return reflection_atlas_owner.make_rid(ra);
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
|
||||
|
||||
ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
|
||||
ERR_FAIL_COND(!ra);
|
||||
|
||||
if (ra->size == p_reflection_size && ra->count == p_reflection_count) {
|
||||
return; //no changes
|
||||
}
|
||||
|
||||
if (ra->reflection.is_valid()) {
|
||||
//clear and invalidate everything
|
||||
RD::get_singleton()->free(ra->reflection);
|
||||
ra->reflection = RID();
|
||||
|
||||
for (int i = 0; i < ra->reflections.size(); i++) {
|
||||
if (ra->reflections[i].owner.is_null()) {
|
||||
continue;
|
||||
}
|
||||
reflection_probe_release_atlas_index(ra->reflections[i].owner);
|
||||
//rp->atlasindex clear
|
||||
}
|
||||
|
||||
ra->reflections.clear();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) {
|
||||
ReflectionProbeInstance rpi;
|
||||
rpi.probe = p_probe;
|
||||
|
@ -483,6 +535,22 @@ void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance,
|
|||
rpi->dirty = true;
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) {
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!rpi);
|
||||
|
||||
if (rpi->atlas.is_null()) {
|
||||
return; //nothing to release
|
||||
}
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
|
||||
ERR_FAIL_COND(!atlas);
|
||||
ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
|
||||
atlas->reflections.write[rpi->atlas_index].owner = RID();
|
||||
rpi->atlas_index = -1;
|
||||
rpi->atlas = RID();
|
||||
}
|
||||
|
||||
bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
|
@ -496,68 +564,116 @@ bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (rpi->current_resolution != storage->reflection_probe_get_resolution(rpi->probe)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return rpi->atlas_index == -1;
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance) {
|
||||
bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) {
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!rpi);
|
||||
rpi->rendering = true;
|
||||
rpi->processing_side = 0;
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
int probe_resolution = storage->reflection_probe_get_resolution(rpi->probe);
|
||||
if (rpi->current_resolution != probe_resolution) {
|
||||
//need to re-create everything
|
||||
_clear_reflection_data(rpi->reflection);
|
||||
_update_reflection_data(rpi->reflection, probe_resolution, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE);
|
||||
return rpi->atlas.is_valid();
|
||||
}
|
||||
|
||||
rpi->current_resolution = probe_resolution;
|
||||
bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
|
||||
|
||||
if (rpi->depth_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(rpi->depth_buffer);
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
|
||||
|
||||
ERR_FAIL_COND_V(!atlas, false);
|
||||
|
||||
if (atlas->reflection.is_null()) {
|
||||
{
|
||||
//reflection atlas was unused, create:
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = 6 * atlas->count;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
|
||||
tf.mipmaps = roughness_layers;
|
||||
tf.width = atlas->size;
|
||||
tf.height = atlas->size;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
}
|
||||
{
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
tf.width = probe_resolution;
|
||||
tf.height = probe_resolution;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
rpi->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
|
||||
tf.width = atlas->size;
|
||||
tf.height = atlas->size;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
atlas->reflections.resize(atlas->count);
|
||||
for (int i = 0; i < atlas->count; i++) {
|
||||
_update_reflection_data(atlas->reflections.write[i].data, atlas->size, roughness_layers, false, atlas->reflection, i * 6);
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(rpi->reflection.layers[0].mipmaps[0].views[i]);
|
||||
fb.push_back(rpi->depth_buffer);
|
||||
rpi->render_fb[i] = RD::get_singleton()->framebuffer_create(fb);
|
||||
fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
|
||||
fb.push_back(atlas->depth_buffer);
|
||||
atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
if (rpi->atlas_index == -1) {
|
||||
for (int i = 0; i < atlas->reflections.size(); i++) {
|
||||
if (atlas->reflections[i].owner.is_null()) {
|
||||
rpi->atlas_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//find the one used last
|
||||
if (rpi->atlas_index == -1) {
|
||||
//everything is in use, find the one least used via LRU
|
||||
uint64_t pass_min = 0;
|
||||
|
||||
for (int i = 0; i < atlas->reflections.size(); i++) {
|
||||
ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.getornull(atlas->reflections[i].owner);
|
||||
if (rpi2->last_pass < pass_min) {
|
||||
pass_min = rpi2->last_pass;
|
||||
rpi->atlas_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rpi->atlas = p_reflection_atlas;
|
||||
rpi->rendering = true;
|
||||
rpi->dirty = false;
|
||||
rpi->processing_side = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) {
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
ERR_FAIL_COND_V(!rpi->rendering, false);
|
||||
ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
|
||||
|
||||
_create_reflection_from_base_mipmap(rpi->reflection, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE, rpi->processing_side);
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
|
||||
if (!atlas || rpi->atlas_index == -1) {
|
||||
//does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
|
||||
rpi->rendering = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_create_reflection_from_base_mipmap(atlas->reflections.write[rpi->atlas_index].data, false, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE, rpi->processing_side);
|
||||
|
||||
rpi->processing_side++;
|
||||
|
||||
if (rpi->processing_side == 6) {
|
||||
rpi->rendering = false;
|
||||
rpi->processing_side = 0;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -568,7 +684,9 @@ uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_insta
|
|||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, 0);
|
||||
|
||||
return rpi->current_resolution;
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
|
||||
ERR_FAIL_COND_V(!atlas, 0);
|
||||
return atlas->size;
|
||||
}
|
||||
|
||||
RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
|
||||
|
@ -576,7 +694,9 @@ RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance,
|
|||
ERR_FAIL_COND_V(!rpi, RID());
|
||||
ERR_FAIL_INDEX_V(p_index, 6, RID());
|
||||
|
||||
return rpi->render_fb[p_index];
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
|
||||
ERR_FAIL_COND_V(!atlas, RID());
|
||||
return atlas->reflections[rpi->atlas_index].fbs[p_index];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -591,8 +711,8 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
|
|||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
|
||||
ERR_FAIL_COND(!shadow_atlas);
|
||||
ERR_FAIL_COND(p_size < 0);
|
||||
|
||||
p_size = next_power_of_2(p_size);
|
||||
p_size = MAX(p_size, 1 << roughness_layers);
|
||||
|
||||
if (p_size == shadow_atlas->size)
|
||||
return;
|
||||
|
@ -1097,12 +1217,12 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
|
|||
return sky_use_cubemap_array;
|
||||
}
|
||||
|
||||
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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
|
||||
|
||||
_render_scene(rb->data, 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_environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
_render_scene(rb ? rb->data : (RenderBufferData *)NULL, 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_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
|
||||
|
@ -1289,14 +1409,21 @@ bool RasterizerSceneRD::free(RID p_rid) {
|
|||
} else if (environment_owner.owns(p_rid)) {
|
||||
//not much to delete, just free it
|
||||
environment_owner.free(p_rid);
|
||||
} else if (reflection_atlas_owner.owns(p_rid)) {
|
||||
reflection_atlas_set_size(p_rid, 0, 0);
|
||||
reflection_atlas_owner.free(p_rid);
|
||||
} else if (reflection_probe_instance_owner.owns(p_rid)) {
|
||||
//not much to delete, just free it
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
|
||||
_clear_reflection_data(rpi->reflection);
|
||||
reflection_probe_release_atlas_index(p_rid);
|
||||
reflection_probe_instance_owner.free(p_rid);
|
||||
} else if (sky_owner.owns(p_rid)) {
|
||||
_update_dirty_skys();
|
||||
Sky *sky = sky_owner.getornull(p_rid);
|
||||
if (sky->radiance.is_valid()) {
|
||||
RD::get_singleton()->free(sky->radiance);
|
||||
sky->radiance = RID();
|
||||
}
|
||||
_clear_reflection_data(sky->reflection);
|
||||
sky_owner.free(p_rid);
|
||||
} else if (light_instance_owner.owns(p_rid)) {
|
||||
|
@ -1340,7 +1467,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
|||
sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples");
|
||||
sky_ggx_samples_realtime = GLOBAL_GET("rendering/quality/reflections/ggx_samples_realtime");
|
||||
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
|
||||
sky_use_cubemap_array = false;
|
||||
// sky_use_cubemap_array = false;
|
||||
}
|
||||
|
||||
RasterizerSceneRD::~RasterizerSceneRD() {
|
||||
|
|
|
@ -15,7 +15,7 @@ protected:
|
|||
};
|
||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||
|
||||
virtual void _render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void _render_scene(RenderBufferData *p_buffer_data, 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
|
||||
|
||||
private:
|
||||
|
@ -24,7 +24,6 @@ private:
|
|||
RasterizerStorageRD *storage;
|
||||
|
||||
struct ReflectionData {
|
||||
RID radiance;
|
||||
|
||||
struct Layer {
|
||||
struct Mipmap {
|
||||
|
@ -40,13 +39,14 @@ private:
|
|||
};
|
||||
|
||||
void _clear_reflection_data(ReflectionData &rd);
|
||||
void _update_reflection_data(ReflectionData &rd, int p_size, bool p_quality);
|
||||
void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer);
|
||||
void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
|
||||
void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side);
|
||||
void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side);
|
||||
void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
|
||||
|
||||
/* SKY */
|
||||
struct Sky {
|
||||
RID radiance;
|
||||
int radiance_size = 256;
|
||||
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
|
||||
RID panorama;
|
||||
|
@ -66,22 +66,41 @@ private:
|
|||
|
||||
mutable RID_Owner<Sky> sky_owner;
|
||||
|
||||
/* REFLECTION ATLAS */
|
||||
|
||||
struct ReflectionAtlas {
|
||||
|
||||
int count = 0;
|
||||
int size = 0;
|
||||
|
||||
RID reflection;
|
||||
RID depth_buffer;
|
||||
|
||||
struct Reflection {
|
||||
RID owner;
|
||||
ReflectionData data;
|
||||
RID fbs[6];
|
||||
};
|
||||
|
||||
Vector<Reflection> reflections;
|
||||
};
|
||||
|
||||
RID_Owner<ReflectionAtlas> reflection_atlas_owner;
|
||||
|
||||
/* REFLECTION PROBE INSTANCE */
|
||||
|
||||
struct ReflectionProbeInstance {
|
||||
|
||||
RID probe;
|
||||
|
||||
ReflectionData reflection;
|
||||
RID depth_buffer;
|
||||
RID render_fb[6];
|
||||
|
||||
int current_resolution = 0;
|
||||
int atlas_index = -1;
|
||||
RID atlas;
|
||||
|
||||
bool dirty = true;
|
||||
bool rendering = false;
|
||||
int processing_side = 0;
|
||||
|
||||
uint32_t render_step = 0;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t render_index = 0;
|
||||
|
||||
Transform transform;
|
||||
|
@ -453,10 +472,20 @@ public:
|
|||
return li->light_type;
|
||||
}
|
||||
|
||||
virtual RID reflection_atlas_create();
|
||||
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count);
|
||||
_FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
|
||||
ERR_FAIL_COND_V(!atlas, RID());
|
||||
return atlas->reflection;
|
||||
}
|
||||
|
||||
virtual RID reflection_probe_instance_create(RID p_probe);
|
||||
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
|
||||
virtual void reflection_probe_release_atlas_index(RID p_instance);
|
||||
virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
|
||||
virtual void reflection_probe_instance_begin_render(RID p_instance);
|
||||
virtual bool reflection_probe_instance_has_reflection(RID p_instance);
|
||||
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas);
|
||||
virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
|
||||
|
||||
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
|
||||
|
@ -482,6 +511,19 @@ public:
|
|||
return rpi->render_index;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!rpi);
|
||||
rpi->last_pass = p_render_pass;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, 0);
|
||||
|
||||
return rpi->last_pass;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, Transform());
|
||||
|
@ -489,11 +531,11 @@ public:
|
|||
return rpi->transform;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ RID reflection_probe_instance_get_texture(RID p_instance) {
|
||||
_FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, RID());
|
||||
ERR_FAIL_COND_V(!rpi, -1);
|
||||
|
||||
return rpi->reflection.radiance;
|
||||
return rpi->atlas_index;
|
||||
}
|
||||
|
||||
RID gi_probe_instance_create() { return RID(); }
|
||||
|
@ -504,7 +546,7 @@ public:
|
|||
RID render_buffers_create();
|
||||
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
|
||||
|
||||
void 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_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
|
||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
|
||||
|
||||
|
|
|
@ -710,6 +710,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
|||
|
||||
|
||||
|
||||
|
||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
vec3 transmission,
|
||||
|
@ -781,6 +782,86 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
|||
diffuse_light, specular_light);
|
||||
}
|
||||
|
||||
void reflection_process(uint ref_index, vec3 vertex, vec3 normal,float roughness,vec3 ambient_light,vec3 specular_light,inout vec4 ambient_accum, inout vec4 reflection_accum) {
|
||||
|
||||
vec3 box_extents = reflections.data[ref_index].box_extents;
|
||||
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
|
||||
|
||||
if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 ref_vec = normalize(reflect(vertex, normal));
|
||||
|
||||
vec3 inner_pos = abs(local_pos / box_extents);
|
||||
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
//make blend more rounded
|
||||
blend = mix(length(inner_pos), blend, blend);
|
||||
blend *= blend;
|
||||
blend = max(0.0, 1.0 - blend);
|
||||
|
||||
if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
|
||||
|
||||
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
|
||||
|
||||
if (reflections.data[ref_index].params.w > 0.5) { //box project
|
||||
|
||||
vec3 nrdir = normalize(local_ref_vec);
|
||||
vec3 rbmax = (box_extents - local_pos) / nrdir;
|
||||
vec3 rbmin = (-box_extents - local_pos) / nrdir;
|
||||
|
||||
vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
|
||||
|
||||
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
||||
vec3 posonbox = local_pos + nrdir * fa;
|
||||
local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
|
||||
}
|
||||
|
||||
vec4 reflection;
|
||||
|
||||
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec,reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb;
|
||||
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
reflection.rgb = mix(specular_light, reflection.rgb, blend);
|
||||
}
|
||||
|
||||
reflection.rgb *= reflections.data[ref_index].params.x;
|
||||
reflection.a = blend;
|
||||
reflection.rgb *= reflection.a;
|
||||
|
||||
reflection_accum += reflection;
|
||||
}
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
|
||||
|
||||
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
||||
|
||||
vec4 ambient_out;
|
||||
|
||||
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec,reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
|
||||
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} else {
|
||||
|
||||
vec4 ambient_out;
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
}
|
||||
#endif //USE_LIGHTMAP
|
||||
}
|
||||
void main() {
|
||||
|
||||
#ifdef MODE_DUAL_PARABOLOID
|
||||
|
@ -976,126 +1057,28 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
//lightmap capture
|
||||
|
||||
#if 0
|
||||
|
||||
{ // process reflections
|
||||
|
||||
|
||||
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (uint i = 0; i < MAX_REFLECTION_PROBES; i++) {
|
||||
if (i >= draw_data.reflection_probe_count) {
|
||||
break;
|
||||
}
|
||||
uint reflection_probe_count = instances.data[instance_index].flags & INSTANCE_FLAGS_FORWARD_MASK;
|
||||
|
||||
uint ref_index;
|
||||
if (i<4) {
|
||||
if (i<2) {
|
||||
ref_index=draw_data.reflection_probe_indices[0];
|
||||
for (uint i = 0; i < reflection_probe_count; i++) {
|
||||
|
||||
|
||||
uint ref_index = instances.data[instance_index].reflection_probe_indices[i>>1];
|
||||
|
||||
if (bool(i&1)) {
|
||||
ref_index>>=16;
|
||||
} else {
|
||||
ref_index=draw_data.reflection_probe_indices[1];
|
||||
}
|
||||
} else {
|
||||
if (i<6) {
|
||||
ref_index=draw_data.reflection_probe_indices[2];
|
||||
} else {
|
||||
ref_index=draw_data.reflection_probe_indices[3];
|
||||
}
|
||||
}
|
||||
ref_index>>=(i&1)*16;
|
||||
ref_index&=0xFFFF;
|
||||
|
||||
vec3 box_extents = reflections.data[ref_index].box_extents.xyz;
|
||||
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
|
||||
|
||||
if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 ref_vec = normalize(reflect(vertex, normal));
|
||||
|
||||
vec3 inner_pos = abs(local_pos / box_extents);
|
||||
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
//make blend more rounded
|
||||
blend = mix(length(inner_pos), blend, blend);
|
||||
blend *= blend;
|
||||
blend = max(0.0, 1.0 - blend);
|
||||
|
||||
if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
|
||||
|
||||
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
|
||||
|
||||
if (reflections.data[ref_index].params.w > 0.5) { //box project
|
||||
|
||||
vec3 nrdir = normalize(local_ref_vec);
|
||||
vec3 rbmax = (box_extents - local_pos) / nrdir;
|
||||
vec3 rbmin = (-box_extents - local_pos) / nrdir;
|
||||
|
||||
vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
|
||||
|
||||
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
||||
vec3 posonbox = local_pos + nrdir * fa;
|
||||
local_ref_vec = posonbox - reflections.data[ref_index].box_offset.xyz;
|
||||
}
|
||||
|
||||
vec4 reflection;
|
||||
|
||||
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
|
||||
|
||||
float lod,layer_blend;
|
||||
layer_blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
|
||||
reflection.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod)).rgb;
|
||||
reflection.rgb = mix(reflection.rgb,texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod+1)).rgb,layer_blend);
|
||||
|
||||
#else
|
||||
reflection.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
|
||||
|
||||
#endif
|
||||
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
reflection.rgb = mix(specular_light, reflection.rgb, blend);
|
||||
}
|
||||
|
||||
reflection.rgb *= reflections.data[ref_index].params.x;
|
||||
reflection.a = blend;
|
||||
reflection.rgb *= reflection.a;
|
||||
|
||||
reflection_accum += reflection;
|
||||
}
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
|
||||
|
||||
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
||||
|
||||
vec4 ambient_out;
|
||||
|
||||
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
|
||||
ambient_out.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, MAX_ROUGHNESS_LOD)).rgb;
|
||||
#else
|
||||
ambient_out.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_amb_vec, MAX_ROUGHNESS_LOD).rgb;
|
||||
#endif //USE_RADIANCE_CUBEMAP_ARRAY
|
||||
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} else {
|
||||
|
||||
vec4 ambient_out;
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
}
|
||||
#endif //USE_LIGHTMAP
|
||||
reflection_process(ref_index,vertex,normal,roughness,ambient_light,specular_light,ambient_accum,reflection_accum);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1111,7 +1094,7 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
|
||||
}
|
||||
#endif //0
|
||||
|
||||
{
|
||||
|
||||
#if defined(DIFFUSE_TOON)
|
||||
|
|
|
@ -145,8 +145,10 @@ layout(set=0,binding=9,std430) buffer Instances {
|
|||
|
||||
struct ReflectionData {
|
||||
|
||||
vec4 box_extents;
|
||||
vec4 box_offset;
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
vec4 params; // intensity, 0, interior , boxproject
|
||||
vec4 ambient; // ambient color, energy
|
||||
mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
|
@ -157,6 +159,7 @@ layout(set=0,binding=10,std140) uniform ReflectionProbeData {
|
|||
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
|
||||
} reflections;
|
||||
|
||||
layout(set=0,binding=11) uniform textureCubeArray reflection_atlas;
|
||||
|
||||
struct LightData { //this structure needs to be 128 bits
|
||||
|
||||
|
@ -172,11 +175,11 @@ struct LightData { //this structure needs to be 128 bits
|
|||
mat4 shadow_matrix;
|
||||
};
|
||||
|
||||
layout(set=0,binding=11,std140) uniform Lights {
|
||||
layout(set=0,binding=12,std140) uniform Lights {
|
||||
LightData data[MAX_LIGHT_DATA_STRUCTS];
|
||||
} lights;
|
||||
|
||||
layout(set=0,binding=12) uniform texture2D shadow_atlas;
|
||||
layout(set=0,binding=13) uniform texture2D shadow_atlas;
|
||||
|
||||
struct DirectionalLightData {
|
||||
|
||||
|
@ -198,11 +201,11 @@ struct DirectionalLightData {
|
|||
|
||||
};
|
||||
|
||||
layout(set=0,binding=13,std140) uniform DirectionalLights {
|
||||
layout(set=0,binding=14,std140) uniform DirectionalLights {
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
} directional_lights;
|
||||
|
||||
layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
|
||||
layout(set=0,binding=15) uniform texture2D directional_shadow_atlas;
|
||||
|
||||
/*
|
||||
layout(set=0,binding=15,std430) buffer Skeletons {
|
||||
|
|
|
@ -268,7 +268,7 @@ RID VisualServerScene::scenario_create() {
|
|||
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
|
||||
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
|
||||
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
|
||||
|
||||
scenario->reflection_atlas = VSG::scene_render->reflection_atlas_create();
|
||||
return scenario_rid;
|
||||
}
|
||||
|
||||
|
@ -293,6 +293,13 @@ void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_
|
|||
scenario->fallback_environment = p_environment;
|
||||
}
|
||||
|
||||
void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
|
||||
|
||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
||||
ERR_FAIL_COND(!scenario);
|
||||
VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
|
||||
}
|
||||
|
||||
/* INSTANCING API */
|
||||
|
||||
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
|
||||
|
@ -510,6 +517,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
|
|||
}
|
||||
} break;
|
||||
case VS::INSTANCE_REFLECTION_PROBE: {
|
||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
|
||||
VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
|
||||
|
||||
} break;
|
||||
case VS::INSTANCE_GI_PROBE: {
|
||||
|
@ -1808,7 +1817,7 @@ void VisualServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface> &
|
|||
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
};
|
||||
|
||||
void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe) {
|
||||
void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
|
||||
// Note, in stereo rendering:
|
||||
// - p_cam_transform will be a transform in the middle of our two eyes
|
||||
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
||||
|
@ -1894,11 +1903,13 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
reflection_probe->reflection_dirty = false;
|
||||
}
|
||||
|
||||
if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
|
||||
reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
|
||||
reflection_probe_cull_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ins->base_type == VS::INSTANCE_GI_PROBE && ins->visible) {
|
||||
|
||||
|
@ -2015,7 +2026,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
//check shadow..
|
||||
|
||||
if (light) {
|
||||
if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
|
||||
if (p_using_shadows && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
|
||||
lights_with_shadow[directional_shadow_count++] = E->get();
|
||||
}
|
||||
//add to list
|
||||
|
@ -2031,7 +2042,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
}
|
||||
}
|
||||
|
||||
{ //setup shadow maps
|
||||
if (p_using_shadows) { //setup shadow maps
|
||||
|
||||
//SortArray<Instance*,_InstanceLightsort> sorter;
|
||||
//sorter.sort(light_cull_result,light_cull_count);
|
||||
|
@ -2148,7 +2159,7 @@ void VisualServerScene::_render_scene(RID p_render_buffers, const Transform p_ca
|
|||
|
||||
/* PROCESS GEOMETRY AND DRAW SCENE */
|
||||
|
||||
VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
}
|
||||
|
||||
void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||
|
@ -2162,7 +2173,7 @@ void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario,
|
|||
environment = scenario->environment;
|
||||
else
|
||||
environment = scenario->fallback_environment;
|
||||
VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, RID(), 0);
|
||||
VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2176,18 +2187,28 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
|
|||
|
||||
if (p_step == 0) {
|
||||
|
||||
VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance);
|
||||
if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
|
||||
return true; //all full
|
||||
}
|
||||
}
|
||||
|
||||
if (p_step >= 0 && p_step < 6) {
|
||||
|
||||
static const Vector3 view_normals[6] = {
|
||||
Vector3(-1, 0, 0),
|
||||
Vector3(+1, 0, 0),
|
||||
Vector3(0, -1, 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, 0, +1)
|
||||
Vector3(0, -1, 0),
|
||||
Vector3(0, -1, 0)
|
||||
};
|
||||
|
||||
Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base);
|
||||
|
@ -2203,15 +2224,6 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
|
|||
CameraMatrix cm;
|
||||
cm.set_perspective(90, 1, 0.01, max_distance);
|
||||
|
||||
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 local_view;
|
||||
local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);
|
||||
|
||||
|
@ -2219,12 +2231,13 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
|
|||
|
||||
RID shadow_atlas;
|
||||
|
||||
if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) {
|
||||
bool use_shadows = VSG::storage->reflection_probe_renders_shadows(p_instance->base);
|
||||
if (use_shadows) {
|
||||
|
||||
shadow_atlas = scenario->reflection_probe_shadow_atlas;
|
||||
}
|
||||
|
||||
_prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance);
|
||||
_prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
|
||||
_render_scene(RID(), xform, cm, false, RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
|
||||
|
||||
} else {
|
||||
|
@ -3465,6 +3478,7 @@ bool VisualServerScene::free(RID p_rid) {
|
|||
instance_set_scenario(scenario->instances.first()->self()->self, RID());
|
||||
}
|
||||
VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
|
||||
VSG::scene_render->free(scenario->reflection_atlas);
|
||||
scenario_owner.free(p_rid);
|
||||
memdelete(scenario);
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ public:
|
|||
RID environment;
|
||||
RID fallback_environment;
|
||||
RID reflection_probe_shadow_atlas;
|
||||
RID reflection_atlas;
|
||||
|
||||
SelfList<Instance>::List instances;
|
||||
|
||||
|
@ -131,6 +132,7 @@ public:
|
|||
virtual void scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode);
|
||||
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
|
||||
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
|
||||
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
|
||||
|
||||
/* INSTANCING API */
|
||||
|
||||
|
@ -475,7 +477,7 @@ public:
|
|||
|
||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
|
||||
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
|||
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
|
||||
int scenario_canvas_max_layer = 0;
|
||||
|
||||
Color bgcolor = clear_color;
|
||||
Color bgcolor = VSG::storage->get_default_clear_color();
|
||||
|
||||
if (!p_viewport->hide_canvas && !p_viewport->disable_environment && VSG::scene->scenario_owner.owns(p_viewport->scenario)) {
|
||||
|
||||
|
@ -295,7 +295,7 @@ void VisualServerViewport::draw_viewports() {
|
|||
#endif
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
clear_color = GLOBAL_GET("rendering/environment/default_clear_color");
|
||||
set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color"));
|
||||
}
|
||||
|
||||
//sort viewports
|
||||
|
@ -719,7 +719,7 @@ bool VisualServerViewport::free(RID p_rid) {
|
|||
}
|
||||
|
||||
void VisualServerViewport::set_default_clear_color(const Color &p_color) {
|
||||
clear_color = p_color;
|
||||
VSG::storage->set_default_clear_color(p_color);
|
||||
}
|
||||
|
||||
VisualServerViewport::VisualServerViewport() {
|
||||
|
|
|
@ -148,7 +148,6 @@ public:
|
|||
Vector<Viewport *> active_viewports;
|
||||
|
||||
private:
|
||||
Color clear_color;
|
||||
void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
|
||||
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
|
||||
|
||||
|
|
|
@ -2302,6 +2302,9 @@ VisualServer::VisualServer() {
|
|||
GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128);
|
||||
GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime", 64);
|
||||
GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime.mobile", 16);
|
||||
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256);
|
||||
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128);
|
||||
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64);
|
||||
|
||||
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
|
||||
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);
|
||||
|
|
Loading…
Reference in New Issue