From c3fee7ba6cdefd285255b9e1198bc1fdf585b1ac Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Sun, 15 Sep 2019 19:58:38 +1000 Subject: [PATCH] Add shader based background mode --- drivers/dummy/rasterizer_dummy.h | 1 + drivers/gles2/rasterizer_scene_gles2.cpp | 7 + drivers/gles2/rasterizer_scene_gles2.h | 3 + drivers/gles2/rasterizer_storage_gles2.cpp | 2 + scene/register_scene_types.cpp | 4 + scene/resources/environment.cpp | 31 +- scene/resources/environment.h | 5 + scene/resources/shader.cpp | 3 + scene/resources/shader.h | 1 + scene/resources/sky_material.cpp | 191 ++++++++++ scene/resources/sky_material.h | 131 +++++++ servers/visual/rasterizer.h | 1 + .../rasterizer_rd/rasterizer_effects_rd.cpp | 41 --- .../rasterizer_rd/rasterizer_effects_rd.h | 23 +- .../rasterizer_scene_high_end_rd.cpp | 338 +++++++++++++++++- .../rasterizer_scene_high_end_rd.h | 86 ++++- .../rasterizer_rd/rasterizer_scene_rd.cpp | 10 + .../rasterizer_rd/rasterizer_scene_rd.h | 3 + .../rasterizer_rd/rasterizer_storage_rd.cpp | 2 + .../rasterizer_rd/rasterizer_storage_rd.h | 1 + servers/visual/rasterizer_rd/shaders/sky.glsl | 42 ++- servers/visual/shader_types.cpp | 6 + servers/visual/visual_server_raster.h | 1 + servers/visual/visual_server_wrap_mt.h | 1 + servers/visual_server.cpp | 2 + servers/visual_server.h | 2 + 26 files changed, 871 insertions(+), 67 deletions(-) create mode 100644 scene/resources/sky_material.cpp create mode 100644 scene/resources/sky_material.h diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 4dc634aefa0..c78b82792b8 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -67,6 +67,7 @@ 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) {} diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index c4338865455..068b9f55386 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -718,6 +718,13 @@ void RasterizerSceneGLES2::environment_set_sky_orientation(RID p_env, const Basi env->sky_orientation = p_orientation; } +void RasterizerSceneGLES2::environment_set_bg_material(RID p_env, RID p_material) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->bg_material = p_material; +} + void RasterizerSceneGLES2::environment_set_bg_color(RID p_env, const Color &p_color) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index 174cdd8e2e7..fda46072a58 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -242,6 +242,8 @@ public: float sky_custom_fov; Basis sky_orientation; + RID bg_material; + Color bg_color; float bg_energy; float sky_ambient; @@ -357,6 +359,7 @@ public: virtual void environment_set_sky(RID p_env, RID p_sky); virtual void environment_set_sky_custom_fov(RID p_env, float p_scale); virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); + virtual void environment_set_bg_material(RID p_env, RID p_material); virtual void environment_set_bg_color(RID p_env, const Color &p_color); virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 0f5452effc9..f76c7da8e13 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1427,6 +1427,8 @@ void RasterizerStorageGLES2::shader_set_code(RID p_shader, const String &p_code) mode = VS::SHADER_CANVAS_ITEM; else if (mode_string == "particles") mode = VS::SHADER_PARTICLES; + else if (mode_string == "sky") + mode = VS::SHADER_SKY; else mode = VS::SHADER_SPATIAL; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index dd005659291..c152bb7e970 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -158,6 +158,7 @@ #include "scene/resources/resource_format_text.h" #include "scene/resources/segment_shape_2d.h" #include "scene/resources/sky.h" +#include "scene/resources/sky_material.h" #include "scene/resources/sphere_shape.h" #include "scene/resources/surface_tool.h" #include "scene/resources/text_file.h" @@ -609,6 +610,9 @@ void register_scene_types() { SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); ParticlesMaterial::init_shaders(); + ClassDB::register_class(); + SkyMaterial::init_shaders(); + ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::register_class(); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index d407dd37220..b5a182ed5a9 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -56,6 +56,17 @@ void Environment::set_sky(const Ref &p_sky) { VS::get_singleton()->environment_set_sky(environment, sb_rid); } +void Environment::set_bg_material(const Ref &p_material) { + + bg_material = p_material; + + RID mb_rid; + if (bg_material.is_valid()) + mb_rid = bg_material->get_rid(); + + VS::get_singleton()->environment_set_bg_material(environment, mb_rid); +} + void Environment::set_sky_custom_fov(float p_scale) { bg_sky_custom_fov = p_scale; @@ -140,6 +151,11 @@ Vector3 Environment::get_sky_rotation() const { return sky_rotation; } +Ref Environment::get_bg_material() const { + + return bg_material; +} + Color Environment::get_bg_color() const { return bg_color; @@ -306,6 +322,13 @@ Ref Environment::get_adjustment_color_correction() const { void Environment::_validate_property(PropertyInfo &property) const { + if (property.name == "background_material") { + if (bg_mode != BG_SKY) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } + + // TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -334,7 +357,7 @@ void Environment::_validate_property(PropertyInfo &property) const { if (property.name == "background_camera_feed_id") { if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -839,6 +862,7 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); + ClassDB::bind_method(D_METHOD("set_bg_material", "material"), &Environment::set_bg_material); ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); @@ -853,6 +877,7 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky); ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov); ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation); + ClassDB::bind_method(D_METHOD("get_bg_material"), &Environment::get_bg_material); ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color); ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy); ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer); @@ -871,10 +896,14 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SkyMaterial"), "set_bg_material", "get_bg_material"); + + // TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material ADD_GROUP("Sky", "sky_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "sky_rotation"), "set_sky_rotation", "get_sky_rotation"); + ADD_GROUP("Ambient Light", "ambient_light_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Color,Sky"), "set_ambient_source", "get_ambient_source"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index f9fe26f792c..9ee0cc312c9 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,6 +34,7 @@ #include "core/resource.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" +#include "scene/resources/material.h" #include "servers/visual_server.h" class Environment : public Resource { @@ -92,6 +93,8 @@ private: BGMode bg_mode; Ref bg_sky; + //@TODO for now introducing material but once it works we'll be replacing the current sky classes with material classes + Ref bg_material; float bg_sky_custom_fov; Vector3 sky_rotation; Color bg_color; @@ -180,6 +183,7 @@ public: void set_sky(const Ref &p_sky); void set_sky_custom_fov(float p_scale); void set_sky_rotation(const Vector3 &p_rotation); + void set_bg_material(const Ref &p_material); void set_bg_color(const Color &p_color); void set_bg_energy(float p_energy); void set_canvas_max_layer(int p_max_layer); @@ -196,6 +200,7 @@ public: Ref get_sky() const; float get_sky_custom_fov() const; Vector3 get_sky_rotation() const; + Ref get_bg_material() const; Color get_bg_color() const; float get_bg_energy() const; int get_canvas_max_layer() const; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index e61a1e68807..47f6d673aed 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -48,6 +48,8 @@ void Shader::set_code(const String &p_code) { mode = MODE_CANVAS_ITEM; } else if (type == "particles") { mode = MODE_PARTICLES; + } else if (type == "sky") { + mode = MODE_SKY; } else { mode = MODE_SPATIAL; } @@ -158,6 +160,7 @@ void Shader::_bind_methods() { BIND_ENUM_CONSTANT(MODE_SPATIAL); BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM); BIND_ENUM_CONSTANT(MODE_PARTICLES); + BIND_ENUM_CONSTANT(MODE_SKY); } Shader::Shader() { diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 84908852da9..5804fe8fef4 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -47,6 +47,7 @@ public: MODE_SPATIAL, MODE_CANVAS_ITEM, MODE_PARTICLES, + MODE_SKY, MODE_MAX }; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp new file mode 100644 index 00000000000..8c2b339015f --- /dev/null +++ b/scene/resources/sky_material.cpp @@ -0,0 +1,191 @@ +/*************************************************************************/ +/* sky_material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sky_material.h" + +Mutex *SkyMaterial::material_mutex = NULL; +SelfList::List *SkyMaterial::dirty_materials = NULL; +Map SkyMaterial::shader_map; +SkyMaterial::ShaderNames *SkyMaterial::shader_names = NULL; + +void SkyMaterial::init_shaders() { + +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif + + dirty_materials = memnew(SelfList::List); + + shader_names = memnew(ShaderNames); + + shader_names->placeholder = "placeholder"; +} + +void SkyMaterial::finish_shaders() { + +#ifndef NO_THREADS + memdelete(material_mutex); +#endif + + memdelete(dirty_materials); + dirty_materials = NULL; + + memdelete(shader_names); +} + +void SkyMaterial::_update_shader() { + + dirty_materials->remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + + current_key = mk; + + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + String code = "shader_type sky;\n"; + + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); +} + +void SkyMaterial::flush_changes() { + + if (material_mutex) + material_mutex->lock(); + + while (dirty_materials->first()) { + + dirty_materials->first()->self()->_update_shader(); + } + + if (material_mutex) + material_mutex->unlock(); +} + +void SkyMaterial::_queue_shader_change() { + + if (material_mutex) + material_mutex->lock(); + + if (!element.in_list()) { + dirty_materials->add(&element); + } + + if (material_mutex) + material_mutex->unlock(); +} + +bool SkyMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); + + if (material_mutex) + material_mutex->unlock(); + + return dirty; +} + + +RID SkyMaterial::get_shader_rid() const { + + ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); + return shader_map[current_key].shader; +} + +void SkyMaterial::_validate_property(PropertyInfo &property) const { + +} + +Shader::Mode SkyMaterial::get_shader_mode() const { + + return Shader::MODE_SKY; +} + +void SkyMaterial::_bind_methods() { + +} + +SkyMaterial::SkyMaterial() : + element(this) { + + + _queue_shader_change(); +} + +SkyMaterial::~SkyMaterial() { + + if (material_mutex) + material_mutex->lock(); + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + + VS::get_singleton()->material_set_shader(_get_material(), RID()); + } + + if (material_mutex) + material_mutex->unlock(); +} diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h new file mode 100644 index 00000000000..5c8cddb10e4 --- /dev/null +++ b/scene/resources/sky_material.h @@ -0,0 +1,131 @@ +/*************************************************************************/ +/* sky_material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/rid.h" +#include "scene/resources/material.h" + +#ifndef SKY_MATERIAL_H +#define SKY_MATERIAL_H + +class SkyMaterial : public Material { + + GDCLASS(SkyMaterial, Material); + +public: + +private: + union MaterialKey { + + struct { + uint32_t texture_mask : 16; + uint32_t texture_color : 1; + uint32_t flags : 4; + uint32_t emission_shape : 2; + uint32_t trail_size_texture : 1; + uint32_t trail_color_texture : 1; + uint32_t invalid_key : 1; + uint32_t has_emission_color : 1; + }; + + uint32_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; + + struct ShaderData { + RID shader; + int users; + }; + + static Map shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + + MaterialKey mk; + mk.key = 0; + /* + for (int i = 0; i < PARAM_MAX; i++) { + if (tex_parameters[i].is_valid()) { + mk.texture_mask |= (1 << i); + } + } + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= (1 << i); + } + } + + mk.texture_color = color_ramp.is_valid() ? 1 : 0; + mk.emission_shape = emission_shape; + mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; + mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; + mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + */ + + return mk; + } + + static Mutex *material_mutex; + static SelfList::List *dirty_materials; + + struct ShaderNames { + StringName placeholder; + }; + + static ShaderNames *shader_names; + + SelfList element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + +public: + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + RID get_shader_rid() const; + + virtual Shader::Mode get_shader_mode() const; + + SkyMaterial(); + ~SkyMaterial(); +}; + +#endif /* !SKY_MATERIAL_H */ diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 2670a750d7c..3179481c984 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -66,6 +66,7 @@ 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 6b6c750fd35..90a8a9592d0 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp @@ -274,31 +274,6 @@ void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_sour RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler) { - - zeromem(&sky.push_constant, sizeof(SkyPushConstant)); - - sky.push_constant.proj[0] = p_camera.matrix[2][0]; - sky.push_constant.proj[1] = p_camera.matrix[0][0]; - sky.push_constant.proj[2] = p_camera.matrix[2][1]; - sky.push_constant.proj[3] = p_camera.matrix[1][1]; - sky.push_constant.alpha = p_alpha; - sky.push_constant.depth = 1.0; - sky.push_constant.multiplier = p_multipler; - store_transform_3x3(p_orientation, sky.push_constant.orientation); - - RD::DrawListID draw_list = p_list; - - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, sky.pipeline.get_render_pipeline(RD::INVALID_ID, p_fb_format)); - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_panorama), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky.push_constant, sizeof(SkyPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); -} - void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) { zeromem(&blur.push_constant, sizeof(BlurPushConstant)); @@ -849,22 +824,6 @@ RasterizerEffectsRD::RasterizerEffectsRD() { } } - { - // Initialize sky - Vector sky_modes; - sky_modes.push_back(""); - sky.shader.initialize(sky_modes); - - sky.shader_version = sky.shader.version_create(); - - RD::PipelineDepthStencilState depth_stencil_state; - - depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - - sky.pipeline.setup(sky.shader.version_get_shader(sky.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0); - } - { // Initialize tonemapper Vector tonemap_modes; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h index fbf6b39ecbc..ab4aa58ce0b 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h @@ -32,7 +32,7 @@ #define RASTERIZER_EFFECTS_RD_H #include "core/math/camera_matrix.h" -#include "render_pipeline_vertex_format_cache_rd.h" +#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" #include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h" @@ -41,7 +41,6 @@ #include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/ssao.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/ssao_blur.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/ssao_minify.glsl.gen.h" @@ -139,23 +138,6 @@ class RasterizerEffectsRD { RID pipelines[CUBEMAP_ROUGHNESS_SOURCE_MAX]; } roughness; - struct SkyPushConstant { - float orientation[12]; - float proj[4]; - float multiplier; - float alpha; - float depth; - float pad; - }; - - struct Sky { - - SkyPushConstant push_constant; - SkyShaderRD shader; - RID shader_version; - RenderPipelineVertexFormatCacheRD pipeline; - } sky; - enum TonemapMode { TONEMAP_MODE_NORMAL, TONEMAP_MODE_BICUBIC_GLOW_FILTER, @@ -422,7 +404,6 @@ public: void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler); void 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 p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); @@ -475,4 +456,4 @@ public: ~RasterizerEffectsRD(); }; -#endif // EFFECTS_RD_H +#endif // !RASTERIZER_EFFECTS_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index 0a3105b1438..5becd6c72a7 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -76,6 +76,8 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra } } } + +/* SCENE SHADER */ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { //compile @@ -345,6 +347,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const Strin default_texture_params[p_name] = p_texture; } } + void RasterizerSceneHighEndRD::ShaderData::get_param_list(List *p_param_list) const { Map order; @@ -377,6 +380,7 @@ bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_ bool RasterizerSceneHighEndRD::ShaderData::is_animated() const { return false; } + bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const { return false; } @@ -499,6 +503,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Mapuniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } + RasterizerSceneHighEndRD::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); @@ -517,6 +522,255 @@ 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(&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 *p_param_list) const { + + Map order; + + for (Map::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::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 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 &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 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(); } @@ -1294,6 +1548,39 @@ void RasterizerSceneHighEndRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu 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); @@ -1320,6 +1607,7 @@ void RasterizerSceneHighEndRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu 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) { @@ -1809,7 +2097,9 @@ 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... radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET); + draw_sky = true; } } break; @@ -2371,7 +2661,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag singleton = this; storage = p_storage; - /* SHADER */ + /* SCENE SHADER */ { String defines; @@ -2596,6 +2886,41 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag shader.compiler.initialize(actions); } + /* SKY SHADER */ + { + // Initialize sky, we may need two modes here + Vector 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(); @@ -2621,6 +2946,17 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); } + { + // 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(); 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 647b8f225ee..c95139c0eef 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -36,6 +36,7 @@ #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 { @@ -48,7 +49,9 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { MATERIAL_UNIFORM_SET = 5 }; - /* Shader */ + /* Scene Shader */ + + // TODO possibly rename this to make it clear we have a SceneShader and SkyShader?? enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, @@ -193,6 +196,87 @@ 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 uniforms; + Vector texture_uniforms; + + Vector ubo_offsets; + uint32_t ubo_size; + + String path; + String code; + Map 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 *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(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 texture_cache; + Vector 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 &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(singleton)->_create_sky_material_func(static_cast(p_shader)); + }; + + struct SkyPushConstant { + float orientation[12]; + float proj[4]; + float multiplier; + float alpha; + float depth; + float pad; + }; + /* Framebuffer */ struct RenderBufferDataHighEnd : public RenderBufferData { diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp index 457f6970c89..cd441a2d040 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp @@ -444,6 +444,11 @@ 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); @@ -490,6 +495,11 @@ 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()); diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h index 0fa853f2dfb..fcd0db48b41 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h @@ -465,6 +465,7 @@ 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; @@ -661,6 +662,7 @@ 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); @@ -670,6 +672,7 @@ 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/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp index b8d7a9dcf40..6e7f0aac073 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp @@ -881,6 +881,8 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { new_type = SHADER_TYPE_PARTICLES; else if (mode_string == "spatial") new_type = SHADER_TYPE_3D; + else if (mode_string == "sky") + new_type = SHADER_TYPE_SKY; else new_type = SHADER_TYPE_MAX; diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h index 9bc4beab6ee..410cd4adb45 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h @@ -44,6 +44,7 @@ public: SHADER_TYPE_2D, SHADER_TYPE_3D, SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, SHADER_TYPE_MAX }; diff --git a/servers/visual/rasterizer_rd/shaders/sky.glsl b/servers/visual/rasterizer_rd/shaders/sky.glsl index 28fd2883c3c..d536b9dbd55 100644 --- a/servers/visual/rasterizer_rd/shaders/sky.glsl +++ b/servers/visual/rasterizer_rd/shaders/sky.glsl @@ -49,6 +49,22 @@ layout(push_constant, binding = 1, std430) uniform Params { } params; +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ + /* clang-format off */ + +MATERIAL_UNIFORMS + + /* clang-format on */ +} material; +#endif + +/* clang-format off */ + +FRAGMENT_SHADER_GLOBALS + +/* clang-format on */ + vec4 texturePanorama(sampler2D pano, vec3 normal) { vec2 st = vec2( @@ -68,12 +84,34 @@ layout(location = 0) out vec4 frag_color; void main() { vec3 cube_normal; - cube_normal.z = -1000000.0; + cube_normal.z = -1.0; cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y; cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w; cube_normal = mat3(params.orientation) * cube_normal; cube_normal.z = -cube_normal.z; - frag_color.rgb = texturePanorama(source_panorama, normalize(cube_normal.xyz)).rgb; + vec3 color = vec3(0.0, 0.0, 0.0); + + // unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in.. +#ifndef REALLYINCLUDETHIS + { + /* clang-format off */ + +LIGHT_SHADER_CODE + + /* clang-format on */ + } +#endif + + // color = texturePanorama(source_panorama, normalize(cube_normal.xyz)).rgb; + { + /* clang-format off */ + +FRAGMENT_SHADER_CODE + + /* clang-format on */ + } + + frag_color.rgb = color; frag_color.a = params.alpha; } diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 631925e7702..082f8a558f5 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -285,7 +285,13 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_velocity"); shader_modes[VS::SHADER_PARTICLES].modes.push_back("keep_data"); + /************ SKY **************************/ + + shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = ShaderLanguage::TYPE_VEC3; + shader_types.insert("spatial"); shader_types.insert("canvas_item"); shader_types.insert("particles"); + shader_types.insert("sky"); } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 09b34ce25cb..c609de50467 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -515,6 +515,7 @@ 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 8f4df6a0e27..7d22efb287d 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -429,6 +429,7 @@ 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 15065619526..cc126478767 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1797,6 +1797,7 @@ 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); @@ -1971,6 +1972,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(SHADER_SPATIAL); BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); BIND_ENUM_CONSTANT(SHADER_PARTICLES); + BIND_ENUM_CONSTANT(SHADER_SKY); BIND_ENUM_CONSTANT(SHADER_MAX); BIND_ENUM_CONSTANT(ARRAY_VERTEX); diff --git a/servers/visual_server.h b/servers/visual_server.h index 4bb1c1a0803..55b13de7349 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -160,6 +160,7 @@ public: SHADER_SPATIAL, SHADER_CANVAS_ITEM, SHADER_PARTICLES, + SHADER_SKY, SHADER_MAX }; @@ -715,6 +716,7 @@ 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;