diff options
author | clayjohn <claynjohn@gmail.com> | 2020-03-19 17:32:19 -0700 |
---|---|---|
committer | clayjohn <claynjohn@gmail.com> | 2020-03-21 20:43:44 -0700 |
commit | 61a74739ca2d201e7e057d85aa99ae68f0500c33 (patch) | |
tree | 73f170a76bb138f01d2df825798d6c4109b81cc8 /servers | |
parent | c3fee7ba6cdefd285255b9e1198bc1fdf585b1ac (diff) |
Working sky shader implementation
Diffstat (limited to 'servers')
-rw-r--r-- | servers/visual/rasterizer.h | 3 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp | 106 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_effects_rd.h | 30 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp | 404 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h | 86 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp | 1063 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_scene_rd.h | 175 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl | 80 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl | 38 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl | 37 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/sky.glsl | 70 | ||||
-rw-r--r-- | servers/visual/shader_types.cpp | 32 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 3 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 3 | ||||
-rw-r--r-- | servers/visual_server.cpp | 7 | ||||
-rw-r--r-- | servers/visual_server.h | 3 |
16 files changed, 1354 insertions, 786 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 3179481c98..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 */ @@ -66,7 +66,6 @@ public: virtual void environment_set_sky(RID p_env, RID p_sky) = 0; virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_material(RID p_env, RID p_material) = 0; virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp index 90a8a9592d..355ebfa409 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp @@ -248,32 +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::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) { zeromem(&blur.push_constant, sizeof(BlurPushConstant)); @@ -731,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); @@ -780,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() { { @@ -813,15 +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)); - } + roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0)); } { @@ -958,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)); } { @@ -1050,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 ab4aa58ce0..562a7b674b 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h @@ -115,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; @@ -135,7 +129,7 @@ class RasterizerEffectsRD { CubemapRoughnessPushConstant push_constant; CubemapRoughnessShaderRD shader; RID shader_version; - RID pipelines[CUBEMAP_ROUGHNESS_SOURCE_MAX]; + RID pipeline; } roughness; enum TonemapMode { @@ -341,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]; @@ -357,7 +345,7 @@ class RasterizerEffectsRD { CubemapDownsamplerPushConstant push_constant; CubemapDownsamplerShaderRD shader; RID shader_version; - RID pipelines[CUBEMAP_DOWNSAMPLER_SOURCE_MAX]; + RID pipeline; } cubemap_downsampler; @@ -381,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; @@ -403,7 +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 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); @@ -449,8 +446,9 @@ 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(); 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 5becd6c72a..1bc181bea3 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -522,255 +522,6 @@ RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_fu return material_data; } -/* SKY SHADER */ - -void RasterizerSceneHighEndRD::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; - - // actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); - // actions.usage_flag_pointers["ALPHA"] = &uses_alpha; - - actions.uniforms = &uniforms; - - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::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 = false; - - 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 RasterizerSceneHighEndRD::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 RasterizerSceneHighEndRD::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 RasterizerSceneHighEndRD::SkyShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RasterizerSceneHighEndRD::SkyShaderData::is_animated() const { - return false; -} - -bool RasterizerSceneHighEndRD::SkyShaderData::casts_shadows() const { - return false; -} - -Variant RasterizerSceneHighEndRD::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(); -} - -RasterizerSceneHighEndRD::SkyShaderData::SkyShaderData() { - valid = false; -} - -RasterizerSceneHighEndRD::SkyShaderData::~SkyShaderData() { - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::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 *RasterizerSceneHighEndRD::_create_sky_shader_func() { - SkyShaderData *shader_data = memnew(SkyShaderData); - return shader_data; -} - -void RasterizerSceneHighEndRD::SkyMaterialData::set_render_priority(int p_priority) { - priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits -} - -void RasterizerSceneHighEndRD::SkyMaterialData::set_next_pass(RID p_pass) { - next_pass = p_pass; -} - -void RasterizerSceneHighEndRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; - - 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), 2); -} - -RasterizerSceneHighEndRD::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 *RasterizerSceneHighEndRD::_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; -} - RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { clear(); } @@ -1544,72 +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 env_material = environment_get_bg_material(p_environment); - ERR_FAIL_COND(!env_material.is_valid()); - - SkyMaterialData *material = NULL; - - if (env_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(env_material, RasterizerStorageRD::SHADER_TYPE_SKY); - if (!material || !material->shader_data->valid) { - material = NULL; - } - } - - if (!material) { - env_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(env_material, RasterizerStorageRD::SHADER_TYPE_SKY); - } - - ERR_FAIL_COND(!material); - - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND]; - - - //@TODO need to gather parameters we source from our environment settings and feed into our material/shader - // such as bg energy, sky transform, etc. - // some we should remove and make part of our material settings instead of environment settings - - /* - TODO need to change this to use our sky shader instead - - 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++) { @@ -1748,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++) { @@ -1823,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: @@ -1993,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; @@ -2003,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; @@ -2043,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); @@ -2097,7 +1809,17 @@ 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()) { - // TODO: change this, we need to check if our radiance texture is dirty and needs updating... + + 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; @@ -2192,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 @@ -2886,41 +2606,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag shader.compiler.initialize(actions); } - /* SKY SHADER */ - { - // Initialize sky, we may need two modes here - Vector<String> sky_modes; - sky_modes.push_back(""); // background - sky_shader.shader.initialize(sky_modes); - } - - // 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["EYEDIR"] = "cube_normal"; - - // actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; - - // actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - - // are these correct? - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = 2; - 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); - } - //render list render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000); render_list.init(); @@ -2947,17 +2632,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag } { - // 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 = vec3(0.0, 0.0, 0.0); } \n"); - sky_shader.default_material = storage->material_create(); - storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - - MaterialData *md = (MaterialData *)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); - } - - { overdraw_material_shader = storage->shader_create(); storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); 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 c95139c0ee..960b95ee86 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -36,7 +36,6 @@ #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" #include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" #include "servers/visual/rasterizer_rd/shaders/scene_high_end.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h" class RasterizerSceneHighEndRD : public RasterizerSceneRD { @@ -51,8 +50,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { /* Scene Shader */ - // TODO possibly rename this to make it clear we have a SceneShader and SkyShader?? - enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, SHADER_VERSION_DEPTH_PASS_DP, @@ -196,87 +193,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t pad[3]; }; - /* Sky shader */ - - enum SkyVersion { - SKY_VERSION_BACKGROUND, - 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; - - 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<RasterizerSceneHighEndRD *>(singleton)->_create_sky_shader_func(); - }; - - // !BAS! Can we re-use MaterialData for our sky shader? does it need its own material subclass? - - struct SkyMaterialData : public RasterizerStorageRD::MaterialData { - // !BAS! do we need all of these? - uint64_t last_frame; - SkyShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector<RID> texture_cache; - Vector<uint8_t> ubo_data; - uint64_t last_pass = 0; - uint32_t index = 0; - RID next_pass; - uint8_t priority; - 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<RasterizerSceneHighEndRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); - }; - - struct SkyPushConstant { - float orientation[12]; - float proj[4]; - float multiplier; - float alpha; - float depth; - float pad; - }; - /* Framebuffer */ struct RenderBufferDataHighEnd : public RenderBufferData { @@ -653,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 cd441a2d04..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()); @@ -444,11 +1101,6 @@ void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis & ERR_FAIL_COND(!env); env->sky_orientation = p_orientation; } -void RasterizerSceneRD::environment_set_bg_material(RID p_env, RID p_material) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->bg_material = p_material; -} void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -495,11 +1147,6 @@ Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const { ERR_FAIL_COND_V(!env, Basis()); return env->sky_orientation; } -RID RasterizerSceneRD::environment_get_bg_material(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, RID()); - return env->bg_material; -} Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Color()); @@ -739,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(); @@ -761,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; @@ -845,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; @@ -857,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++; @@ -3063,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)) { @@ -3108,6 +3777,7 @@ void RasterizerSceneRD::update() { } void RasterizerSceneRD::set_time(double p_time, double p_step) { + time = p_time; time_step = p_step; } @@ -3124,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"); @@ -3217,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")); @@ -3232,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 fcd0db48b4..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; @@ -465,7 +623,6 @@ private: // BG VS::EnvironmentBG background = VS::ENV_BG_CLEAR_COLOR; RID sky; - RID bg_material; float sky_custom_fov = 0.0; Basis sky_orientation; Color bg_color; @@ -648,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 */ @@ -662,7 +819,6 @@ public: void environment_set_sky(RID p_env, RID p_sky); void environment_set_sky_custom_fov(RID p_env, float p_scale); void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); - void environment_set_bg_material(RID p_env, RID p_material); void environment_set_bg_color(RID p_env, const Color &p_color); void environment_set_bg_energy(RID p_env, float p_energy); void environment_set_canvas_max_layer(RID p_env, int p_max_layer); @@ -672,7 +828,6 @@ public: RID environment_get_sky(RID p_env) const; float environment_get_sky_custom_fov(RID p_env) const; Basis environment_get_sky_orientation(RID p_env) const; - RID environment_get_bg_material(RID p_env) const; Color environment_get_bg_color(RID p_env) const; float environment_get_bg_energy(RID p_env) const; int environment_get_canvas_max_layer(RID p_env) const; diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl index b042dc8868..08abe3f2c9 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 a7e51c1489..b0e97ca803 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; } }
\ No newline at end of file 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 d536b9dbd5..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,20 +35,18 @@ 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; +layout(set = 0, binding = 0) uniform sampler material_samplers[12]; + #ifdef USE_MATERIAL_UNIFORMS -layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ +layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS @@ -59,25 +55,27 @@ MATERIAL_UNIFORMS } material; #endif -/* clang-format off */ +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; -FRAGMENT_SHADER_GLOBALS +struct DirectionalLightData { + vec3 direction; + float energy; + vec3 color; + bool enabled; +}; -/* clang-format on */ - -vec4 texturePanorama(sampler2D pano, vec3 normal) { - - vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y)); +layout(set = 3, binding = 0, std140) uniform DirectionalLights { + DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; +} +directional_lights; - if (st.x < 0.0) - st.x += M_PI * 2.0; +/* clang-format off */ - st /= vec2(M_PI * 2.0, M_PI); +FRAGMENT_SHADER_GLOBALS - return texture(pano, st); -} +/* clang-format on */ layout(location = 0) out vec4 frag_color; @@ -89,10 +87,22 @@ void main() { 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.. +// 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 */ @@ -102,8 +112,6 @@ LIGHT_SHADER_CODE /* clang-format on */ } #endif - - // color = texturePanorama(source_panorama, normalize(cube_normal.xyz)).rgb; { /* clang-format off */ @@ -112,6 +120,6 @@ FRAGMENT_SHADER_CODE /* clang-format on */ } - frag_color.rgb = color; - 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 082f8a558f..7307f7527a 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -287,8 +287,38 @@ ShaderTypes::ShaderTypes() { /************ 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["EYEDIR"] = 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"); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index c609de5046..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) @@ -515,7 +515,6 @@ public: BIND2(environment_set_sky, RID, RID) BIND2(environment_set_sky_custom_fov, RID, float) BIND2(environment_set_sky_orientation, RID, const Basis &) - BIND2(environment_set_bg_material, RID, RID) BIND2(environment_set_bg_color, RID, const Color &) BIND2(environment_set_bg_energy, RID, float) BIND2(environment_set_canvas_max_layer, RID, int) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 7d22efb287..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 */ @@ -429,7 +429,6 @@ public: FUNC2(environment_set_sky, RID, RID) FUNC2(environment_set_sky_custom_fov, RID, float) FUNC2(environment_set_sky_orientation, RID, const Basis &) - FUNC2(environment_set_bg_material, RID, RID) FUNC2(environment_set_bg_color, RID, const Color &) FUNC2(environment_set_bg_energy, RID, float) FUNC2(environment_set_canvas_max_layer, RID, int) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index cc12647876..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); @@ -1797,7 +1797,6 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &VisualServer::environment_set_sky); ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &VisualServer::environment_set_sky_custom_fov); ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &VisualServer::environment_set_sky_orientation); - ClassDB::bind_method(D_METHOD("environment_set_bg_material", "env", "material"), &VisualServer::environment_set_bg_material); ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &VisualServer::environment_set_bg_color); ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &VisualServer::environment_set_bg_energy); ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &VisualServer::environment_set_canvas_max_layer); @@ -2313,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 55b13de734..dfe5e7feed 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -682,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 */ @@ -716,7 +716,6 @@ public: virtual void environment_set_sky(RID p_env, RID p_sky) = 0; virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_material(RID p_env, RID p_material) = 0; virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; |