summaryrefslogtreecommitdiff
path: root/servers/visual
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual')
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp147
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.h53
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp82
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h4
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp1053
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h172
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp2
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h1
-rw-r--r--servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl80
-rw-r--r--servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl38
-rw-r--r--servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl37
-rw-r--r--servers/visual/rasterizer_rd/shaders/sky.glsl90
-rw-r--r--servers/visual/shader_types.cpp36
-rw-r--r--servers/visual/visual_server_raster.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
16 files changed, 1397 insertions, 404 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 2670a750d7..84eda2d80c 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -56,7 +56,7 @@ public:
virtual RID sky_create() = 0;
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, VS::SkyMode p_samples) = 0;
- virtual void sky_set_texture(RID p_sky, RID p_panorama) = 0;
+ virtual void sky_set_material(RID p_sky, RID p_material) = 0;
/* ENVIRONMENT API */
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
index 6b6c750fd3..355ebfa409 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -248,57 +248,6 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuff
RD::get_singleton()->draw_list_end();
}
-void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
-
- zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
-
- roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
- roughness.push_constant.roughness = p_roughness;
- roughness.push_constant.sample_count = p_sample_count;
- roughness.push_constant.use_direct_write = p_roughness == 0.0;
- roughness.push_constant.face_size = p_size;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipelines[p_source_is_panorama ? CUBEMAP_ROUGHNESS_SOURCE_PANORAMA : CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
-
- int x_groups = (p_size - 1) / 8 + 1;
- int y_groups = (p_size - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RasterizerEffectsRD::render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler) {
-
- zeromem(&sky.push_constant, sizeof(SkyPushConstant));
-
- sky.push_constant.proj[0] = p_camera.matrix[2][0];
- sky.push_constant.proj[1] = p_camera.matrix[0][0];
- sky.push_constant.proj[2] = p_camera.matrix[2][1];
- sky.push_constant.proj[3] = p_camera.matrix[1][1];
- sky.push_constant.alpha = p_alpha;
- sky.push_constant.depth = 1.0;
- sky.push_constant.multiplier = p_multipler;
- store_transform_3x3(p_orientation, sky.push_constant.orientation);
-
- RD::DrawListID draw_list = p_list;
-
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, sky.pipeline.get_render_pipeline(RD::INVALID_ID, p_fb_format));
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_panorama), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky.push_constant, sizeof(SkyPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
-}
-
void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -756,12 +705,38 @@ void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness,
RD::get_singleton()->compute_list_end();
}
-void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, bool p_source_is_panorama, RID p_dest_cubemap, const Size2i &p_size) {
+void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+
+ zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
+
+ roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
+ roughness.push_constant.roughness = p_roughness;
+ roughness.push_constant.sample_count = p_sample_count;
+ roughness.push_constant.use_direct_write = p_roughness == 0.0;
+ roughness.push_constant.face_size = p_size;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
+
+ int x_groups = (p_size - 1) / 8 + 1;
+ int y_groups = (p_size - 1) / 8 + 1;
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
cubemap_downsampler.push_constant.face_size = p_size.x;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipelines[p_source_is_panorama ? CUBEMAP_DOWNSAMPLER_SOURCE_PANORAMA : CUBEMAP_DOWNSAMPLER_SOURCE_CUBEMAP]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1);
@@ -805,6 +780,41 @@ void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_des
RD::get_singleton()->compute_list_end();
}
+void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
+
+ SkyPushConstant sky_push_constant;
+
+ zeromem(&sky_push_constant, sizeof(SkyPushConstant));
+
+ sky_push_constant.proj[0] = p_camera.matrix[2][0];
+ sky_push_constant.proj[1] = p_camera.matrix[0][0];
+ sky_push_constant.proj[2] = p_camera.matrix[2][1];
+ sky_push_constant.proj[3] = p_camera.matrix[1][1];
+ sky_push_constant.position[0] = p_position.x;
+ sky_push_constant.position[1] = p_position.y;
+ sky_push_constant.position[2] = p_position.z;
+ sky_push_constant.multiplier = p_multiplier;
+ sky_push_constant.time = p_time;
+ store_transform_3x3(p_orientation, sky_push_constant.orientation);
+
+ RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
+
+ RD::DrawListID draw_list = p_list;
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
+
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_lights, 3);
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+}
+
RasterizerEffectsRD::RasterizerEffectsRD() {
{
@@ -838,31 +848,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
{
// Initialize roughness
Vector<String> cubemap_roughness_modes;
- cubemap_roughness_modes.push_back("\n#define MODE_SOURCE_PANORAMA\n");
- cubemap_roughness_modes.push_back("\n#define MODE_SOURCE_CUBEMAP\n");
+ cubemap_roughness_modes.push_back("");
roughness.shader.initialize(cubemap_roughness_modes);
roughness.shader_version = roughness.shader.version_create();
- for (int i = 0; i < CUBEMAP_ROUGHNESS_SOURCE_MAX; i++) {
- roughness.pipelines[i] = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, i));
- }
- }
-
- {
- // Initialize sky
- Vector<String> sky_modes;
- sky_modes.push_back("");
- sky.shader.initialize(sky_modes);
-
- sky.shader_version = sky.shader.version_create();
-
- RD::PipelineDepthStencilState depth_stencil_state;
-
- depth_stencil_state.enable_depth_test = true;
- depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
-
- sky.pipeline.setup(sky.shader.version_get_shader(sky.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0));
}
{
@@ -999,15 +990,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
{
//Initialize cubemap downsampler
Vector<String> cubemap_downsampler_modes;
- cubemap_downsampler_modes.push_back("\n#define MODE_SOURCE_PANORAMA\n");
- cubemap_downsampler_modes.push_back("\n#define MODE_SOURCE_CUBEMAP\n");
+ cubemap_downsampler_modes.push_back("");
cubemap_downsampler.shader.initialize(cubemap_downsampler_modes);
cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create();
- for (int i = 0; i < CUBEMAP_DOWNSAMPLER_SOURCE_MAX; i++) {
- cubemap_downsampler.pipelines[i] = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, i));
- }
+ cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0));
}
{
@@ -1091,7 +1079,6 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
RD::get_singleton()->free(filter.coefficient_buffer);
blur.shader.version_free(blur.shader_version);
roughness.shader.version_free(roughness.shader_version);
- sky.shader.version_free(sky.shader_version);
tonemap.shader.version_free(tonemap.shader_version);
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
copy.shader.version_free(copy.shader_version);
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
index fbf6b39ecb..562a7b674b 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
@@ -32,7 +32,7 @@
#define RASTERIZER_EFFECTS_RD_H
#include "core/math/camera_matrix.h"
-#include "render_pipeline_vertex_format_cache_rd.h"
+#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h"
@@ -41,7 +41,6 @@
#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h"
-#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/ssao.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/ssao_minify.glsl.gen.h"
@@ -116,12 +115,6 @@ class RasterizerEffectsRD {
} blur;
- enum CubemapRoughnessSource {
- CUBEMAP_ROUGHNESS_SOURCE_PANORAMA,
- CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP,
- CUBEMAP_ROUGHNESS_SOURCE_MAX
- };
-
struct CubemapRoughnessPushConstant {
uint32_t face_id;
uint32_t sample_count;
@@ -136,26 +129,9 @@ class RasterizerEffectsRD {
CubemapRoughnessPushConstant push_constant;
CubemapRoughnessShaderRD shader;
RID shader_version;
- RID pipelines[CUBEMAP_ROUGHNESS_SOURCE_MAX];
+ RID pipeline;
} roughness;
- struct SkyPushConstant {
- float orientation[12];
- float proj[4];
- float multiplier;
- float alpha;
- float depth;
- float pad;
- };
-
- struct Sky {
-
- SkyPushConstant push_constant;
- SkyShaderRD shader;
- RID shader_version;
- RenderPipelineVertexFormatCacheRD pipeline;
- } sky;
-
enum TonemapMode {
TONEMAP_MODE_NORMAL,
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
@@ -359,12 +335,6 @@ class RasterizerEffectsRD {
} roughness_limiter;
- enum CubemapDownsamplerSource {
- CUBEMAP_DOWNSAMPLER_SOURCE_PANORAMA,
- CUBEMAP_DOWNSAMPLER_SOURCE_CUBEMAP,
- CUBEMAP_DOWNSAMPLER_SOURCE_MAX
- };
-
struct CubemapDownsamplerPushConstant {
uint32_t face_size;
float pad[3];
@@ -375,7 +345,7 @@ class RasterizerEffectsRD {
CubemapDownsamplerPushConstant push_constant;
CubemapDownsamplerShaderRD shader;
RID shader_version;
- RID pipelines[CUBEMAP_DOWNSAMPLER_SOURCE_MAX];
+ RID pipeline;
} cubemap_downsampler;
@@ -399,6 +369,15 @@ class RasterizerEffectsRD {
} filter;
+ struct SkyPushConstant {
+ float orientation[12];
+ float proj[4];
+ float position[3];
+ float multiplier;
+ float time;
+ float pad[3];
+ };
+
RID default_sampler;
RID default_mipmap_sampler;
RID index_buffer;
@@ -421,8 +400,7 @@ public:
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
- void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
+ void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
@@ -468,11 +446,12 @@ public:
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
- void cubemap_downsample(RID p_source_cubemap, bool p_source_is_panorama, RID p_dest_cubemap, const Size2i &p_size);
+ void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
+ void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
RasterizerEffectsRD();
~RasterizerEffectsRD();
};
-#endif // EFFECTS_RD_H
+#endif // !RASTERIZER_EFFECTS_RD_H
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index 0a3105b143..1bc181bea3 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -76,6 +76,8 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra
}
}
}
+
+/* SCENE SHADER */
void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
//compile
@@ -345,6 +347,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const Strin
default_texture_params[p_name] = p_texture;
}
}
+
void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
@@ -377,6 +380,7 @@ bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_
bool RasterizerSceneHighEndRD::ShaderData::is_animated() const {
return false;
}
+
bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const {
return false;
}
@@ -499,6 +503,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
+
RasterizerSceneHighEndRD::MaterialData::~MaterialData() {
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
@@ -1290,38 +1295,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
}
}
-void RasterizerSceneHighEndRD::_draw_sky(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha) {
-
- ERR_FAIL_COND(!is_environment(p_environment));
-
- RID sky = environment_get_sky(p_environment);
- ERR_FAIL_COND(!sky.is_valid());
- RID panorama = sky_get_panorama_texture_rd(sky);
- ERR_FAIL_COND(!panorama.is_valid());
- Basis sky_transform = environment_get_sky_orientation(p_environment);
- sky_transform.invert();
-
- float multiplier = environment_get_bg_energy(p_environment);
- float custom_fov = environment_get_sky_custom_fov(p_environment);
- // Camera
- CameraMatrix camera;
-
- if (custom_fov) {
-
- float near_plane = p_projection.get_z_near();
- float far_plane = p_projection.get_z_far();
- float aspect = p_projection.get_aspect();
-
- camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
-
- } else {
- camera = p_projection;
- }
-
- sky_transform = p_transform.basis * sky_transform;
- storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
-}
-
void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
@@ -1460,6 +1433,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
uint32_t light_count = 0;
scene_state.ubo.directional_light_count = 0;
+ sky_scene_state.directional_light_count = 0;
for (int i = 0; i < p_light_cull_count; i++) {
@@ -1535,6 +1509,27 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.fade_to = -light_data.shadow_split_offsets[3];
}
+ // Copy to SkyDirectionalLightData
+ if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) {
+
+ SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count];
+
+ Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
+
+ sky_light_data.direction[0] = world_direction.x;
+ sky_light_data.direction[1] = world_direction.y;
+ sky_light_data.direction[2] = -world_direction.z;
+
+ sky_light_data.energy = light_data.energy / Math_PI;
+
+ sky_light_data.color[0] = light_data.color[0];
+ sky_light_data.color[1] = light_data.color[1];
+ sky_light_data.color[2] = light_data.color[2];
+
+ sky_light_data.enabled = true;
+ sky_scene_state.directional_light_count++;
+ }
+
scene_state.ubo.directional_light_count++;
} break;
case VS::LIGHT_SPOT:
@@ -1705,6 +1700,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
scene_state.ubo.viewport_size[1] = vp_he.y;
Size2 screen_pixel_size;
+ Size2i screen_size;
RID opaque_framebuffer;
RID depth_framebuffer;
RID alpha_framebuffer;
@@ -1715,6 +1711,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
if (render_buffer) {
screen_pixel_size.width = 1.0 / render_buffer->width;
screen_pixel_size.height = 1.0 / render_buffer->height;
+ screen_size.x = render_buffer->width;
+ screen_size.y = render_buffer->height;
opaque_framebuffer = render_buffer->color_fb;
@@ -1755,6 +1753,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
screen_pixel_size.width = 1.0 / resolution;
screen_pixel_size.height = 1.0 / resolution;
+ screen_size.x = resolution;
+ screen_size.y = resolution;
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_reflection_probe, p_reflection_probe_pass);
@@ -1809,7 +1809,19 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
case VS::ENV_BG_SKY: {
RID sky = environment_get_sky(p_environment);
if (sky.is_valid()) {
+
+ RENDER_TIMESTAMP("Setup Sky");
+ CameraMatrix projection = p_cam_projection;
+ if (p_reflection_probe.is_valid()) {
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ projection = correction * p_cam_projection;
+ }
+
+ _setup_sky(p_environment, p_cam_transform.origin, screen_size);
+ _update_sky(p_environment, projection, p_cam_transform);
radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET);
+
draw_sky = true;
}
} break;
@@ -1902,9 +1914,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
projection = correction * p_cam_projection;
}
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, projection, p_cam_transform, 1.0);
- RD::get_singleton()->draw_list_end();
+ _draw_sky(can_continue, opaque_framebuffer, p_environment, projection, p_cam_transform);
if (using_separate_specular && !can_continue) {
//can't continue, so close the buffers
@@ -2371,7 +2381,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
singleton = this;
storage = p_storage;
- /* SHADER */
+ /* SCENE SHADER */
{
String defines;
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
index 647b8f225e..960b95ee86 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -48,7 +48,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
MATERIAL_UNIFORM_SET = 5
};
- /* Shader */
+ /* Scene Shader */
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
@@ -569,8 +569,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
- 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(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
index 457f6970c8..41682d3135 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -55,7 +55,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
uint32_t w = p_size, h = p_size;
if (p_use_array) {
- int layers = p_low_quality ? 7 : roughness_layers;
+ int layers = p_low_quality ? 8 : roughness_layers;
for (int i = 0; i < layers; i++) {
ReflectionData::Layer layer;
@@ -84,7 +84,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
}
} else {
- mipmaps = p_low_quality ? 7 : mipmaps;
+ mipmaps = p_low_quality ? 8 : mipmaps;
//regular cubemap, lower quality (aliasing, less memory)
ReflectionData::Layer layer;
uint32_t mmw = w;
@@ -139,87 +139,41 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
}
}
-void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality) {
+void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) {
- if (sky_use_cubemap_array) {
-
- if (p_quality) {
- //render directly to the layers
- for (int i = 0; i < rd.layers.size(); i++) {
- storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[i].views[0], 10, sky_ggx_samples_quality, float(i) / (rd.layers.size() - 1.0), rd.layers[i].mipmaps[0].size.x);
- }
- } else {
- // Use fast filtering. Render directly to base mip levels
- storage->get_effects()->cubemap_downsample(p_panorama, true, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
+ storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
- for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
- storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, false, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
- }
- Vector<RID> views;
- for (int i = 0; i < rd.layers.size(); i++) {
- views.push_back(rd.layers[i].views[0]);
- }
+ for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
+ storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
+ }
- storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, true);
+ Vector<RID> views;
+ if (p_use_arrays) {
+ for (int i = 1; i < rd.layers.size(); i++) {
+ views.push_back(rd.layers[i].views[0]);
}
} else {
-
- if (p_quality) {
- //render directly to the layers
- for (int i = 0; i < rd.layers[0].mipmaps.size(); i++) {
- storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[0].views[i], 10, sky_ggx_samples_quality, float(i) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[i].size.x);
- }
- } else {
- // Use fast filtering. Render directly to each mip level
- storage->get_effects()->cubemap_downsample(p_panorama, true, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
-
- for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
- storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, false, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
- }
- storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, rd.layers[0].views, false);
+ for (int i = 1; i < rd.layers[0].views.size(); i++) {
+ views.push_back(rd.layers[0].views[i]);
}
}
+
+ storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, p_use_arrays);
}
-void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side, int p_base_layer) {
+void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) {
if (p_use_arrays) {
- if (p_quality) {
- //render directly to the layers
- storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x);
- } else {
-
- storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, false, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
-
- for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
- storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, false, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
- }
- Vector<RID> views;
- for (int i = 0; i < rd.layers.size(); i++) {
- views.push_back(rd.layers[i].views[0]);
- }
-
- storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, true);
- }
+ //render directly to the layers
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x);
} else {
- if (p_quality) {
-
- storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], false, rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x);
- } else {
-
- storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, false, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
-
- for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
- storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, false, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
- }
- storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, rd.layers[0].views, false);
- }
+ storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x);
}
}
-void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd, bool p_quality) {
+void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) {
if (sky_use_cubemap_array) {
@@ -258,9 +212,9 @@ void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
}
sky->radiance_size = p_radiance_size;
- if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 128) {
- WARN_PRINT("Realtime Skies can only use a radiance size of 128. Radiance size will be set to 128 internally.");
- sky->radiance_size = 128;
+ if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 256) {
+ WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
+ sky->radiance_size = 256;
}
_sky_invalidate(sky);
@@ -281,9 +235,9 @@ void RasterizerSceneRD::sky_set_mode(RID p_sky, VS::SkyMode p_mode) {
sky->mode = p_mode;
- if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 128) {
- WARN_PRINT("Realtime Skies can only use a radiance size of 128. Radiance size will be set to 128 internally.");
- sky_set_radiance_size(p_sky, 128);
+ if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 256) {
+ WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
+ sky_set_radiance_size(p_sky, 256);
}
_sky_invalidate(sky);
@@ -294,26 +248,10 @@ void RasterizerSceneRD::sky_set_mode(RID p_sky, VS::SkyMode p_mode) {
_clear_reflection_data(sky->reflection);
}
-void RasterizerSceneRD::sky_set_texture(RID p_sky, RID p_panorama) {
-
+void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) {
Sky *sky = sky_owner.getornull(p_sky);
ERR_FAIL_COND(!sky);
-
- 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);
- }
-
- sky->panorama = p_panorama;
-
- if (!sky->panorama.is_valid())
- return; //cleared
-
- _sky_invalidate(sky);
+ sky->material = p_material;
}
void RasterizerSceneRD::_update_dirty_skys() {
@@ -321,13 +259,20 @@ void RasterizerSceneRD::_update_dirty_skys() {
while (sky) {
+ bool texture_set_dirty = false;
//update sky configuration if texture is missing
if (sky->radiance.is_null()) {
int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
uint32_t w = sky->radiance_size, h = sky->radiance_size;
- int layers = sky->mode == VS::SKY_MODE_REALTIME ? 7 : roughness_layers;
+ int layers = roughness_layers;
+ if (sky->mode == VS::SKY_MODE_REALTIME) {
+ layers = 8;
+ if (roughness_layers != 8) {
+ WARN_PRINT("When using REALTIME skies, roughness_layers should be set to 8 in the project settings for best quality reflections");
+ }
+ }
if (sky_use_cubemap_array) {
//array (higher quality, 6 times more memory)
@@ -359,15 +304,50 @@ void RasterizerSceneRD::_update_dirty_skys() {
_update_reflection_data(sky->reflection, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == VS::SKY_MODE_REALTIME);
}
+ texture_set_dirty = true;
+ }
+
+ // Create subpass buffers if they havent been created already
+ if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tformat.width = sky->screen_size.x / 2;
+ tformat.height = sky->screen_size.y / 2;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D;
+
+ sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ Vector<RID> texs;
+ texs.push_back(sky->half_res_pass);
+ sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs);
+ texture_set_dirty = true;
+ }
+
+ if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tformat.width = sky->screen_size.x / 4;
+ tformat.height = sky->screen_size.y / 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D;
+
+ sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ Vector<RID> texs;
+ texs.push_back(sky->quarter_res_pass);
+ sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs);
+ texture_set_dirty = true;
+ }
+
+ if (texture_set_dirty) {
+ for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) {
+ if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) {
+ RD::get_singleton()->free(sky->texture_uniform_sets[i]);
+ sky->texture_uniform_sets[i] = RID();
+ }
+ }
}
- RID panorama_texture = storage->texture_get_rd_texture(sky->panorama);
-
- if (panorama_texture.is_valid()) {
- //is there a panorama texture?
- _create_reflection_from_panorama(sky->reflection, panorama_texture, sky->mode == VS::SKY_MODE_QUALITY);
- _update_reflection_mipmaps(sky->reflection, sky->mode == VS::SKY_MODE_QUALITY);
- }
+ sky->reflection.dirty = true;
Sky *next = sky->dirty_list;
sky->dirty_list = nullptr;
@@ -378,16 +358,6 @@ void RasterizerSceneRD::_update_dirty_skys() {
dirty_sky_list = nullptr;
}
-RID RasterizerSceneRD::sky_get_panorama_texture_rd(RID p_sky) const {
-
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND_V(!sky, RID());
- if (sky->panorama.is_null()) {
- return RID();
- }
-
- return storage->texture_get_rd_texture(sky->panorama, true);
-}
RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const {
Sky *sky = sky_owner.getornull(p_sky);
ERR_FAIL_COND_V(!sky, RID());
@@ -419,6 +389,693 @@ RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader,
return sky->uniform_set;
}
+RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) {
+
+ if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) {
+ return p_sky->texture_uniform_sets[p_version];
+ }
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ if (p_sky->radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
+ u.ids.push_back(p_sky->radiance);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1; // half res
+ if (p_sky->half_res_pass.is_valid() && (p_version != SKY_TEXTURE_SET_HALF_RES) && (p_version < SKY_TEXTURE_SET_CUBEMAP_HALF_RES0 || p_version > SKY_TEXTURE_SET_CUBEMAP_HALF_RES5)) {
+ if (p_version >= SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0) {
+ u.ids.push_back(p_sky->reflection.layers[0].mipmaps[1].views[p_version - SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0]);
+ } else if (p_version >= SKY_TEXTURE_SET_CUBEMAP0) {
+ u.ids.push_back(p_sky->reflection.layers[0].mipmaps[1].views[p_version - SKY_TEXTURE_SET_CUBEMAP0]);
+ } else {
+ u.ids.push_back(p_sky->half_res_pass);
+ }
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2; // quarter res
+ if (p_sky->quarter_res_pass.is_valid() && (p_version != SKY_TEXTURE_SET_QUARTER_RES) && (p_version < SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0 || p_version > SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES5)) {
+ if (p_version >= SKY_TEXTURE_SET_CUBEMAP_HALF_RES0) {
+ u.ids.push_back(p_sky->reflection.layers[0].mipmaps[2].views[p_version - SKY_TEXTURE_SET_CUBEMAP_HALF_RES0]);
+ } else if (p_version >= SKY_TEXTURE_SET_CUBEMAP0) {
+ u.ids.push_back(p_sky->reflection.layers[0].mipmaps[2].views[p_version - SKY_TEXTURE_SET_CUBEMAP0]);
+ } else {
+ u.ids.push_back(p_sky->quarter_res_pass);
+ }
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+
+ p_sky->texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
+ return p_sky->texture_uniform_sets[p_version];
+}
+
+RID RasterizerSceneRD::sky_get_material(RID p_sky) const {
+ Sky *sky = sky_owner.getornull(p_sky);
+ ERR_FAIL_COND_V(!sky, RID());
+
+ return sky->material;
+}
+
+void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
+
+ ERR_FAIL_COND(!is_environment(p_environment));
+
+ Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
+ ERR_FAIL_COND(!sky);
+
+ RID sky_material = sky_get_material(environment_get_sky(p_environment));
+
+ SkyMaterialData *material = NULL;
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = NULL;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ Basis sky_transform = environment_get_sky_orientation(p_environment);
+ sky_transform.invert();
+
+ float multiplier = environment_get_bg_energy(p_environment);
+ float custom_fov = environment_get_sky_custom_fov(p_environment);
+ // Camera
+ CameraMatrix camera;
+
+ if (custom_fov) {
+
+ float near_plane = p_projection.get_z_near();
+ float far_plane = p_projection.get_z_far();
+ float aspect = p_projection.get_aspect();
+
+ camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
+
+ } else {
+ camera = p_projection;
+ }
+
+ sky_transform = p_transform.basis * sky_transform;
+
+ if (shader_data->uses_quarter_res) {
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
+
+ RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_QUARTER_RES);
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ storage->get_effects()->render_sky(draw_list, time, sky->quarter_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (shader_data->uses_half_res) {
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
+
+ RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_HALF_RES);
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ storage->get_effects()->render_sky(draw_list, time, sky->half_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
+
+ RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_BACKGROUND);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ storage->get_effects()->render_sky(draw_list, time, p_fb, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+}
+
+void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size) {
+
+ ERR_FAIL_COND(!is_environment(p_environment));
+
+ Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
+ ERR_FAIL_COND(!sky);
+
+ RID sky_material = sky_get_material(environment_get_sky(p_environment));
+
+ SkyMaterialData *material = NULL;
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = NULL;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ // Invalidate supbass buffers if screen size changes
+ if (sky->screen_size != p_screen_size) {
+ sky->screen_size = p_screen_size;
+ sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x;
+ sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y;
+ if (shader_data->uses_half_res) {
+ if (sky->half_res_pass.is_valid()) {
+ RD::get_singleton()->free(sky->half_res_pass);
+ sky->half_res_pass = RID();
+ }
+ _sky_invalidate(sky);
+ }
+ if (shader_data->uses_quarter_res) {
+ if (sky->quarter_res_pass.is_valid()) {
+ RD::get_singleton()->free(sky->quarter_res_pass);
+ sky->quarter_res_pass = RID();
+ }
+ _sky_invalidate(sky);
+ }
+ }
+
+ // Create new subpass buffers if necessary
+ if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) ||
+ (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) ||
+ sky->radiance.is_null()) {
+ _sky_invalidate(sky);
+ _update_dirty_skys();
+ }
+
+ if (shader_data->uses_time && time - sky->prev_time > 0.00001) {
+
+ sky->prev_time = time;
+ sky->reflection.dirty = true;
+ VisualServerRaster::redraw_request();
+ }
+
+ if (material != sky->prev_material) {
+
+ sky->prev_material = material;
+ sky->reflection.dirty = true;
+ }
+
+ if (material->uniform_set_updated) {
+
+ material->uniform_set_updated = false;
+ sky->reflection.dirty = true;
+ }
+
+ if (!p_position.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
+
+ sky->prev_position = p_position;
+ sky->reflection.dirty = true;
+ }
+
+ if (shader_data->uses_light || sky_scene_state.light_uniform_set.is_null()) {
+ // Check whether the directional_light_buffer changes
+ bool light_data_dirty = false;
+
+ if (sky_scene_state.directional_light_count != sky_scene_state.last_frame_directional_light_count) {
+ light_data_dirty = true;
+ for (uint32_t i = sky_scene_state.directional_light_count; i < sky_scene_state.max_directional_lights; i++) {
+ sky_scene_state.directional_lights[i].enabled = false;
+ }
+ }
+ if (!light_data_dirty) {
+ for (uint32_t i = 0; i < sky_scene_state.directional_light_count; i++) {
+ if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] ||
+ sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] ||
+ sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] ||
+ sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy ||
+ sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] ||
+ sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] ||
+ sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] ||
+ sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled) {
+ light_data_dirty = true;
+ break;
+ }
+ }
+ }
+
+ if (light_data_dirty || sky_scene_state.light_uniform_set.is_null()) {
+
+ RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights, true);
+
+ if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.light_uniform_set);
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(sky_scene_state.directional_light_buffer);
+ uniforms.push_back(u);
+ }
+
+ sky_scene_state.light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_LIGHTS);
+
+ RasterizerSceneRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights;
+ sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights;
+ sky_scene_state.directional_lights = temp;
+ sky_scene_state.last_frame_directional_light_count = sky_scene_state.directional_light_count;
+ sky->reflection.dirty = true;
+ }
+ }
+}
+
+void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
+
+ ERR_FAIL_COND(!is_environment(p_environment));
+
+ Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
+ ERR_FAIL_COND(!sky);
+
+ RID sky_material = sky_get_material(environment_get_sky(p_environment));
+
+ SkyMaterialData *material = NULL;
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = NULL;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ float multiplier = environment_get_bg_energy(p_environment);
+
+ // Update radiance cubemap
+ if (sky->reflection.dirty) {
+
+ static const Vector3 view_normals[6] = {
+ Vector3(+1, 0, 0),
+ Vector3(-1, 0, 0),
+ Vector3(0, +1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1)
+ };
+ static const Vector3 view_up[6] = {
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1),
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0)
+ };
+
+ CameraMatrix cm;
+ cm.set_perspective(90, 1, 0.01, 10.0);
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ cm = correction * cm;
+
+ if (shader_data->uses_quarter_res) {
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+ RD::DrawListID cubemap_draw_list;
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = _get_sky_textures(sky, SkyTextureSetVersion(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0 + i));
+
+ cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ if (shader_data->uses_half_res) {
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+ RD::DrawListID cubemap_draw_list;
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = _get_sky_textures(sky, SkyTextureSetVersion(SKY_TEXTURE_SET_CUBEMAP_HALF_RES0 + i));
+
+ cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ RD::DrawListID cubemap_draw_list;
+ RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = _get_sky_textures(sky, SkyTextureSetVersion(SKY_TEXTURE_SET_CUBEMAP0 + i));
+
+ cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+ if (sky_use_cubemap_array) {
+ if (sky->mode == VS::SKY_MODE_QUALITY) {
+ for (int i = 1; i < sky->reflection.layers.size(); i++) {
+ _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i);
+ }
+ } else {
+ _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
+ }
+
+ _update_reflection_mipmaps(sky->reflection);
+ } else {
+ if (sky->mode == VS::SKY_MODE_QUALITY) {
+ for (int i = 1; i < sky->reflection.layers[0].mipmaps.size(); i++) {
+ _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i);
+ }
+ } else {
+ _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
+ }
+ }
+
+ sky->reflection.dirty = false;
+ }
+}
+
+/* SKY SHADER */
+
+void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code == String()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompilerRD::IdentifierActions actions;
+
+ uses_time = false;
+ uses_half_res = false;
+ uses_quarter_res = false;
+ uses_position = false;
+ uses_light = false;
+
+ actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+ actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+ // TODO: Consider using usage flags instead
+ //actions.usage_flag_pointers["HALF_RES_TEXTURE"] = &uses_half_res;
+ //actions.usage_flag_pointers["QUARTER_RES_TEXTURE"] = &uses_quarter_res;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+ actions.usage_flag_pointers["POSITION"] = &uses_position;
+ actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
+
+ actions.uniforms = &uniforms;
+
+ RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton;
+
+ Error err = scene_singleton->sky_shader.compiler.compile(VS::SHADER_SKY, code, &actions, path, gen_code);
+
+ ERR_FAIL_COND(err != OK);
+
+ if (version.is_null()) {
+ version = scene_singleton->sky_shader.shader.version_create();
+ }
+
+#if 0
+ print_line("**compiling shader:");
+ print_line("**defines:\n");
+ for (int i = 0; i < gen_code.defines.size(); i++) {
+ print_line(gen_code.defines[i]);
+ }
+ print_line("\n**uniforms:\n" + gen_code.uniforms);
+ // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
+ // print_line("\n**vertex_code:\n" + gen_code.vertex);
+ print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
+ print_line("\n**fragment_code:\n" + gen_code.fragment);
+ print_line("\n**light_code:\n" + gen_code.light);
+#endif
+
+ scene_singleton->sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
+ ERR_FAIL_COND(!scene_singleton->sky_shader.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ //update pipelines
+
+ for (int i = 0; i < SKY_VERSION_MAX; i++) {
+
+ RD::PipelineDepthStencilState depth_stencil_state;
+ depth_stencil_state.enable_depth_test = true;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+
+ RID shader_variant = scene_singleton->sky_shader.shader.version_get_shader(version, i);
+ pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ valid = true;
+}
+
+void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+ if (!p_texture.is_valid()) {
+ default_texture_params.erase(p_name);
+ } else {
+ default_texture_params[p_name] = p_texture;
+ }
+}
+
+void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
+ pi.name = E->get();
+ p_param_list->push_back(pi);
+ }
+}
+
+bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool RasterizerSceneRD::SkyShaderData::is_animated() const {
+ return false;
+}
+
+bool RasterizerSceneRD::SkyShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant RasterizerSceneRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ }
+ return Variant();
+}
+
+RasterizerSceneRD::SkyShaderData::SkyShaderData() {
+ valid = false;
+}
+
+RasterizerSceneRD::SkyShaderData::~SkyShaderData() {
+ RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton;
+ ERR_FAIL_COND(!scene_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ scene_singleton->sky_shader.shader.version_free(version);
+ }
+}
+
+RasterizerStorageRD::ShaderData *RasterizerSceneRD::_create_sky_shader_func() {
+ SkyShaderData *shader_data = memnew(SkyShaderData);
+ return shader_data;
+}
+
+void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+
+ RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton;
+
+ uniform_set_updated = true;
+
+ if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(shader_data->ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+
+ update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
+ }
+
+ uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+
+ update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+
+ if (shader_data->ubo_size) {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (uint32_t i = 0; i < tex_uniform_count; i++) {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + i;
+ u.ids.push_back(textures[i]);
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
+}
+
+RasterizerSceneRD::SkyMaterialData::~SkyMaterialData() {
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func(SkyShaderData *p_shader) {
+ SkyMaterialData *material_data = memnew(SkyMaterialData);
+ material_data->shader_data = p_shader;
+ material_data->last_frame = false;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
RID RasterizerSceneRD::environment_create() {
return environment_owner.make_rid(Environent());
@@ -729,12 +1386,12 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
- if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 128) {
- WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 128. Please update the atlas size in the ProjectSettings.");
- reflection_atlas_set_size(p_reflection_atlas, 128, atlas->count);
+ if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
+ WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
+ reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 7) {
+ if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
// Invalidate reflection atlas, need to regenerate
RD::get_singleton()->free(atlas->reflection);
atlas->reflection = RID();
@@ -751,7 +1408,7 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
if (atlas->reflection.is_null()) {
int mipmaps = MIN(roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
- mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS ? 7 : mipmaps; // always use 7 mipmaps with real time filtering
+ mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
{
//reflection atlas was unused, create:
RD::TextureFormat tf;
@@ -835,8 +1492,17 @@ bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instanc
return false;
}
+ if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ // Using real time reflections, all roughness is done in one step
+ _create_reflection_fast_filter(atlas->reflections.write[rpi->atlas_index].data, false);
+ rpi->rendering = false;
+ rpi->processing_side = 0;
+ rpi->processing_layer = 1;
+ return true;
+ }
+
if (rpi->processing_layer > 1) {
- _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, 10, rpi->processing_layer);
+ _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, 10, rpi->processing_layer);
rpi->processing_layer++;
if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
rpi->rendering = false;
@@ -847,15 +1513,7 @@ bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instanc
return false;
} else {
- _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_layer);
- }
-
- if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) {
- // Using real time reflections, all roughness is done in one step
- rpi->rendering = false;
- rpi->processing_side = 0;
- rpi->processing_layer = 1;
- return true;
+ _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, rpi->processing_side, rpi->processing_layer);
}
rpi->processing_side++;
@@ -3053,11 +3711,32 @@ bool RasterizerSceneRD::free(RID 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);
+
+ if (sky->uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(sky->uniform_buffer);
+ sky->uniform_buffer = RID();
+ }
+
+ if (sky->half_res_pass.is_valid()) {
+ RD::get_singleton()->free(sky->half_res_pass);
+ sky->half_res_pass = RID();
+ }
+
+ if (sky->quarter_res_pass.is_valid()) {
+ RD::get_singleton()->free(sky->quarter_res_pass);
+ sky->quarter_res_pass = RID();
+ }
+
+ if (sky->material.is_valid()) {
+ storage->free(sky->material);
+ }
+
sky_owner.free(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
@@ -3098,6 +3777,7 @@ void RasterizerSceneRD::update() {
}
void RasterizerSceneRD::set_time(double p_time, double p_step) {
+ time = p_time;
time_step = p_step;
}
@@ -3114,8 +3794,11 @@ float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const {
return screen_space_roughness_limiter_curve;
}
+RasterizerSceneRD *RasterizerSceneRD::singleton = NULL;
+
RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
storage = p_storage;
+ singleton = this;
roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers");
sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples");
@@ -3207,6 +3890,116 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
}
}
+ /* SKY SHADER */
+
+ {
+ // Start with the directional lights for the sky
+ sky_scene_state.max_directional_lights = 4;
+ uint32_t directional_light_buffer_size = sky_scene_state.max_directional_lights * sizeof(SkyDirectionalLightData);
+ sky_scene_state.directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
+ sky_scene_state.last_frame_directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
+ sky_scene_state.last_frame_directional_light_count = sky_scene_state.max_directional_lights + 1;
+ sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
+
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n";
+
+ // Initialize sky
+ Vector<String> sky_modes;
+ sky_modes.push_back("\n#define AT_CUBEMAP_PASS false\n#define AT_HALF_RES_PASS false\n#define AT_QUARTER_RES_PASS false\n"); // Full size
+ sky_modes.push_back("\n#define AT_CUBEMAP_PASS false\n#define AT_HALF_RES_PASS true\n#define AT_QUARTER_RES_PASS false\n"); // Half Res
+ sky_modes.push_back("\n#define AT_CUBEMAP_PASS false\n#define AT_HALF_RES_PASS false\n#define AT_QUARTER_RES_PASS true\n"); // Quarter res
+ sky_modes.push_back("\n#define AT_CUBEMAP_PASS true\n#define AT_HALF_RES_PASS false\n#define AT_QUARTER_RES_PASS false\n"); // Cubemap
+ sky_shader.shader.initialize(sky_modes, defines);
+ }
+
+ // register our shader funds
+ storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+
+ {
+ ShaderCompilerRD::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "color";
+ actions.renames["ALPHA"] = "alpha";
+ actions.renames["EYEDIR"] = "cube_normal";
+ actions.renames["POSITION"] = "params.position_multiplier.xyz";
+ actions.renames["SKY_COORDS"] = "panorama_coords";
+ actions.renames["SCREEN_UV"] = "uv";
+ actions.renames["TIME"] = "params.time";
+ actions.renames["HALF_RES_TEXTURE"] = "half_res";
+ actions.renames["QUARTER_RES_TEXTURE"] = "quarter_res";
+ actions.renames["RADIANCE"] = "radiance";
+ actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled";
+ actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction";
+ actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].energy";
+ actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color";
+ actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled";
+ actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction";
+ actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].energy";
+ actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color";
+ actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled";
+ actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction";
+ actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].energy";
+ actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color";
+ actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled";
+ actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction";
+ actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].energy";
+ actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color";
+ actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
+ actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
+ actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
+ actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
+ actions.custom_samplers["SUBPASS2"] = "material_samplers[1]";
+ actions.custom_samplers["SUBPASS4"] = "material_samplers[1]";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = 1;
+ actions.base_uniform_string = "material.";
+ actions.base_varying_index = 10;
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+
+ sky_shader.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for sky shader
+ sky_shader.default_shader = storage->shader_create();
+ storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = mix(vec3(0.3), vec3(0.2, 0.4, 0.9), smoothstep(0.0, 0.05, EYEDIR.y)); } \n");
+ sky_shader.default_material = storage->material_create();
+ storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+
+ SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 0;
+ u.ids.resize(12);
+ RID *ids_ptr = u.ids.ptrw();
+ ids_ptr[0] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ uniforms.push_back(u);
+ }
+
+ sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS);
+ }
+
camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape"))));
camera_effects_set_dof_blur_quality(VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter"));
environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
@@ -3222,8 +4015,22 @@ RasterizerSceneRD::~RasterizerSceneRD() {
RD::get_singleton()->free(E->get().cubemap);
}
+ if (sky_scene_state.sampler_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.sampler_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.sampler_uniform_set);
+ }
+ if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.light_uniform_set);
+ }
+
RD::get_singleton()->free(gi_probe_lights_uniform);
giprobe_debug_shader.version_free(giprobe_debug_shader_version);
giprobe_shader.version_free(giprobe_lighting_shader_version);
memdelete_arr(gi_probe_lights);
+ SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY);
+ sky_shader.shader.version_free(md->shader_data->version);
+ RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
+ memdelete_arr(sky_scene_state.directional_lights);
+ memdelete_arr(sky_scene_state.last_frame_directional_lights);
+ storage->free(sky_shader.default_shader);
+ storage->free(sky_shader.default_material);
}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
index 0fa853f2df..e779854327 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -36,6 +36,7 @@
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h"
+#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rendering_device.h"
class RasterizerSceneRD : public RasterizerScene {
@@ -47,6 +48,29 @@ public:
};
protected:
+ double time;
+
+ // Skys need less info from Directional Lights than the normal shaders
+ struct SkyDirectionalLightData {
+
+ float direction[3];
+ float energy;
+ float color[3];
+ uint32_t enabled;
+ };
+
+ struct SkySceneState {
+
+ SkyDirectionalLightData *directional_lights;
+ SkyDirectionalLightData *last_frame_directional_lights;
+ uint32_t max_directional_lights;
+ uint32_t directional_light_count;
+ uint32_t last_frame_directional_light_count;
+ RID directional_light_buffer;
+ RID sampler_uniform_set;
+ RID light_uniform_set;
+ } sky_scene_state;
+
struct RenderBufferData {
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
@@ -69,9 +93,14 @@ protected:
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
+ void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size);
+ void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
+ void _draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
+
private:
VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
double time_step = 0;
+ static RasterizerSceneRD *singleton;
int roughness_layers;
@@ -102,31 +131,160 @@ private:
DownsampleLayer downsampled_layer;
RID coefficient_buffer;
+ bool dirty = true;
+
Vector<Layer> layers;
};
void _clear_reflection_data(ReflectionData &rd);
void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality);
- void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
- void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side, int p_base_layer);
- void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
+ void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays);
+ void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer);
+ void _update_reflection_mipmaps(ReflectionData &rd);
+
+ /* Sky shader */
+
+ enum SkyVersion {
+ SKY_VERSION_BACKGROUND,
+ SKY_VERSION_HALF_RES,
+ SKY_VERSION_QUARTER_RES,
+ SKY_VERSION_CUBEMAP,
+ SKY_VERSION_MAX
+ };
+
+ struct SkyShader {
+ SkyShaderRD shader;
+ ShaderCompilerRD compiler;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+ } sky_shader;
+
+ struct SkyShaderData : public RasterizerStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX];
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, RID> default_texture_params;
+
+ bool uses_time;
+ bool uses_position;
+ bool uses_half_res;
+ bool uses_quarter_res;
+ bool uses_light;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ SkyShaderData();
+ virtual ~SkyShaderData();
+ };
+
+ RasterizerStorageRD::ShaderData *_create_sky_shader_func();
+ static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() {
+ return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_shader_func();
+ };
+
+ struct SkyMaterialData : public RasterizerStorageRD::MaterialData {
+ uint64_t last_frame;
+ SkyShaderData *shader_data;
+ RID uniform_buffer;
+ RID uniform_set;
+ Vector<RID> texture_cache;
+ Vector<uint8_t> ubo_data;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~SkyMaterialData();
+ };
+
+ RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
+ return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
+ };
+
+ enum SkyTextureSetVersion {
+ SKY_TEXTURE_SET_BACKGROUND,
+ SKY_TEXTURE_SET_HALF_RES,
+ SKY_TEXTURE_SET_QUARTER_RES,
+ SKY_TEXTURE_SET_CUBEMAP0,
+ SKY_TEXTURE_SET_CUBEMAP1,
+ SKY_TEXTURE_SET_CUBEMAP2,
+ SKY_TEXTURE_SET_CUBEMAP3,
+ SKY_TEXTURE_SET_CUBEMAP4,
+ SKY_TEXTURE_SET_CUBEMAP5,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES0,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES1,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES2,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES3,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES4,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES5,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES1,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES2,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES3,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES4,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES5,
+ SKY_TEXTURE_SET_MAX
+ };
+
+ enum SkySet {
+ SKY_SET_SAMPLERS,
+ SKY_SET_MATERIAL,
+ SKY_SET_TEXTURES,
+ SKY_SET_LIGHTS,
+ SKY_SET_MAX
+ };
/* SKY */
struct Sky {
RID radiance;
+ RID half_res_pass;
+ RID half_res_framebuffer;
+ RID quarter_res_pass;
+ RID quarter_res_framebuffer;
+ Size2i screen_size;
+
+ RID texture_uniform_sets[SKY_TEXTURE_SET_MAX];
RID uniform_set;
- int radiance_size = 128;
+
+ RID material;
+ RID uniform_buffer;
+
+ int radiance_size = 256;
+
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
- RID panorama;
+
ReflectionData reflection;
bool dirty = false;
Sky *dirty_list = nullptr;
+
+ //State to track when radiance cubemap needs updating
+ SkyMaterialData *prev_material;
+ Vector3 prev_position;
+ float prev_time;
};
Sky *dirty_sky_list = nullptr;
void _sky_invalidate(Sky *p_sky);
void _update_dirty_skys();
+ RID _get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version);
uint32_t sky_ggx_samples_quality;
bool sky_use_cubemap_array;
@@ -647,11 +805,11 @@ public:
RID sky_create();
void sky_set_radiance_size(RID p_sky, int p_radiance_size);
void sky_set_mode(RID p_sky, VS::SkyMode p_mode);
- void sky_set_texture(RID p_sky, RID p_panorama);
+ void sky_set_material(RID p_sky, RID p_material);
- RID sky_get_panorama_texture_rd(RID p_sky) const;
RID sky_get_radiance_texture_rd(RID p_sky) const;
RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const;
+ RID sky_get_material(RID p_sky) const;
/* ENVIRONMENT API */
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
index b8d7a9dcf4..6e7f0aac07 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -881,6 +881,8 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
new_type = SHADER_TYPE_PARTICLES;
else if (mode_string == "spatial")
new_type = SHADER_TYPE_3D;
+ else if (mode_string == "sky")
+ new_type = SHADER_TYPE_SKY;
else
new_type = SHADER_TYPE_MAX;
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
index 9bc4beab6e..410cd4adb4 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
@@ -44,6 +44,7 @@ public:
SHADER_TYPE_2D,
SHADER_TYPE_3D,
SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
SHADER_TYPE_MAX
};
diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl
index b9cb0e848c..9f3ecf6053 100644
--- a/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl
@@ -30,13 +30,7 @@ VERSION_DEFINES
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
/* clang-format on */
-#ifdef MODE_SOURCE_PANORAMA
-layout(set = 0, binding = 0) uniform sampler2D source_panorama;
-#endif
-
-#ifdef MODE_SOURCE_CUBEMAP
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
-#endif
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
@@ -83,32 +77,6 @@ float calcWeight(float u, float v) {
return val * sqrt(val);
}
-#ifdef MODE_SOURCE_PANORAMA
-
-vec4 texturePanorama(vec3 normal, sampler2D pano) {
-
- vec2 st = vec2(
- atan(normal.x, -normal.z),
- acos(normal.y));
-
- if (st.x < 0.0)
- st.x += M_PI * 2.0;
-
- st /= vec2(M_PI * 2.0, M_PI);
-
- return textureLod(pano, st, 0.0);
-}
-
-#endif
-
-vec4 get_texture(vec3 p_dir) {
-#ifdef MODE_SOURCE_PANORAMA
- return texturePanorama(normalize(p_dir), source_panorama);
-#else
- return textureLod(source_cubemap, normalize(p_dir), 0.0);
-#endif
-}
-
void main() {
uvec3 id = gl_GlobalInvocationID;
uint face_size = params.face_size;
@@ -138,81 +106,81 @@ void main() {
switch (id.z) {
case 0:
get_dir_0(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_0(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_0(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_0(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 1:
get_dir_1(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_1(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_1(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_1(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 2:
get_dir_2(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_2(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_2(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_2(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 3:
get_dir_3(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_3(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_3(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_3(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 4:
get_dir_4(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_4(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_4(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_4(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
default:
get_dir_5(dir, u0, v0);
- color = get_texture(dir) * weights[0];
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_5(dir, u1, v0);
- color += get_texture(dir) * weights[1];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_5(dir, u0, v1);
- color += get_texture(dir) * weights[2];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_5(dir, u1, v1);
- color += get_texture(dir) * weights[3];
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
}
imageStore(dest_cubemap, ivec3(id), color);
diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl
index dd06647d3d..e0b0899dfa 100644
--- a/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl
+++ b/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl
@@ -262,28 +262,66 @@ void main() {
// write color
color.xyz = max(vec3(0.0), color.xyz);
color.w = 1.0;
+#ifdef USE_TEXTURE_ARRAY
+ id.xy *= uvec2(2, 2);
+#endif
switch (level) {
case 0:
imageStore(dest_cubemap0, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap0, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
case 1:
imageStore(dest_cubemap1, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap1, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
case 2:
imageStore(dest_cubemap2, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap2, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
case 3:
imageStore(dest_cubemap3, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap3, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
case 4:
imageStore(dest_cubemap4, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap4, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
case 5:
imageStore(dest_cubemap5, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap5, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
default:
imageStore(dest_cubemap6, ivec3(id), color);
+#ifdef USE_TEXTURE_ARRAY
+ imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
+ imageStore(dest_cubemap6, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
+ imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
+#endif
break;
}
}
diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl
index 3dba143e56..e85996fa1a 100644
--- a/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl
@@ -10,13 +10,7 @@ VERSION_DEFINES
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
/* clang-format on */
-#ifdef MODE_SOURCE_PANORAMA
-layout(set = 0, binding = 0) uniform sampler2D source_panorama;
-#endif
-
-#ifdef MODE_SOURCE_CUBEMAP
layout(set = 0, binding = 0) uniform samplerCube source_cube;
-#endif
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
@@ -115,24 +109,6 @@ vec2 Hammersley(uint i, uint N) {
return vec2(float(i) / float(N), radicalInverse_VdC(i));
}
-#ifdef MODE_SOURCE_PANORAMA
-
-vec4 texturePanorama(vec3 normal, sampler2D pano) {
-
- vec2 st = vec2(
- atan(normal.x, -normal.z),
- acos(normal.y));
-
- if (st.x < 0.0)
- st.x += M_PI * 2.0;
-
- st /= vec2(M_PI * 2.0, M_PI);
-
- return textureLod(pano, st, 0.0);
-}
-
-#endif
-
void main() {
uvec3 id = gl_GlobalInvocationID;
id.z += params.face_id;
@@ -144,15 +120,7 @@ void main() {
if (params.use_direct_write) {
-#ifdef MODE_SOURCE_PANORAMA
- imageStore(dest_cubemap, ivec3(id), vec4(texturePanorama(N, source_panorama).rgb, 1.0));
-#endif
-
-#ifdef MODE_SOURCE_CUBEMAP
imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
-
-#endif
-
} else {
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -167,13 +135,8 @@ void main() {
float ndotl = clamp(dot(N, L), 0.0, 1.0);
if (ndotl > 0.0) {
-#ifdef MODE_SOURCE_PANORAMA
- sum.rgb += texturePanorama(L, source_panorama).rgb * ndotl;
-#endif
-#ifdef MODE_SOURCE_CUBEMAP
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
-#endif
sum.a += ndotl;
}
}
diff --git a/servers/visual/rasterizer_rd/shaders/sky.glsl b/servers/visual/rasterizer_rd/shaders/sky.glsl
index 28fd2883c3..b73f9345e7 100644
--- a/servers/visual/rasterizer_rd/shaders/sky.glsl
+++ b/servers/visual/rasterizer_rd/shaders/sky.glsl
@@ -11,10 +11,8 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
vec4 proj;
- float multiplier;
- float alpha;
- float depth;
- float pad;
+ vec4 position_multiplier;
+ float time;
}
params;
@@ -22,7 +20,7 @@ void main() {
vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
uv_interp = base_arr[gl_VertexIndex];
- gl_Position = vec4(uv_interp, params.depth, 1.0);
+ gl_Position = vec4(uv_interp, 1.0, 1.0);
}
/* clang-format off */
@@ -37,43 +35,91 @@ VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
/* clang-format on */
-layout(set = 0, binding = 0) uniform sampler2D source_panorama;
-
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
vec4 proj;
- float multiplier;
- float alpha;
- float depth;
- float pad;
+ vec4 position_multiplier;
+ float time; //TODO consider adding vec2 screen res, and float radiance size
}
params;
-vec4 texturePanorama(sampler2D pano, vec3 normal) {
+layout(set = 0, binding = 0) uniform sampler material_samplers[12];
+
+#ifdef USE_MATERIAL_UNIFORMS
+layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
+ /* clang-format off */
+
+MATERIAL_UNIFORMS
- vec2 st = vec2(
- atan(normal.x, normal.z),
- acos(normal.y));
+ /* clang-format on */
+} material;
+#endif
- if (st.x < 0.0)
- st.x += M_PI * 2.0;
+layout(set = 2, binding = 0) uniform textureCube radiance;
+layout(set = 2, binding = 1) uniform texture2D half_res;
+layout(set = 2, binding = 2) uniform texture2D quarter_res;
- st /= vec2(M_PI * 2.0, M_PI);
+struct DirectionalLightData {
+ vec3 direction;
+ float energy;
+ vec3 color;
+ bool enabled;
+};
- return texture(pano, st);
+layout(set = 3, binding = 0, std140) uniform DirectionalLights {
+ DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
+directional_lights;
+
+/* clang-format off */
+
+FRAGMENT_SHADER_GLOBALS
+
+/* clang-format on */
layout(location = 0) out vec4 frag_color;
void main() {
vec3 cube_normal;
- cube_normal.z = -1000000.0;
+ cube_normal.z = -1.0;
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w;
cube_normal = mat3(params.orientation) * cube_normal;
cube_normal.z = -cube_normal.z;
+ cube_normal = normalize(cube_normal);
+
+ vec2 uv = uv_interp * 0.5 + 0.5;
+
+ vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
+
+ if (panorama_coords.x < 0.0) {
+ panorama_coords.x += M_PI * 2.0;
+ }
+
+ panorama_coords /= vec2(M_PI * 2.0, M_PI);
+
+ vec3 color = vec3(0.0, 0.0, 0.0);
+ float alpha = 1.0; // Only available to subpasses
+
+// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in..
+#ifndef REALLYINCLUDETHIS
+ {
+ /* clang-format off */
+
+LIGHT_SHADER_CODE
+
+ /* clang-format on */
+ }
+#endif
+ {
+ /* clang-format off */
+
+FRAGMENT_SHADER_CODE
+
+ /* clang-format on */
+ }
- frag_color.rgb = texturePanorama(source_panorama, normalize(cube_normal.xyz)).rgb;
- frag_color.a = params.alpha;
+ frag_color.rgb = color * params.position_multiplier.w;
+ frag_color.a = alpha;
}
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 631925e770..7307f7527a 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -285,7 +285,43 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_velocity");
shader_modes[VS::SHADER_PARTICLES].modes.push_back("keep_data");
+ /************ SKY **************************/
+
+ shader_modes[VS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_QUARTER_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_CUBEMAP_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+
+ shader_modes[VS::SHADER_SKY].modes.push_back("use_half_res_pass");
+ shader_modes[VS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
+
shader_types.insert("spatial");
shader_types.insert("canvas_item");
shader_types.insert("particles");
+ shader_types.insert("sky");
}
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 09b34ce25c..b6afbbff93 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -507,7 +507,7 @@ public:
BIND0R(RID, sky_create)
BIND2(sky_set_radiance_size, RID, int)
BIND2(sky_set_mode, RID, SkyMode)
- BIND2(sky_set_texture, RID, RID)
+ BIND2(sky_set_material, RID, RID)
BIND0R(RID, environment_create)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 8f4df6a0e2..0d4683e43d 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -419,7 +419,7 @@ public:
FUNCRID(sky)
FUNC2(sky_set_radiance_size, RID, int)
FUNC2(sky_set_mode, RID, SkyMode)
- FUNC2(sky_set_texture, RID, RID)
+ FUNC2(sky_set_material, RID, RID)
/* ENVIRONMENT API */