Reflection probes working

This commit is contained in:
Juan Linietsky 2019-09-09 17:50:51 -03:00
parent 69e83e4815
commit 9d7b7f931b
14 changed files with 527 additions and 284 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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() {}
};

View File

@ -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

View File

@ -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:

View File

@ -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() {

View File

@ -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);

View File

@ -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)

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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() {

View File

@ -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);

View File

@ -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);