diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2020-03-22 20:03:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-22 20:03:35 +0100 |
commit | ed9a0d0484411e631b0cc927e46dc234054d5ae5 (patch) | |
tree | e4c66055fb9e63bf80a9d6b7ec6a359e24781387 /servers | |
parent | 7acdf74a6a87c5a2e91b13a5060ae5ba9d4438a1 (diff) | |
parent | 61a74739ca2d201e7e057d85aa99ae68f0500c33 (diff) |
Merge pull request #37179 from clayjohn/VULKAN-sky-shader
Implement Sky Shaders
Diffstat (limited to 'servers')
18 files changed, 1403 insertions, 408 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 */ diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 1506561952..b50ad89b1e 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1578,7 +1578,7 @@ void VisualServer::_bind_methods() { #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create); - ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "panorama"), &VisualServer::sky_set_texture); + ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &VisualServer::sky_set_material); #endif ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create); ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code); @@ -1971,6 +1971,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(SHADER_SPATIAL); BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); BIND_ENUM_CONSTANT(SHADER_PARTICLES); + BIND_ENUM_CONSTANT(SHADER_SKY); BIND_ENUM_CONSTANT(SHADER_MAX); BIND_ENUM_CONSTANT(ARRAY_VERTEX); @@ -2311,13 +2312,13 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled (Fastest),PCF5,PCF13 (Slowest)")); - GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 6); + GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8); GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true); GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false); GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024); GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128); GLOBAL_DEF("rendering/quality/reflections/fast_filter_high_quality", false); - GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 128); + GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256); GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128); GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64); diff --git a/servers/visual_server.h b/servers/visual_server.h index 4bb1c1a080..dfe5e7feed 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -160,6 +160,7 @@ public: SHADER_SPATIAL, SHADER_CANVAS_ITEM, SHADER_PARTICLES, + SHADER_SKY, SHADER_MAX }; @@ -681,7 +682,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, SkyMode p_mode) = 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 */ |