diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 5b19dee7cb..54e1264df9 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1775,8 +1775,9 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra } sky->panorama = p_panorama; - if (!sky->panorama.is_valid()) + if (!sky->panorama.is_valid()) { return; //cleared + } Texture *texture = texture_owner.getornull(sky->panorama); if (!texture) { diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 93e1b09cfd..a89183d1cc 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1044,6 +1044,8 @@ bool RenderingDeviceVulkan::format_has_stencil(DataFormat p_format) { case DATA_FORMAT_D32_SFLOAT_S8_UINT: { return true; } + default: { + } } return false; } @@ -1219,7 +1221,7 @@ const VkImageType RenderingDeviceVulkan::vulkan_image_type[RenderingDevice::TEXT VK_IMAGE_TYPE_2D, VK_IMAGE_TYPE_1D, VK_IMAGE_TYPE_2D, - VK_IMAGE_TYPE_3D + VK_IMAGE_TYPE_2D }; /***************************/ @@ -1364,7 +1366,7 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_ } else { //flush EVERYTHING including setup commands. IF not immediate, also need to flush the draw commands - _flush(true, p_on_draw_command_buffer); + _flush(true); //clear the whole staging buffer for (int i = 0; i < staging_buffer_blocks.size(); i++) { @@ -1408,7 +1410,7 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_ continue; //and try again } else { - _flush(false, false); + _flush(false); for (int i = 0; i < staging_buffer_blocks.size(); i++) { //clear all blocks but the ones from this frame @@ -1562,10 +1564,6 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_create_info.mipLevels = p_format.mipmaps; - uint32_t array_layer_multiplier = 1; - if (p_format.type == TEXTURE_TYPE_CUBE_ARRAY || p_format.type == TEXTURE_TYPE_CUBE) { - array_layer_multiplier = 6; - } if (p_format.type == TEXTURE_TYPE_1D_ARRAY || p_format.type == TEXTURE_TYPE_2D_ARRAY || p_format.type == TEXTURE_TYPE_CUBE_ARRAY || p_format.type == TEXTURE_TYPE_CUBE) { ERR_FAIL_COND_V_MSG(p_format.array_layers < 1, RID(), "Amount of layers must be equal or greater than 1 for arrays and cubemaps."); @@ -1576,8 +1574,6 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_create_info.arrayLayers = 1; } - image_create_info.arrayLayers = p_format.array_layers; - ERR_FAIL_INDEX_V(p_format.samples, TEXTURE_SAMPLES_MAX, RID()); image_create_info.samples = rasterization_sample_count[p_format.samples]; @@ -1624,11 +1620,11 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T ERR_FAIL_COND_V_MSG(!(p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT), RID(), "Texture needs the TEXTURE_USAGE_CAN_UPDATE_BIT usage flag in order to be updated at initialization or later"); - int expected_images = image_create_info.arrayLayers * array_layer_multiplier; + int expected_images = image_create_info.arrayLayers; ERR_FAIL_COND_V_MSG(p_data.size() != expected_images, RID(), "Default supplied data for image format is of invalid length (" + itos(p_data.size()) + "), should be (" + itos(expected_images) + ")."); - for (uint32_t i = 0; i < image_create_info.arrayLayers * array_layer_multiplier; i++) { + for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) { uint32_t required_size = get_image_format_required_size(p_format.format, image_create_info.extent.width, image_create_info.extent.height, image_create_info.extent.depth, image_create_info.mipLevels); ERR_FAIL_COND_V_MSG((uint32_t)p_data[i].size() != required_size, RID(), "Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(p_data[i].size()) + ") than what is required by the format (" + itos(required_size) + ")."); @@ -1789,7 +1785,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_view_create_info.subresourceRange.baseMipLevel = 0; image_view_create_info.subresourceRange.levelCount = image_create_info.mipLevels; image_view_create_info.subresourceRange.baseArrayLayer = 0; - image_view_create_info.subresourceRange.layerCount = array_layer_multiplier * image_create_info.arrayLayers; + image_view_create_info.subresourceRange.layerCount = image_create_info.arrayLayers; if (p_format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; } else { @@ -1819,7 +1815,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_memory_barrier.subresourceRange.baseMipLevel = 0; image_memory_barrier.subresourceRange.levelCount = image_create_info.mipLevels; image_memory_barrier.subresourceRange.baseArrayLayer = 0; - image_memory_barrier.subresourceRange.layerCount = image_create_info.arrayLayers * array_layer_multiplier; + image_memory_barrier.subresourceRange.layerCount = image_create_info.arrayLayers; vkCmdPipelineBarrier(frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier); } @@ -1850,11 +1846,6 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID Texture texture = *src_texture; - uint32_t array_layer_multiplier = 1; - if (texture.type == TEXTURE_TYPE_CUBE_ARRAY || texture.type == TEXTURE_TYPE_CUBE) { - array_layer_multiplier = 6; - } - VkImageViewCreateInfo image_view_create_info; image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; image_view_create_info.pNext = NULL; @@ -1899,7 +1890,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID image_view_create_info.subresourceRange.baseMipLevel = 0; image_view_create_info.subresourceRange.levelCount = texture.mipmaps; - image_view_create_info.subresourceRange.layerCount = array_layer_multiplier * texture.layers; + image_view_create_info.subresourceRange.layerCount = texture.layers; image_view_create_info.subresourceRange.baseArrayLayer = 0; if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { @@ -1921,7 +1912,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID return id; } -RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap) { +RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) { Texture *src_texture = texture_owner.getornull(p_with_texture); ERR_FAIL_COND_V(!src_texture, RID()); @@ -1932,20 +1923,18 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p ERR_FAIL_COND_V(!src_texture, RID()); //this is a bug } + ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_CUBEMAP && (src_texture->type != TEXTURE_TYPE_CUBE && src_texture->type != TEXTURE_TYPE_CUBE_ARRAY), RID(), + "Can only create a cubemap slice from a cubemap or cubemap array mipmap"); + //create view ERR_FAIL_INDEX_V(p_mipmap, src_texture->mipmaps, RID()); - - uint32_t array_layer_multiplier = 1; - if (src_texture->type == TEXTURE_TYPE_CUBE_ARRAY || src_texture->type == TEXTURE_TYPE_CUBE) { - array_layer_multiplier = 6; - } - ERR_FAIL_INDEX_V(p_layer, src_texture->layers * array_layer_multiplier, RID()); + ERR_FAIL_INDEX_V(p_layer, src_texture->layers, RID()); Texture texture = *src_texture; get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height); texture.mipmaps = 1; - texture.layers = 1; + texture.layers = p_slice_type == TEXTURE_SLICE_CUBEMAP ? 6 : 1; VkImageViewCreateInfo image_view_create_info; image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -1963,7 +1952,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p VK_IMAGE_VIEW_TYPE_2D, }; - image_view_create_info.viewType = view_types[texture.type]; + image_view_create_info.viewType = p_slice_type == TEXTURE_SLICE_CUBEMAP ? VK_IMAGE_VIEW_TYPE_CUBE : view_types[texture.type]; if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) { image_view_create_info.format = vulkan_formats[texture.format]; } else { @@ -1989,9 +1978,15 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p image_view_create_info.components.b = component_swizzles[p_view.swizzle_b]; image_view_create_info.components.a = component_swizzles[p_view.swizzle_a]; + if (p_slice_type == TEXTURE_SLICE_CUBEMAP) { + ERR_FAIL_COND_V_MSG(p_layer >= src_texture->layers, RID(), + "Specified layer is invalid for cubemap"); + ERR_FAIL_COND_V_MSG((p_layer % 6) != 0, RID(), + "Specified layer must be a multiple of 6."); + } image_view_create_info.subresourceRange.baseMipLevel = p_mipmap; image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.layerCount = 1; + image_view_create_info.subresourceRange.layerCount = p_slice_type == TEXTURE_SLICE_CUBEMAP ? 6 : 1; image_view_create_info.subresourceRange.baseArrayLayer = p_layer; if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { @@ -2469,7 +2464,7 @@ PoolVector RenderingDeviceVulkan::texture_get_data(RID p_texture, uint3 } //flush everything so memory can be safely mapped - _flush(true, false); + _flush(true); PoolVector ret = _texture_get_data_from_image(tex, image, allocation, p_layer); vmaDestroyImage(allocator, image, allocation); @@ -4555,7 +4550,7 @@ PoolVector RenderingDeviceVulkan::buffer_get_data(RID p_buffer) { region.size = buffer->size; vkCmdCopyBuffer(command_buffer, buffer->buffer, tmp_buffer.buffer, 1, ®ion); //dst buffer is in CPU, but I wonder if src buffer needs a barrier for this.. //flush everything so memory can be safely mapped - _flush(true, false); + _flush(true); void *buffer_mem; VkResult vkerr = vmaMapMemory(allocator, tmp_buffer.allocation, &buffer_mem); @@ -4571,6 +4566,8 @@ PoolVector RenderingDeviceVulkan::buffer_get_data(RID p_buffer) { copymem(w.ptr(), buffer_mem, buffer->size); } + vmaUnmapMemory(allocator, tmp_buffer.allocation); + _buffer_free(&tmp_buffer); return buffer_data; @@ -6041,18 +6038,16 @@ void RenderingDeviceVulkan::advance_frame() { } } -void RenderingDeviceVulkan::_flush(bool p_setup, bool p_draw) { +void RenderingDeviceVulkan::_flush(bool p_current_frame) { //not doing this crashes RADV (undefined behavior) - if (p_setup) { + if (p_current_frame) { vkEndCommandBuffer(frames[frame].setup_command_buffer); - } - if (p_draw) { vkEndCommandBuffer(frames[frame].draw_command_buffer); } - context->flush(p_setup, p_draw); + context->flush(p_current_frame, p_current_frame); //re-create the setup command - if (p_setup) { + if (p_current_frame) { VkCommandBufferBeginInfo cmdbuf_begin; cmdbuf_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdbuf_begin.pNext = NULL; @@ -6064,7 +6059,7 @@ void RenderingDeviceVulkan::_flush(bool p_setup, bool p_draw) { context->set_setup_buffer(frames[frame].setup_command_buffer); //append now so it's added before everything else } - if (p_draw) { + if (p_current_frame) { VkCommandBufferBeginInfo cmdbuf_begin; cmdbuf_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdbuf_begin.pNext = NULL; @@ -6232,7 +6227,7 @@ void RenderingDeviceVulkan::finalize() { //free all resources - _flush(false, false); + _flush(false); _free_rids(pipeline_owner, "Pipeline"); _free_rids(uniform_set_owner, "UniformSet"); diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index e2b43d9aeb..d9fb65bb47 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -840,7 +840,7 @@ class RenderingDeviceVulkan : public RenderingDevice { VulkanContext *context; void _free_internal(RID p_id); - void _flush(bool p_setup, bool p_draw); + void _flush(bool p_current_frame); bool screen_prepared; @@ -850,7 +850,8 @@ class RenderingDeviceVulkan : public RenderingDevice { public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector > &p_data = Vector >()); virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture); - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap); + + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D); virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector &p_data, bool p_sync_with_draw = false); virtual PoolVector texture_get_data(RID p_texture, uint32_t p_layer); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index efd025c1e2..f232073f47 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -923,13 +923,11 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*b*/ VK_COMPONENT_SWIZZLE_B, /*a*/ VK_COMPONENT_SWIZZLE_A, }, - /*subresourceRange*/ { - /*aspectMask*/ VK_IMAGE_ASPECT_COLOR_BIT, - /*baseMipLevel*/ 0, - /*levelCount*/ 1, - /*baseArrayLayer*/ 0, - /*layerCount*/ 1 - }, + /*subresourceRange*/ { /*aspectMask*/ VK_IMAGE_ASPECT_COLOR_BIT, + /*baseMipLevel*/ 0, + /*levelCount*/ 1, + /*baseArrayLayer*/ 0, + /*layerCount*/ 1 }, }; window->swapchain_image_resources[i].image = swapchainImages[i]; diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 7895c31778..c4e6d37e7f 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -225,7 +225,9 @@ EditorInspectorPluginMaterial::EditorInspectorPluginMaterial() { env.instance(); Ref proc_sky = memnew(ProceduralSky(true)); env->set_sky(proc_sky); - env->set_background(Environment::BG_COLOR_SKY); + env->set_background(Environment::BG_COLOR); + env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY); + env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY); } MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) { diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 37a185ecac..5e18e73b5b 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -61,25 +61,6 @@ void Environment::set_sky_custom_fov(float p_scale) { bg_sky_custom_fov = p_scale; VS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); } -void Environment::set_sky_orientation(const Basis &p_orientation) { - - bg_sky_orientation = p_orientation; - _change_notify("background_sky_rotation"); - _change_notify("background_sky_rotation_degrees"); - VS::get_singleton()->environment_set_sky_orientation(environment, bg_sky_orientation); -} -void Environment::set_sky_rotation(const Vector3 &p_euler_rad) { - - bg_sky_orientation.set_euler(p_euler_rad); - _change_notify("background_sky_orientation"); - _change_notify("background_sky_rotation_degrees"); - VS::get_singleton()->environment_set_sky_orientation(environment, bg_sky_orientation); -} -void Environment::set_sky_rotation_degrees(const Vector3 &p_euler_deg) { - - set_sky_rotation(p_euler_deg * Math_PI / 180.0); - _change_notify("background_sky_rotation"); -} void Environment::set_bg_color(const Color &p_color) { bg_color = p_color; @@ -98,17 +79,17 @@ void Environment::set_canvas_max_layer(int p_max_layer) { void Environment::set_ambient_light_color(const Color &p_color) { ambient_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); } void Environment::set_ambient_light_energy(float p_energy) { ambient_energy = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); } void Environment::set_ambient_light_sky_contribution(float p_energy) { ambient_sky_contribution = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); } void Environment::set_camera_feed_id(int p_camera_feed_id) { @@ -119,6 +100,22 @@ void Environment::set_camera_feed_id(int p_camera_feed_id) { #endif }; +void Environment::set_ambient_source(AmbientSource p_source) { + ambient_source = p_source; + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); +} + +Environment::AmbientSource Environment::get_ambient_source() const { + return ambient_source; +} +void Environment::set_reflection_source(ReflectionSource p_source) { + reflection_source = p_source; + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); +} +Environment::ReflectionSource Environment::get_reflection_source() const { + return reflection_source; +} + Environment::BGMode Environment::get_background() const { return bg_mode; @@ -133,20 +130,14 @@ float Environment::get_sky_custom_fov() const { return bg_sky_custom_fov; } -Basis Environment::get_sky_orientation() const { - - return bg_sky_orientation; +void Environment::set_sky_rotation(const Vector3 &p_rotation) { + sky_rotation = p_rotation; + VS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); } Vector3 Environment::get_sky_rotation() const { - // should we cache this? maybe overkill - return bg_sky_orientation.get_euler(); -} - -Vector3 Environment::get_sky_rotation_degrees() const { - - return get_sky_rotation() * 180.0 / Math_PI; + return sky_rotation; } Color Environment::get_bg_color() const { @@ -315,14 +306,14 @@ Ref Environment::get_adjustment_color_correction() const { void Environment::_validate_property(PropertyInfo &property) const { - if (property.name == "background_sky" || property.name == "background_sky_custom_fov" || property.name == "background_sky_orientation" || property.name == "background_sky_rotation" || property.name == "background_sky_rotation_degrees" || property.name == "ambient_light/sky_contribution") { - if (bg_mode != BG_SKY && bg_mode != BG_COLOR_SKY) { + 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; } } if (property.name == "background_color") { - if (bg_mode != BG_COLOR && bg_mode != BG_COLOR_SKY) { + if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -951,9 +942,7 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); 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_orientation", "orientation"), &Environment::set_sky_orientation); ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); - ClassDB::bind_method(D_METHOD("set_sky_rotation_degrees", "euler_degrees"), &Environment::set_sky_rotation_degrees); 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); @@ -961,13 +950,13 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "energy"), &Environment::set_ambient_light_sky_contribution); ClassDB::bind_method(D_METHOD("set_camera_feed_id", "camera_feed_id"), &Environment::set_camera_feed_id); + ClassDB::bind_method(D_METHOD("set_ambient_source", "source"), &Environment::set_ambient_source); + ClassDB::bind_method(D_METHOD("set_reflection_source", "source"), &Environment::set_reflection_source); ClassDB::bind_method(D_METHOD("get_background"), &Environment::get_background); 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_orientation"), &Environment::get_sky_orientation); ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation); - ClassDB::bind_method(D_METHOD("get_sky_rotation_degrees"), &Environment::get_sky_rotation_degrees); 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); @@ -975,24 +964,26 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &Environment::get_camera_feed_id); + ClassDB::bind_method(D_METHOD("get_ambient_source"), &Environment::get_ambient_source); + ClassDB::bind_method(D_METHOD("get_reflection_source"), &Environment::get_reflection_source); ADD_GROUP("Background", "background_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Color+Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); - ADD_PROPERTY(PropertyInfo(Variant::BASIS, "background_sky_orientation"), "set_sky_orientation", "get_sky_orientation"); - // Only display rotation in degrees in the inspector (like in Spatial). - // This avoids displaying the same information twice. - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation", PROPERTY_HINT_NONE, "", 0), "set_sky_rotation", "get_sky_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_sky_rotation_degrees", "get_sky_rotation_degrees"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer"); 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::REAL, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_GROUP("Sky", "sky_"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "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"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); + ADD_GROUP("Reflected Light", "reflected_light_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "reflected_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Sky"), "set_reflection_source", "get_reflection_source"); ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); @@ -1282,11 +1273,19 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(BG_CLEAR_COLOR); BIND_ENUM_CONSTANT(BG_COLOR); BIND_ENUM_CONSTANT(BG_SKY); - BIND_ENUM_CONSTANT(BG_COLOR_SKY); BIND_ENUM_CONSTANT(BG_CANVAS); BIND_ENUM_CONSTANT(BG_CAMERA_FEED); BIND_ENUM_CONSTANT(BG_MAX); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_BG); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_COLOR); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_SKY); + + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_BG); + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_SKY); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_ADDITIVE); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); @@ -1324,11 +1323,12 @@ Environment::Environment() : bg_mode = BG_CLEAR_COLOR; bg_sky_custom_fov = 0; - bg_sky_orientation = Basis(); bg_energy = 1.0; bg_canvas_max_layer = 0; ambient_energy = 1.0; //ambient_sky_contribution = 1.0; + ambient_source = AMBIENT_SOURCE_BG; + reflection_source = REFLECTION_SOURCE_BG; set_ambient_light_sky_contribution(1.0); set_camera_feed_id(1); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index e9088d4fbd..30f96e97fd 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -46,13 +46,25 @@ public: BG_CLEAR_COLOR, BG_COLOR, BG_SKY, - BG_COLOR_SKY, BG_CANVAS, BG_KEEP, BG_CAMERA_FEED, BG_MAX }; + enum AmbientSource { + AMBIENT_SOURCE_BG, + AMBIENT_SOURCE_DISABLED, + AMBIENT_SOURCE_COLOR, + AMBIENT_SOURCE_SKY, + }; + + enum ReflectionSource { + REFLECTION_SOURCE_BG, + REFLECTION_SOURCE_DISABLED, + REFLECTION_SOURCE_SKY, + }; + enum ToneMapper { TONE_MAPPER_LINEAR, TONE_MAPPER_REINHARDT, @@ -92,7 +104,7 @@ private: BGMode bg_mode; Ref bg_sky; float bg_sky_custom_fov; - Basis bg_sky_orientation; + Vector3 sky_rotation; Color bg_color; float bg_energy; int bg_canvas_max_layer; @@ -100,6 +112,8 @@ private: float ambient_energy; float ambient_sky_contribution; int camera_feed_id; + AmbientSource ambient_source; + ReflectionSource reflection_source; ToneMapper tone_mapper; float tonemap_exposure; @@ -183,11 +197,10 @@ protected: public: void set_background(BGMode p_bg); + void set_sky(const Ref &p_sky); void set_sky_custom_fov(float p_scale); - void set_sky_orientation(const Basis &p_orientation); - void set_sky_rotation(const Vector3 &p_euler_rad); - void set_sky_rotation_degrees(const Vector3 &p_euler_deg); + void set_sky_rotation(const Vector3 &p_rotation); void set_bg_color(const Color &p_color); void set_bg_energy(float p_energy); void set_canvas_max_layer(int p_max_layer); @@ -195,13 +208,15 @@ public: void set_ambient_light_energy(float p_energy); void set_ambient_light_sky_contribution(float p_energy); void set_camera_feed_id(int p_camera_feed_id); + void set_ambient_source(AmbientSource p_source); + AmbientSource get_ambient_source() const; + void set_reflection_source(ReflectionSource p_source); + ReflectionSource get_reflection_source() const; BGMode get_background() const; Ref get_sky() const; float get_sky_custom_fov() const; - Basis get_sky_orientation() const; Vector3 get_sky_rotation() const; - Vector3 get_sky_rotation_degrees() const; Color get_bg_color() const; float get_bg_energy() const; int get_canvas_max_layer() const; @@ -412,6 +427,8 @@ public: }; VARIANT_ENUM_CAST(Environment::BGMode) +VARIANT_ENUM_CAST(Environment::AmbientSource) +VARIANT_ENUM_CAST(Environment::ReflectionSource) VARIANT_ENUM_CAST(Environment::ToneMapper) VARIANT_ENUM_CAST(Environment::GlowBlendMode) VARIANT_ENUM_CAST(Environment::DOFBlurQuality) diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 368d65cb85..8569d998e4 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -461,7 +461,7 @@ void SpatialMaterial::_update_shader() { code += ",unshaded"; } if (flags[FLAG_DISABLE_DEPTH_TEST]) { - code += ",depth_test_disable"; + code += ",depth_test_disabled"; } if (flags[FLAG_USE_VERTEX_LIGHTING]) { code += ",vertex_lighting"; diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 59af1f58e8..3e797a7bde 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -36,7 +36,10 @@ void Sky::set_radiance_size(RadianceSize p_size) { ERR_FAIL_INDEX(p_size, RADIANCE_SIZE_MAX); radiance_size = p_size; - _radiance_changed(); + static const int size[RADIANCE_SIZE_MAX] = { + 32, 64, 128, 256, 512, 1024, 2048 + }; + VS::get_singleton()->sky_set_radiance_size(sky, size[radiance_size]); } Sky::RadianceSize Sky::get_radiance_size() const { @@ -44,12 +47,30 @@ Sky::RadianceSize Sky::get_radiance_size() const { return radiance_size; } +void Sky::set_process_mode(ProcessMode p_mode) { + mode = p_mode; + VS::get_singleton()->sky_set_mode(sky, VS::SkyMode(mode)); +} + +Sky::ProcessMode Sky::get_process_mode() const { + return mode; +} + +RID Sky::get_rid() const { + + return sky; +} + void Sky::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size); ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size); + ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Sky::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &Sky::get_process_mode); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "HighQuality,RealTime"), "set_process_mode", "get_process_mode"); BIND_ENUM_CONSTANT(RADIANCE_SIZE_32); BIND_ENUM_CONSTANT(RADIANCE_SIZE_64); @@ -59,35 +80,30 @@ void Sky::_bind_methods() { BIND_ENUM_CONSTANT(RADIANCE_SIZE_1024); BIND_ENUM_CONSTANT(RADIANCE_SIZE_2048); BIND_ENUM_CONSTANT(RADIANCE_SIZE_MAX); + + BIND_ENUM_CONSTANT(PROCESS_MODE_QUALITY); + BIND_ENUM_CONSTANT(PROCESS_MODE_REALTIME); } Sky::Sky() { + mode = PROCESS_MODE_QUALITY; radiance_size = RADIANCE_SIZE_128; + sky = VS::get_singleton()->sky_create(); +} + +Sky::~Sky() { + + VS::get_singleton()->free(sky); } ///////////////////////////////////////// -void PanoramaSky::_radiance_changed() { - - if (panorama.is_valid()) { - static const int size[RADIANCE_SIZE_MAX] = { - 32, 64, 128, 256, 512, 1024, 2048 - }; - VS::get_singleton()->sky_set_texture(sky, panorama->get_rid(), size[get_radiance_size()]); - } -} - void PanoramaSky::set_panorama(const Ref &p_panorama) { panorama = p_panorama; - if (panorama.is_valid()) { - - _radiance_changed(); - - } else { - VS::get_singleton()->sky_set_texture(sky, RID(), 0); - } + RID rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID(); + VS::get_singleton()->sky_set_texture(get_rid(), rid); } Ref PanoramaSky::get_panorama() const { @@ -95,11 +111,6 @@ Ref PanoramaSky::get_panorama() const { return panorama; } -RID PanoramaSky::get_rid() const { - - return sky; -} - void PanoramaSky::_bind_methods() { ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama); @@ -109,27 +120,12 @@ void PanoramaSky::_bind_methods() { } PanoramaSky::PanoramaSky() { - - sky = VS::get_singleton()->sky_create(); } PanoramaSky::~PanoramaSky() { - - VS::get_singleton()->free(sky); } ////////////////////////////////// -void ProceduralSky::_radiance_changed() { - - if (update_queued) - return; //do nothing yet - - static const int size[RADIANCE_SIZE_MAX] = { - 32, 64, 128, 256, 512, 1024, 2048 - }; - VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]); -} - Ref ProceduralSky::_generate_sky() { update_queued = false; @@ -390,10 +386,6 @@ ProceduralSky::TextureSize ProceduralSky::get_texture_size() const { return texture_size; } -RID ProceduralSky::get_rid() const { - return sky; -} - void ProceduralSky::_update_sky() { bool use_thread = true; @@ -421,7 +413,7 @@ void ProceduralSky::_update_sky() { } else { texture = VS::get_singleton()->texture_2d_create(image); } - _radiance_changed(); + VS::get_singleton()->sky_set_texture(get_rid(), texture); } } @@ -443,7 +435,8 @@ void ProceduralSky::_thread_done(const Ref &p_image) { texture = VS::get_singleton()->texture_2d_create(p_image); } - _radiance_changed(); + VS::get_singleton()->sky_set_texture(get_rid(), texture); + Thread::wait_to_finish(sky_thread); memdelete(sky_thread); sky_thread = NULL; @@ -547,8 +540,6 @@ void ProceduralSky::_bind_methods() { ProceduralSky::ProceduralSky(bool p_desaturate) { - sky = VS::get_singleton()->sky_create(); - update_queued = false; sky_top_color = Color::hex(0xa5d6f1ff); sky_horizon_color = Color::hex(0xd6eafaff); @@ -589,7 +580,6 @@ ProceduralSky::~ProceduralSky() { memdelete(sky_thread); sky_thread = NULL; } - VS::get_singleton()->free(sky); if (texture.is_valid()) { VS::get_singleton()->free(texture); } diff --git a/scene/resources/sky.h b/scene/resources/sky.h index cc5ec79a1f..09ebbd88a0 100644 --- a/scene/resources/sky.h +++ b/scene/resources/sky.h @@ -49,38 +49,48 @@ public: RADIANCE_SIZE_MAX }; + enum ProcessMode { + PROCESS_MODE_QUALITY, + PROCESS_MODE_REALTIME + }; + private: + RID sky; + ProcessMode mode; RadianceSize radiance_size; protected: static void _bind_methods(); - virtual void _radiance_changed() = 0; public: void set_radiance_size(RadianceSize p_size); RadianceSize get_radiance_size() const; + + void set_process_mode(ProcessMode p_mode); + ProcessMode get_process_mode() const; + + virtual RID get_rid() const; + Sky(); + ~Sky(); }; VARIANT_ENUM_CAST(Sky::RadianceSize) +VARIANT_ENUM_CAST(Sky::ProcessMode) class PanoramaSky : public Sky { GDCLASS(PanoramaSky, Sky); private: - RID sky; Ref panorama; protected: static void _bind_methods(); - virtual void _radiance_changed(); public: void set_panorama(const Ref &p_panorama); Ref get_panorama() const; - virtual RID get_rid() const; - PanoramaSky(); ~PanoramaSky(); }; @@ -120,7 +130,6 @@ private: TextureSize texture_size; - RID sky; RID texture; bool update_queued; @@ -133,7 +142,6 @@ private: protected: static void _bind_methods(); - virtual void _radiance_changed(); Ref _generate_sky(); void _update_sky(); @@ -189,8 +197,6 @@ public: void set_texture_size(TextureSize p_size); TextureSize get_texture_size() const; - virtual RID get_rid() const; - ProceduralSky(bool p_desaturate = false); ~ProceduralSky(); }; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8df43bc695..c6517a12ed 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -49,6 +49,13 @@ public: virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; virtual void set_directional_shadow_count(int p_count) = 0; + /* SKY API */ + + 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; + /* ENVIRONMENT API */ virtual RID environment_create() = 0; @@ -60,7 +67,7 @@ public: 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; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG) = 0; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; @@ -82,9 +89,9 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; - virtual bool is_environment(RID p_env) = 0; - virtual VS::EnvironmentBG environment_get_background(RID p_env) = 0; - virtual int environment_get_canvas_max_layer(RID p_env) = 0; + virtual bool is_environment(RID p_env) const = 0; + virtual VS::EnvironmentBG environment_get_background(RID p_env) const = 0; + virtual int environment_get_canvas_max_layer(RID p_env) const = 0; struct InstanceBase; @@ -258,6 +265,7 @@ public: virtual bool free(RID p_rid) = 0; + virtual void update() = 0; virtual ~RasterizerScene() {} }; @@ -304,11 +312,6 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - /* SKY API */ - - virtual RID sky_create() = 0; - virtual void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) = 0; - /* SHADER API */ virtual RID shader_create() = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp index 130e0e15b7..bf2214752d 100644 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -265,10 +265,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector polygon_buffer; polygon_buffer.resize(buffer_size * sizeof(float)); Vector descriptions; - descriptions.resize(5); + descriptions.resize(4); Vector buffers; - buffers.resize(5); + buffers.resize(4); { PoolVector::Read r = polygon_buffer.read(); @@ -374,7 +371,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vectormesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES); } - //bones - if ((uint32_t)p_weights.size() == vertex_count * 4) { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = base_offset * sizeof(float); - vd.location = VS::ARRAY_WEIGHTS; - vd.stride = stride * sizeof(float); - - descriptions.write[4] = vd; - - const float *weight_ptr = p_weights.ptr(); - - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = weight_ptr[i * 4 + 0]; - fptr[base_offset + i * stride + 1] = weight_ptr[i * 4 + 1]; - fptr[base_offset + i * stride + 2] = weight_ptr[i * 4 + 2]; - fptr[base_offset + i * stride + 3] = weight_ptr[i * 4 + 3]; - } - - base_offset += 4; - } else { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = 0; - vd.location = VS::ARRAY_WEIGHTS; - vd.stride = 0; - - descriptions.write[4] = vd; - buffers.write[4] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_WEIGHTS); - } - //check that everything is as it should be ERR_FAIL_COND_V(base_offset != stride, 0); //bug } @@ -913,7 +889,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ ERR_CONTINUE(!pb); //bind pipeline { - static const PipelineVariant variant[VS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES }; + static const PipelineVariant variant[VS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= VS::PRIMITIVE_MAX); RID pipeline = pipeline_variants->variants[light_mode][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); @@ -1976,9 +1952,12 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_POINTS, RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, }; + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { { //non lit SHADER_VARIANT_QUAD, @@ -1988,6 +1967,8 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { SHADER_VARIANT_PRIMITIVE_POINTS, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES_POINTS }, { //lit SHADER_VARIANT_QUAD_LIGHT, @@ -1997,6 +1978,8 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, }; @@ -2283,6 +2266,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, }; + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { { //non lit SHADER_VARIANT_QUAD, diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp index 765e718279..121cc5b48a 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp @@ -1,5 +1,20 @@ #include "rasterizer_effects_rd.h" +static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) { + p_array[0] = p_basis.elements[0][0]; + p_array[1] = p_basis.elements[1][0]; + p_array[2] = p_basis.elements[2][0]; + p_array[3] = 0; + p_array[4] = p_basis.elements[0][1]; + p_array[5] = p_basis.elements[1][1]; + p_array[6] = p_basis.elements[2][1]; + p_array[7] = 0; + p_array[8] = p_basis.elements[0][2]; + p_array[9] = p_basis.elements[1][2]; + p_array[10] = p_basis.elements[2][2]; + p_array[11] = 0; +} + RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) { if (texture_to_uniform_set_cache.has(p_texture)) { @@ -86,31 +101,127 @@ void RasterizerEffectsRD::gaussian_blur(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) { + + zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); + + roughness.push_constant.face_id = 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; + + //RUN + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.pipelines[p_source_is_panorama ? CUBEMAP_ROUGHNESS_SOURCE_PANORAMA : CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_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)); + + blur.push_constant.pixel_size[0] = p_pixel_size.x; + blur.push_constant.pixel_size[1] = p_pixel_size.y; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + RasterizerEffectsRD::RasterizerEffectsRD() { - // Initialize blur - Vector blur_modes; - blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n"); - blur_modes.push_back("\n#define MODE_SSAO_MERGE\n"); - blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); + { + // Initialize blur + Vector blur_modes; + blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n"); + blur_modes.push_back("\n#define MODE_SSAO_MERGE\n"); + blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); + blur_modes.push_back("\n#define MODE_MIPMAP\n"); - blur.shader.initialize(blur_modes); - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - blur.shader_version = blur.shader.version_create(); + blur.shader.initialize(blur_modes); + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + blur.shader_version = blur.shader.version_create(); - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { + // Initialize roughness + Vector 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"); + 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].setup(roughness.shader.version_get_shader(roughness.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { + // 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); } RD::SamplerState sampler; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h index a51340b368..259eb32b76 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h @@ -1,8 +1,11 @@ #ifndef RASTERIZER_EFFECTS_RD_H #define RASTERIZER_EFFECTS_RD_H +#include "core/math/camera_matrix.h" #include "render_pipeline_vertex_format_cache_rd.h" -#include "shaders/blur.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h" class RasterizerEffectsRD { @@ -21,6 +24,7 @@ class RasterizerEffectsRD { BLUR_MODE_DOF_FAR_HIGH, BLUR_MODE_SSAO_MERGE, BLUR_MODE_SIMPLY_COPY, + BLUR_MODE_MIPMAP, BLUR_MODE_MAX, }; @@ -68,6 +72,44 @@ 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; + float roughness; + uint32_t use_direct_write; + }; + + struct CubemapRoughness { + + CubemapRoughnessPushConstant push_constant; + CubemapRoughnessShaderRD shader; + RID shader_version; + RenderPipelineVertexFormatCacheRD 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; + RID default_sampler; RID index_buffer; RID index_array; @@ -79,6 +121,9 @@ class RasterizerEffectsRD { public: void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region); 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 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); + 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); RasterizerEffectsRD(); ~RasterizerEffectsRD(); diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h index ca0103de7f..31d8c5bc17 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_rd.h @@ -85,7 +85,7 @@ public: _create_func = _create_current; } - virtual bool is_low_end() const { return true; } + virtual bool is_low_end() const { return false; } static ThreadWorkPool thread_work_pool; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp index 1eb0ab3d8d..b4c3e86194 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp @@ -254,6 +254,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) { RD::PipelineDepthStencilState depth_stencil_state; if (depth_test != DEPTH_TEST_DISABLED) { + depth_stencil_state.enable_depth_test = true; depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; } @@ -487,7 +488,7 @@ void RasterizerSceneForwardRD::MaterialData::update_parameters(const Mapuniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 3); + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 2); } RasterizerSceneForwardRD::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { @@ -563,6 +564,13 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_t color_fb = RD::get_singleton()->framebuffer_create(fb); } + + { + Vector fb; + fb.push_back(color); + + color_only_fb = RD::get_singleton()->framebuffer_create(fb); + } } RasterizerSceneRD::RenderBufferData *RasterizerSceneForwardRD::_create_render_buffer_data() { @@ -580,6 +588,7 @@ bool RasterizerSceneForwardRD::free(RID p_rid) { void RasterizerSceneForwardRD::instance_create_custom_data(InstanceBase *p_instance) { InstanceGeometryData *geom_data = memnew(InstanceGeometryData); geom_data->ubo = RD::get_singleton()->uniform_buffer_create(sizeof(InstanceGeometryData::UBO)); + geom_data->using_lightmap_gi = p_instance->lightmap.is_valid(); p_instance->custom_data = geom_data; } @@ -632,13 +641,13 @@ void RasterizerSceneForwardRD::instance_custom_data_update_transform(InstanceBas /// RENDERING /// -void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_screen_uniform_set, bool p_no_gi) { +void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; //global scope bindings - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, 0); MaterialData *prev_material = nullptr; // ShaderData *prev_shader = nullptr; @@ -827,11 +836,10 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l } } -void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { - Transform sky_orientation; +void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { CameraMatrix projection = p_cam_projection; - projection.flip_y(); + projection.flip_y(); // Vulkan and modern APIs use Y-Down //store camera into ubo store_camera(projection, scene_state.ubo.projection_matrix); @@ -842,8 +850,68 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const Camer //time global variables scene_state.ubo.time = time; - RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); + if (is_environment(p_environment)) { + VS::EnvironmentBG env_bg = environment_get_background(p_environment); + VS::EnvironmentAmbientSource ambient_src = environment_get_ambient_light_ambient_source(p_environment); + + float bg_energy = environment_get_bg_energy(p_environment); + scene_state.ubo.ambient_light_color_energy[3] = bg_energy; + + scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_environment); + + //ambient + if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) { + + Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? storage->render_target_get_clear_request_color(p_render_target) : environment_get_bg_color(p_environment); + color = color.to_linear(); + + scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy; + scene_state.ubo.use_ambient_light = true; + scene_state.ubo.use_ambient_cubemap = false; + } else { + + float energy = environment_get_ambient_light_ambient_energy(p_environment); + Color color = environment_get_ambient_light_color(p_environment); + color = color.to_linear(); + scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; + + Basis sky_transform = environment_get_sky_orientation(p_environment); + sky_transform = sky_transform.inverse() * p_cam_transform.basis; + store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + + scene_state.ubo.use_ambient_cubemap = (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && env_bg == VS::ENV_BG_SKY) || ambient_src == VS::ENV_AMBIENT_SOURCE_SKY; + scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == VS::ENV_AMBIENT_SOURCE_COLOR; + } + + //specular + VS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_environment); + if ((ref_src == VS::ENV_REFLECTION_SOURCE_BG && env_bg == VS::ENV_BG_SKY) || ref_src == VS::ENV_REFLECTION_SOURCE_SKY) { + scene_state.ubo.use_reflection_cubemap = true; + } else { + scene_state.ubo.use_reflection_cubemap = false; + } + + } else { + if (p_render_target.is_valid()) { + scene_state.ubo.use_ambient_light = true; + Color clear_color = storage->render_target_get_clear_request_color(p_render_target); + clear_color = clear_color.to_linear(); + scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; + scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; + scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; + scene_state.ubo.ambient_light_color_energy[3] = 1.0; + } else { + scene_state.ubo.use_ambient_light = false; + } + + scene_state.ubo.use_ambient_cubemap = false; + scene_state.ubo.use_reflection_cubemap = false; + } #if 0 //bg and ambient if (p_environment.is_valid()) { @@ -952,6 +1020,8 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const Camer glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data); glBindBuffer(GL_UNIFORM_BUFFER, 0); #endif + + RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); } void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode) { @@ -1239,6 +1309,38 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i } } +void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha) { + + ERR_FAIL_COND(!is_environment(p_environment)); + + RID sky = environment_get_sky(p_environment); + ERR_FAIL_COND(!sky.is_valid()); + RID panorama = sky_get_panorama_texture_rd(sky); + ERR_FAIL_COND(!panorama.is_valid()); + Basis sky_transform = environment_get_sky_orientation(p_environment); + sky_transform.invert(); + + float multiplier = environment_get_bg_energy(p_environment); + float custom_fov = environment_get_sky_custom_fov(p_environment); + // Camera + CameraMatrix camera; + + if (custom_fov) { + + float near_plane = p_projection.get_z_near(); + float far_plane = p_projection.get_z_far(); + float aspect = p_projection.get_aspect(); + + camera.set_perspective(custom_fov, aspect, near_plane, far_plane); + + } else { + camera = p_projection; + } + + sky_transform = p_transform.basis * sky_transform; + storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier); +} + void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data; @@ -1285,12 +1387,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; + RID render_target; + if (render_buffer) { scene_state.ubo.screen_pixel_size[0] = 1.0 / render_buffer->width; scene_state.ubo.screen_pixel_size[1] = 1.0 / render_buffer->height; + render_target = render_buffer->render_target; } - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); + _setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); #if 0 for (int i = 0; i < p_light_cull_count; i++) { @@ -1356,6 +1461,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co bool use_mrt = false; #endif + render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); #if 0 @@ -1620,18 +1726,79 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co } #endif + RID radiance_cubemap; + bool draw_sky = false; + + Color clear_color; + bool keep_color = false; + + if (is_environment(p_environment)) { + VS::EnvironmentBG bg_mode = environment_get_background(p_environment); + float bg_energy = environment_get_bg_energy(p_environment); + switch (bg_mode) { + case VS::ENV_BG_CLEAR_COLOR: { + clear_color = render_target.is_valid() ? storage->render_target_get_clear_request_color(render_target) : environment_get_bg_color(p_environment); + clear_color.r *= bg_energy; + clear_color.g *= bg_energy; + clear_color.b *= bg_energy; + } break; + case VS::ENV_BG_COLOR: { + clear_color = environment_get_bg_color(p_environment); + clear_color.r *= bg_energy; + clear_color.g *= bg_energy; + clear_color.b *= bg_energy; + } break; + case VS::ENV_BG_SKY: { + RID sky = environment_get_sky(p_environment); + if (sky.is_valid()) { + radiance_cubemap = sky_get_radiance_texture_rd(sky); + draw_sky = true; + } + } break; + case VS::ENV_BG_CANVAS: { + keep_color = true; + } break; + case VS::ENV_BG_KEEP: { + keep_color = true; + } break; + case VS::ENV_BG_CAMERA_FEED: { + + } break; + } + } else { + if (render_target.is_valid()) { + clear_color = storage->render_target_get_clear_request_color(render_target); + } + } + + _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap); + render_list.sort_by_key(false); + bool can_continue = true; //unless the middle buffers are needed + bool using_separate_specular = false; + { //regular forward for now Vector c; - c.push_back(Color(0, 0, 0, 1)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, c); - - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, default_render_buffer_uniform_set, render_buffer == nullptr); + c.push_back(clear_color.to_linear()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr); RD::get_singleton()->draw_list_end(); } + if (draw_sky) { + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH); + _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), p_environment, p_cam_projection, p_cam_transform, 1.0); + RD::get_singleton()->draw_list_end(); + + if (using_separate_specular && !can_continue) { + //can't continue, so close the buffers + //RD::get_singleton()->draw_list_begin(render_buffer->color_specular_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c); + //RD::get_singleton()->draw_list_end(); + } + } + //_render_list #if 0 if (state.directional_light_count == 0) { @@ -1721,8 +1888,8 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co render_list.sort_by_reverse_depth_and_priority(true); { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, default_render_buffer_uniform_set, render_buffer == nullptr); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr); RD::get_singleton()->draw_list_end(); } @@ -1806,6 +1973,90 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co #endif } +void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap) { + + if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + RD::get_singleton()->free(render_base_uniform_set); + } + + //default render buffer and scene state uniform set + + Vector uniforms; + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = p_depth_buffer.is_valid() ? p_depth_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = p_color_buffer.is_valid() ? p_color_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = p_normal_buffer.is_valid() ? p_normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = p_roughness_limit_buffer.is_valid() ? p_roughness_limit_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 5; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = p_radiance_cubemap.is_valid() ? p_radiance_cubemap : storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 6; + 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_MIMPAMPS, 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_MIMPAMPS_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_MIMPAMPS, 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_MIMPAMPS_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); + } + + { + RD::Uniform u; + u.binding = 7; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.uniform_buffer); + uniforms.push_back(u); + } + + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0); +} + RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL; void RasterizerSceneForwardRD::set_scene_pass(uint64_t p_pass) { @@ -1816,7 +2067,8 @@ void RasterizerSceneForwardRD::set_time(double p_time) { time = p_time; } -RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) { +RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) : + RasterizerSceneRD(p_storage) { singleton = this; storage = p_storage; @@ -1824,6 +2076,10 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag { String defines; + defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; + if (is_using_radiance_cubemap_array()) { + defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; + } Vector shader_versions; shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); @@ -1847,7 +2103,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag actions.renames["WORLD_MATRIX"] = "world_matrix"; actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; - actions.renames["INV_CAMERA_MATRIX"] = "scene_data.camera_inverse_matrix"; + actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; @@ -1907,21 +2163,21 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; - actions.usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; + actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; actions.usage_defines["BINORMAL"] = "@TANGENT"; - actions.usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; + actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; actions.usage_defines["RIM_TINT"] = "@RIM"; - actions.usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; + actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions.usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; + actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions.usage_defines["AO"] = "#define ENABLE_AO\n"; - actions.usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions.usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions.usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions.usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; + actions.usage_defines["AO"] = "#define AO_USED\n"; + actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; + actions.usage_defines["UV"] = "#define UV_USED\n"; + actions.usage_defines["UV2"] = "#define UV2_USED\n"; + actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions.usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; + actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; @@ -1982,77 +2238,23 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag scene_pass = 0; render_pass = 0; + scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); + { //default material and shader default_shader = storage->shader_create(); - storage->shader_set_code(default_shader, "shader_type spatial;\n"); + storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n"); default_material = storage->material_create(); storage->material_set_shader(default_material, default_shader); MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); } - - //default render buffer and scene state uniform set - - { - Vector uniforms; - { - RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - uniforms.push_back(u); - } - - scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); - - { - - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 4; - u.ids.push_back(scene_state.uniform_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 5; - 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_MIMPAMPS, 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_MIMPAMPS_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_MIMPAMPS, 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_MIMPAMPS_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); - } - - default_render_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0); - } } RasterizerSceneForwardRD::~RasterizerSceneForwardRD() { + //clear base uniform set if still valid + if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + RD::get_singleton()->free(render_base_uniform_set); + } } diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h index 299cd178e1..ca28678fcc 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h @@ -214,13 +214,11 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RID color; RID depth; RID color_fb; + RID color_only_fb; int width, height; RID render_target; - RID uniform_set_opaque; - RID uniform_set_alpha; - void clear(); virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa); @@ -229,18 +227,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { virtual RenderBufferData *_create_render_buffer_data(); - RID default_render_buffer_uniform_set; - /* Instance Data */ - - struct InstanceData { - struct UBO { - }; - - RID state_buffer; - RID uniform_set; - }; - - RID_Owner instance_data_owner; + RID render_base_uniform_set; + void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap); /* Scene State UBO */ @@ -260,6 +248,15 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { float time; float reflection_multiplier; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t use_ambient_light; + uint32_t use_ambient_cubemap; + uint32_t use_reflection_cubemap; + + float radiance_inverse_xform[12]; }; UBO ubo; @@ -427,14 +424,16 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { PASS_MODE_DEPTH_NORMAL_ROUGHNESS, }; - void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog); + void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_screen_uniform_set, bool p_no_gi); + void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi); _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode); _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode); 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(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp index 26598b70a4..ab63cd9343 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp @@ -1,4 +1,366 @@ #include "rasterizer_scene_rd.h" +#include "core/project_settings.h" + +RID RasterizerSceneRD::sky_create() { + return sky_owner.make_rid(Sky()); +} + +void RasterizerSceneRD::_sky_invalidate(Sky *p_sky) { + if (!p_sky->dirty) { + p_sky->dirty = true; + p_sky->dirty_list = dirty_sky_list; + dirty_sky_list = p_sky; + } +} + +void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + ERR_FAIL_COND(p_radiance_size < 32 || p_radiance_size > 2048); + if (sky->radiance_size == p_radiance_size) { + return; + } + sky->radiance_size = p_radiance_size; + _sky_invalidate(sky); + if (sky->radiance.is_valid()) { + //if size changes, everything must be cleared + RD::get_singleton()->free(sky->radiance); + //everything else gets dependency, erase, so just clean it up + sky->radiance = RID(); + sky->layers.clear(); + sky->radiance_base_cubemap = RID(); + } +} + +void RasterizerSceneRD::sky_set_mode(RID p_sky, VS::SkyMode p_mode) { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + + if (sky->mode == p_mode) { + return; + } + + sky->mode = p_mode; + _sky_invalidate(sky); +} + +void RasterizerSceneRD::sky_set_texture(RID p_sky, RID p_panorama) { + + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + + if (sky->panorama.is_valid()) { + sky->panorama = RID(); + RD::get_singleton()->free(sky->radiance); + sky->radiance = RID(); + } + + sky->panorama = p_panorama; + + if (!sky->panorama.is_valid()) + return; //cleared + + _sky_invalidate(sky); +} +void RasterizerSceneRD::_update_dirty_skys() { + + Sky *sky = dirty_sky_list; + + while (sky) { + + //update sky configuration if texture is missing + + if (sky->radiance.is_null()) { + //recreate radiance and all data + int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; + if (sky->mode == VS::SKY_MODE_REALTIME) { + //use less mipmaps + mipmaps = MIN(8, mipmaps); + } + + uint32_t w = sky->radiance_size, h = sky->radiance_size; + + if (sky_use_cubemap_array) { + //array (higher quality, 6 times more memory) + RD::TextureFormat tf; + tf.array_layers = roughness_layers * 6; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.mipmaps = mipmaps; + tf.width = w; + tf.height = h; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + for (int i = 0; i < roughness_layers; i++) { + Sky::Layer layer; + uint32_t mmw = w; + uint32_t mmh = h; + layer.mipmaps.resize(mipmaps); + for (int j = 0; j < mipmaps; j++) { + Sky::Layer::Mipmap &mm = layer.mipmaps.write[j]; + mm.size.width = mmw; + mm.size.height = mmh; + for (int k = 0; k < 6; k++) { + mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sky->radiance, i * 6 + k, j); + Vector fbtex; + fbtex.push_back(mm.views[k]); + mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); + } + + mmw = MAX(1, mmw >> 1); + mmh = MAX(1, mmh >> 1); + } + + sky->layers.push_back(layer); + } + + } else { + //regular cubemap, lower quality (aliasing, less memory) + RD::TextureFormat tf; + tf.array_layers = 6; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.type = RD::TEXTURE_TYPE_CUBE; + tf.mipmaps = roughness_layers; + tf.width = w; + tf.height = h; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Sky::Layer layer; + uint32_t mmw = w; + uint32_t mmh = h; + layer.mipmaps.resize(roughness_layers); + for (int j = 0; j < roughness_layers; j++) { + Sky::Layer::Mipmap &mm = layer.mipmaps.write[j]; + mm.size.width = mmw; + mm.size.height = mmh; + for (int k = 0; k < 6; k++) { + mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sky->radiance, k, j); + Vector fbtex; + fbtex.push_back(mm.views[k]); + mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); + } + + mmw = MAX(1, mmw >> 1); + mmh = MAX(1, mmh >> 1); + } + + sky->layers.push_back(layer); + } + + sky->radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sky->radiance, 0, 0, RD::TEXTURE_SLICE_CUBEMAP); + } + + RID panorama_texture = storage->texture_get_rd_texture(sky->panorama); + + if (panorama_texture.is_valid()) { + //is there a panorama texture? + + if (sky_use_cubemap_array) { + + if (sky->mode == VS::SKY_MODE_QUALITY) { + //render directly to the layers + for (int i = 0; i < sky->layers.size(); i++) { + for (int j = 0; j < 6; j++) { + storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[i].mipmaps[0].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (sky->layers.size() - 1.0)); + } + } + } else if (sky->mode == VS::SKY_MODE_REALTIME) { + //render to first mipmap + for (int j = 0; j < 6; j++) { + storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0.0); + } + //do the rest in other mipmaps and use cubemap itself as source + for (int i = 1; i < roughness_layers; i++) { + //render using a smaller mipmap, then copy to main layer + for (int j = 0; j < 6; j++) { + //storage->get_effects()->cubemap_roughness(sky->radiance_base_cubemap, false, sky->layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (sky->layers.size() - 1.0)); + storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (sky->layers.size() - 1.0)); + storage->get_effects()->copy(sky->layers[0].mipmaps[i].views[0], sky->layers[i].mipmaps[0].framebuffers[j], Rect2()); + } + } + } + + //generate mipmaps + + for (int i = 0; i < sky->layers.size(); i++) { + for (int j = 0; j < sky->layers[i].mipmaps.size() - 1; j++) { + for (int k = 0; k < 6; k++) { + RID view = sky->layers[i].mipmaps[j].views[k]; + RID fb = sky->layers[i].mipmaps[j + 1].framebuffers[k]; + Vector2 size = sky->layers[i].mipmaps[j].size; + size = Vector2(1.0 / size.x, 1.0 / size.y); + storage->get_effects()->make_mipmap(view, fb, size); + } + } + } + } else { + + if (sky->mode == VS::SKY_MODE_QUALITY) { + //render directly to the layers + for (int i = 0; i < sky->layers[0].mipmaps.size(); i++) { + for (int j = 0; j < 6; j++) { + storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (sky->layers[0].mipmaps.size() - 1.0)); + } + } + } else { + + for (int j = 0; j < 6; j++) { + storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0); + } + + for (int i = 1; i < sky->layers[0].mipmaps.size(); i++) { + for (int j = 0; j < 6; j++) { + storage->get_effects()->cubemap_roughness(sky->radiance_base_cubemap, false, sky->layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_realtime, float(i) / (sky->layers[0].mipmaps.size() - 1.0)); + } + } + } + } + } + + Sky *next = sky->dirty_list; + sky->dirty_list = nullptr; + sky->dirty = false; + sky = next; + } + + 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()); + + return sky->radiance; +} + +RID RasterizerSceneRD::environment_create() { + + return environment_owner.make_rid(Environent()); +} + +void RasterizerSceneRD::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->background = p_bg; +} +void RasterizerSceneRD::environment_set_sky(RID p_env, RID p_sky) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky = p_sky; +} +void RasterizerSceneRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky_custom_fov = p_scale; +} +void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky_orientation = p_orientation; +} +void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->bg_color = p_color; +} +void RasterizerSceneRD::environment_set_bg_energy(RID p_env, float p_energy) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->bg_energy = p_energy; +} +void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->canvas_max_layer = p_max_layer; +} +void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, VS::EnvironmentReflectionSource p_reflection_source) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->ambient_light = p_color; + env->ambient_source = p_ambient; + env->ambient_light_energy = p_energy; + env->ambient_sky_contribution = p_sky_contribution; + env->reflection_source = p_reflection_source; +} + +VS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); + return env->background; +} +RID RasterizerSceneRD::environment_get_sky(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, RID()); + return env->sky; +} +float RasterizerSceneRD::environment_get_sky_custom_fov(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->sky_custom_fov; +} +Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Basis()); + return env->sky_orientation; +} +Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->bg_color; +} +float RasterizerSceneRD::environment_get_bg_energy(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->bg_energy; +} +int RasterizerSceneRD::environment_get_canvas_max_layer(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->canvas_max_layer; +} +Color RasterizerSceneRD::environment_get_ambient_light_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->ambient_light; +} +VS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_light_ambient_source(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_AMBIENT_SOURCE_BG); + return env->ambient_source; +} +float RasterizerSceneRD::environment_get_ambient_light_ambient_energy(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->ambient_light_energy; +} +float RasterizerSceneRD::environment_get_ambient_sky_contribution(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->ambient_sky_contribution; +} +VS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_source(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_REFLECTION_SOURCE_DISABLED); + return env->reflection_source; +} + +bool RasterizerSceneRD::is_environment(RID p_env) const { + return environment_owner.owns(p_env); +} RID RasterizerSceneRD::render_buffers_create() { RenderBuffers rb; @@ -16,6 +378,14 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren rb->data->configure(p_render_target, p_width, p_height, p_msaa); } +int RasterizerSceneRD::get_roughness_layers() const { + return roughness_layers; +} + +bool RasterizerSceneRD::is_using_radiance_cubemap_array() const { + return sky_use_cubemap_array; +} + void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); @@ -30,6 +400,14 @@ bool RasterizerSceneRD::free(RID p_rid) { RenderBuffers *rb = render_buffers_owner.getornull(p_rid); memdelete(rb->data); render_buffers_owner.free(p_rid); + } else if (environment_owner.owns(p_rid)) { + //not much to delete, just free it + environment_owner.free(p_rid); + } else if (sky_owner.owns(p_rid)) { + _update_dirty_skys(); + Sky *sky = sky_owner.getornull(p_rid); + RD::get_singleton()->free(sky->radiance); //free radiance, everything else gets dependency-erased + sky_owner.free(p_rid); } else { return false; } @@ -37,5 +415,16 @@ bool RasterizerSceneRD::free(RID p_rid) { return true; } -RasterizerSceneRD::RasterizerSceneRD() { +void RasterizerSceneRD::update() { + _update_dirty_skys(); +} + +RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { + storage = p_storage; + + roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers"); + sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples"); + sky_ggx_samples_realtime = GLOBAL_GET("rendering/quality/reflections/ggx_samples_realtime"); + sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); + sky_use_cubemap_array = false; } diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h index 2019d4e5a5..59f28a167f 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h @@ -3,6 +3,9 @@ #include "core/rid_owner.h" #include "servers/visual/rasterizer.h" +#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/visual/rendering_device.h" + class RasterizerSceneRD : public RasterizerScene { protected: struct RenderBufferData { @@ -15,6 +18,58 @@ protected: virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; private: + int roughness_layers; + + RasterizerStorageRD *storage; + + struct Sky { + int radiance_size = 256; + VS::SkyMode mode = VS::SKY_MODE_QUALITY; + RID panorama; + RID radiance; + bool dirty = false; + Sky *dirty_list = nullptr; + struct Layer { + struct Mipmap { + RID framebuffers[6]; + RID views[6]; + Size2i size; + }; + Vector mipmaps; + }; + RID radiance_base_cubemap; //cubemap for first layer, first cubemap + Vector layers; + }; + + Sky *dirty_sky_list = nullptr; + + void _sky_invalidate(Sky *p_sky); + void _update_dirty_skys(); + + uint32_t sky_ggx_samples_quality; + uint32_t sky_ggx_samples_realtime; + bool sky_use_cubemap_array; + + mutable RID_Owner sky_owner; + + struct Environent { + + VS::EnvironmentBG background = VS::ENV_BG_CLEAR_COLOR; + RID sky; + float sky_custom_fov = 0.0; + Basis sky_orientation; + Color bg_color; + float bg_energy = 1.0; + int canvas_max_layer = 0; + VS::EnvironmentAmbientSource ambient_source = VS::ENV_AMBIENT_SOURCE_BG; + Color ambient_light; + float ambient_light_energy = 1.0; + float ambient_sky_contribution = 1.0; + VS::EnvironmentReflectionSource reflection_source = VS::ENV_REFLECTION_SOURCE_BG; + }; + + mutable RID_Owner environment_owner; + struct RenderBuffers { RenderBufferData *data = nullptr; @@ -23,7 +78,7 @@ private: RID render_target; }; - RID_Owner render_buffers_owner; + mutable RID_Owner render_buffers_owner; public: /* SHADOW ATLAS API */ @@ -36,18 +91,43 @@ public: int get_directional_light_shadow_size(RID p_light_intance) { return 0; } void set_directional_shadow_count(int p_count) {} + /* SKY API */ + + 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); + + RID sky_get_panorama_texture_rd(RID p_sky) const; + RID sky_get_radiance_texture_rd(RID p_sky) const; + /* ENVIRONMENT API */ - RID environment_create() { return RID(); } + RID environment_create(); - void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {} - 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_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) {} - void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) {} + void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); + 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_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); + void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG); + + VS::EnvironmentBG environment_get_background(RID p_env) const; + 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; + 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; + Color environment_get_ambient_light_color(RID p_env) const; + VS::EnvironmentAmbientSource environment_get_ambient_light_ambient_source(RID p_env) const; + float environment_get_ambient_light_ambient_energy(RID p_env) const; + float environment_get_ambient_sky_contribution(RID p_env) const; + VS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + + bool is_environment(RID p_env) const; void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} @@ -66,10 +146,6 @@ public: void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {} void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {} - bool is_environment(RID p_env) { return false; } - VS::EnvironmentBG environment_get_background(RID p_env) { return VS::ENV_BG_KEEP; } - int environment_get_canvas_max_layer(RID p_env) { return 0; } - RID light_instance_create(RID p_light) { return RID(); } void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {} void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {} @@ -97,9 +173,14 @@ public: void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + int get_roughness_layers() const; + bool is_using_radiance_cubemap_array() const; + virtual bool free(RID p_rid); - RasterizerSceneRD(); + virtual void update(); + + RasterizerSceneRD(RasterizerStorageRD *p_storage); }; #endif // RASTERIZER_SCENE_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp index 61f9a373a8..d28d2245cb 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp @@ -2598,6 +2598,61 @@ RasterizerStorageRD::RasterizerStorageRD() { default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); } + { //create default cubemap + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_CUBE; + + PoolVector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector > vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + PoolVector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector > vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } //default samplers for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h index dca270746b..1e9c137f6d 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h @@ -77,6 +77,8 @@ public: DEFAULT_RD_TEXTURE_NORMAL, DEFAULT_RD_TEXTURE_ANISO, DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, DEFAULT_RD_TEXTURE_MAX }; @@ -393,11 +395,6 @@ public: return default_rd_samplers[p_filter][p_repeat]; } - /* SKY API */ - - RID sky_create() { return RID(); } - void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) {} - /* SHADER API */ RID shader_create(); diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub index 65a40e981d..e8a62d0660 100644 --- a/servers/visual/rasterizer_rd/shaders/SCsub +++ b/servers/visual/rasterizer_rd/shaders/SCsub @@ -6,5 +6,7 @@ if 'RD_GLSL' in env['BUILDERS']: env.RD_GLSL('canvas.glsl'); env.RD_GLSL('canvas_occlusion.glsl'); env.RD_GLSL('blur.glsl'); + env.RD_GLSL('cubemap_roughness.glsl'); env.RD_GLSL('scene_forward.glsl'); - env.RD_GLSL('scene_forward_inc.glsl'); + env.RD_GLSL('sky.glsl'); + diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl index 830d4d7d94..4f47595d2c 100644 --- a/servers/visual/rasterizer_rd/shaders/blur.glsl +++ b/servers/visual/rasterizer_rd/shaders/blur.glsl @@ -85,6 +85,17 @@ const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.0 void main() { +#ifdef MODE_MIPMAP + + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(-0.5,-0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5,-0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5,0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(-0.5,0.5) * pix_size); + frag_color = color / 4.0; + +#endif + #ifdef MODE_GAUSSIAN_BLUR //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect diff --git a/servers/visual/rasterizer_rd/shaders/canvas.glsl b/servers/visual/rasterizer_rd/shaders/canvas.glsl index 63d2251465..f6c5251760 100644 --- a/servers/visual/rasterizer_rd/shaders/canvas.glsl +++ b/servers/visual/rasterizer_rd/shaders/canvas.glsl @@ -13,8 +13,7 @@ layout(location = 0) in vec2 vertex_attrib; layout(location = 3) in vec4 color_attrib; layout(location = 4) in vec2 uv_attrib; -layout(location = 6) in uvec4 bone_indices_attrib; -layout(location = 7) in vec4 bone_weights_attrib; +layout(location = 6) in uvec4 bones_attrib; #endif @@ -68,8 +67,7 @@ void main() { uv = draw_data.uvs[2]; color = vec4(unpackHalf2x16(draw_data.colors[4]),unpackHalf2x16(draw_data.colors[5])); } - uvec4 bone_indices = uvec4(0,0,0,0); - vec4 bone_weights = vec4(0,0,0,0); + uvec4 bones = uvec4(0,0,0,0); #elif defined(USE_ATTRIBUTES) @@ -77,8 +75,7 @@ void main() { vec4 color = color_attrib; vec2 uv = uv_attrib; - uvec4 bone_indices = bone_indices_attrib; - vec4 bone_weights = bone_weights_attrib; + uvec4 bones = bones_attrib; #else vec2 vertex_base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0)); @@ -87,8 +84,7 @@ void main() { vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags&FLAGS_TRANSPOSE_RECT)!=0 ? vertex_base.yx : vertex_base.xy); vec4 color = draw_data.modulation; vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); - uvec4 bone_indices = uvec4(0,0,0,0); - vec4 bone_weights = vec4(0,0,0,0); + uvec4 bones = uvec4(0,0,0,0); #endif diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl new file mode 100644 index 0000000000..f741fab355 --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl @@ -0,0 +1,234 @@ +/* clang-format off */ +[vertex] +/* clang-format on */ + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* clang-format on */ + + +layout(location=0) out highp vec2 uv_interp; + + +void main() { + + vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0)); + uv_interp = base_arr[gl_VertexIndex]; + gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0); + +} + +/* clang-format off */ +[fragment] +/* clang-format on */ + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* 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(push_constant, binding = 1, std430) uniform Params { + uint face_id; + uint sample_count; + float roughness; + bool use_direct_write; +} params; + +layout(location=0) in vec2 uv_interp; + +layout(location = 0) out vec4 frag_color; + +#define M_PI 3.14159265359 + +vec3 texelCoordToVec(vec2 uv, uint faceID) { + mat3 faceUvVectors[6]; + /* + // -x + faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face + */ + + // -x + faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face + + // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. + vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; + return normalize(result); +} + +vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { + float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] + + // Compute distribution direction + float Phi = 2.0 * M_PI * Xi.x; + float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + + // Convert to spherical direction + vec3 H; + H.x = SinTheta * cos(Phi); + H.y = SinTheta * sin(Phi); + H.z = CosTheta; + + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 TangentX = normalize(cross(UpVector, N)); + vec3 TangentY = cross(N, TangentX); + + // Tangent to world space + return TangentX * H.x + TangentY * H.y + N * H.z; +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float GGX(float NdotV, float a) { + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float G_Smith(float a, float nDotV, float nDotL) { + return GGX(nDotL, a * a) * GGX(nDotV, a * a); +} + +float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +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() { + + vec2 uv = (uv_interp * 2.0) - 1.0; + vec3 N = texelCoordToVec(uv, params.face_id); + + //vec4 color = color_interp; + + if (params.use_direct_write) { + +#ifdef MODE_SOURCE_PANORAMA + + frag_color = vec4(texturePanorama(N, source_panorama).rgb, 1.0); +#endif + +#ifdef MODE_SOURCE_CUBEMAP + frag_color = vec4(texture(source_cube,N).rgb, 1.0); +#endif + + } else { + + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + + for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) { + vec2 xi = Hammersley(sampleNum, params.sample_count); + + vec3 H = ImportanceSampleGGX(xi, params.roughness, N); + vec3 V = N; + vec3 L = (2.0 * dot(V, H) * H - V); + + 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; + } + } + sum /= sum.a; + + frag_color = vec4(sum.rgb, 1.0); + } +} diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl index 57fcd049b5..df31d8c26f 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl @@ -44,7 +44,7 @@ layout(location = 2) out vec4 color_interp; #endif #if defined(UV_USED) -layout(location = 3) out vec4 uv_interp; +layout(location = 3) out vec2 uv_interp; #endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) @@ -186,7 +186,7 @@ VERTEX_SHADER_CODE #endif //MODE_RENDER_DEPTH #ifdef USE_OVERRIDE_POSITION - gl_Position = position;; + gl_Position = position; #else gl_Position = projection_matrix * vec4(vertex_interp, 1.0); #endif @@ -215,7 +215,7 @@ layout(location = 2) in vec4 color_interp; #endif #if defined(UV_USED) -layout(location = 3) in vec4 uv_interp; +layout(location = 3) in vec2 uv_interp; #endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) @@ -351,15 +351,15 @@ LIGHT_SHADER_CODE float NdotV = dot(N, V); float cNdotV = max(NdotV, 0.0); -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) vec3 H = normalize(V + L); #endif -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) float cNdotH = max(dot(N, H), 0.0); #endif -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) float cLdotH = max(dot(L, H), 0.0); #endif @@ -423,7 +423,7 @@ LIGHT_SHADER_CODE diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; #endif -#if defined(LIGHT_USE_RIM) +#if defined(RIM_LIGHT_USED) float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; #endif @@ -495,7 +495,7 @@ LIGHT_SHADER_CODE specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif -#if defined(LIGHT_USE_CLEARCOAT) +#if defined(LIGHT_CLEARCOAT_USED) #if !defined(SPECULAR_SCHLICK_GGX) float cLdotH5 = SchlickFresnel(cLdotH); @@ -537,7 +537,7 @@ void main() { float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); -#if defined(ENABLE_AO) +#if defined(AO_USED) float ao = 1.0; float ao_light_affect = 0.0; #endif @@ -651,6 +651,48 @@ FRAGMENT_SHADER_CODE vec3 diffuse_light = vec3(0.0, 0.0, 0.0); vec3 ambient_light = vec3( 0.0, 0.0, 0.0); +#ifndef MODE_RENDER_DEPTH + if (scene_data.use_reflection_cubemap){ + + vec3 ref_vec = reflect(-view, normal); + ref_vec = scene_data.radiance_inverse_xform * ref_vec; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + + float lod,blend; + blend = modf(roughness * MAX_ROUGHNESS_LOD, lod); + specular_light = texture(samplerCubeArray(radiance_cubemap,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; + specular_light = mix(specular_light,texture(samplerCubeArray(radiance_cubemap,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod+1)).rgb,blend); + +#else + specular_light = textureLod(samplerCube(radiance_cubemap,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb; + +#endif //USE_RADIANCE_CUBEMAP_ARRAY + specular_light *= scene_data.ambient_light_color_energy.a; + } + +#ifndef USE_LIGHTMAP + //lightmap overrides everything + if (scene_data.use_ambient_light){ + + ambient_light = scene_data.ambient_light_color_energy.rgb; + + if (scene_data.use_ambient_cubemap) { + vec3 ambient_dir = scene_data.radiance_inverse_xform * normal; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb; +#else + vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb; +#endif //USE_RADIANCE_CUBEMAP_ARRAY + + ambient_light = mix( ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix ); + } + + + } +#endif // USE_LIGHTMAP + +#endif // MODE_RENDER_DEPTH + //radiance float specular_blob_intensity = 1.0; @@ -722,7 +764,7 @@ FRAGMENT_SHADER_CODE specular_light *= scene_data.reflection_multiplier; ambient_light *= albedo; //ambient must be multiplied by albedo at the end -#if defined(ENABLE_AO) +#if defined(AO_USED) ambient_light *= ao; ao_light_affect = mix(1.0, ao, ao_light_affect); specular_light *= ao_light_affect; @@ -753,8 +795,8 @@ FRAGMENT_SHADER_CODE #ifdef USE_NO_SHADING frag_color = vec4(albedo, alpha); #else - //frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); - frag_color = vec4(1.0); + frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); + //frag_color = vec4(1.0); #endif //USE_NO_SHADING diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl index c481ddf8f4..3547cad46c 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl @@ -7,8 +7,35 @@ layout(set=0,binding=1) uniform texture2D depth_buffer; layout(set=0,binding=2) uniform texture2D color_buffer; layout(set=0,binding=3) uniform texture2D normal_buffer; +layout(set=0,binding=4) uniform texture2D roughness_limit; -layout(set=0,binding=4,std140) uniform SceneData { +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + +layout(set = 0, binding = 5) uniform textureCubeArray radiance_cubemap; + +#else + +layout(set = 0, binding = 5) uniform textureCube radiance_cubemap; + +#endif + + +#define SAMPLER_NEAREST_CLAMP 0 +#define SAMPLER_LINEAR_CLAMP 1 +#define SAMPLER_NEAREST_WITH_MIMPAMPS_CLAMP 2 +#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 +#define SAMPLER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC_CLAMP 4 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 +#define SAMPLER_NEAREST_REPEAT 6 +#define SAMPLER_LINEAR_REPEAT 7 +#define SAMPLER_NEAREST_WITH_MIMPAMPS_REPEAT 8 +#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 +#define SAMPLER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC_REPEAT 10 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 + +layout(set = 0, binding = 6) uniform sampler material_samplers[12]; + +layout(set=0,binding=7,std140) uniform SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; @@ -27,6 +54,15 @@ layout(set=0,binding=4,std140) uniform SceneData { float time; float reflection_multiplier; // one normally, zero when rendering reflections + vec4 ambient_light_color_energy; + + float ambient_color_sky_mix; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; + + mat3 radiance_inverse_xform; + #if 0 vec4 ambient_light_color; vec4 bg_color; @@ -65,7 +101,6 @@ layout(set=0,binding=4,std140) uniform SceneData { #endif } scene_data; -layout(set = 0, binding = 5) uniform sampler material_samplers[12]; #if 0 struct DirectionalLightData { diff --git a/servers/visual/rasterizer_rd/shaders/sky.glsl b/servers/visual/rasterizer_rd/shaders/sky.glsl new file mode 100644 index 0000000000..a32a1da41c --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/sky.glsl @@ -0,0 +1,89 @@ +/* clang-format off */ +[vertex] +/* clang-format on */ + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* clang-format on */ + +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; + +} params; + +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); + +} + +/* clang-format off */ +[fragment] +/* clang-format on */ + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* clang-format on */ + +#define M_PI 3.14159265359 + +layout(location =0) in vec2 uv_interp; + +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; + +} params; + + +vec4 texturePanorama(sampler2D pano, vec3 normal) { + + 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 texture(pano, st); +} + + +layout(location = 0) out vec4 frag_color; + + +void main() { + + vec3 cube_normal; + cube_normal.z = -1000000.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; + frag_color.a = params.alpha; + +} diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h index 64c4f0f0c1..32d5520c0a 100644 --- a/servers/visual/rendering_device.h +++ b/servers/visual/rendering_device.h @@ -409,7 +409,13 @@ public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector > &p_data = Vector >()) = 0; virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0; - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap) = 0; + + enum TextureSliceType { + TEXTURE_SLICE_2D, + TEXTURE_SLICE_CUBEMAP + }; + + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector &p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls virtual PoolVector texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 1b9f5b58b2..0910bf3a9f 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -105,6 +105,8 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) { VSG::scene->update_dirty_instances(); //update scene stuff + VSG::scene_render->update(); + VSG::viewport->draw_viewports(); VSG::scene->render_probes(); VSG::canvas_render->update(); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 3168359473..bef82a7da4 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -186,11 +186,6 @@ public: BIND2(texture_set_force_redraw_if_visible, RID, bool) - /* SKY API */ - - BIND0R(RID, sky_create) - BIND3(sky_set_texture, RID, RID, int) - /* SHADER API */ BIND0R(RID, shader_create) @@ -494,6 +489,13 @@ public: //from now on, calls forwarded to this singleton #define BINDBASE VSG::scene_render + /* SKY API */ + + BIND0R(RID, sky_create) + BIND2(sky_set_radiance_size, RID, int) + BIND2(sky_set_mode, RID, SkyMode) + BIND2(sky_set_texture, RID, RID) + BIND0R(RID, environment_create) BIND2(environment_set_background, RID, EnvironmentBG) @@ -503,7 +505,8 @@ public: BIND2(environment_set_bg_color, RID, const Color &) BIND2(environment_set_bg_energy, RID, float) BIND2(environment_set_canvas_max_layer, RID, int) - BIND4(environment_set_ambient_light, RID, const Color &, float, float) + BIND6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource) + // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 BIND2(environment_set_camera_feed_id, RID, int) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 76ff6265cc..ae95fe386d 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -711,7 +711,9 @@ void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap instance->lightmap = p_lightmap; } - VSG::scene_render->instance_custom_data_update_lightmap(instance); + if (instance->custom_data) { + VSG::scene_render->instance_custom_data_update_lightmap(instance); + } } void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 135e4a8bd0..ac4b5c3ecb 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -117,11 +117,6 @@ public: FUNC2(texture_set_force_redraw_if_visible, RID, bool) - /* SKY API */ - - FUNCRID(sky) - FUNC3(sky_set_texture, RID, RID, int) - /* SHADER API */ FUNCRID(shader) @@ -409,6 +404,13 @@ public: FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw) + /* SKY API */ + + FUNCRID(sky) + FUNC2(sky_set_radiance_size, RID, int) + FUNC2(sky_set_mode, RID, SkyMode) + FUNC2(sky_set_texture, RID, RID) + /* ENVIRONMENT API */ FUNCRID(environment) @@ -420,7 +422,8 @@ public: FUNC2(environment_set_bg_color, RID, const Color &) FUNC2(environment_set_bg_energy, RID, float) FUNC2(environment_set_canvas_max_layer, RID, int) - FUNC4(environment_set_ambient_light, RID, const Color &, float, float) + FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource) + // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 FUNC2(environment_set_camera_feed_id, RID, int) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 7aa2160545..e83498389e 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1602,7 +1602,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", "cube_map", "radiance_size"), &VisualServer::sky_set_texture); + ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "panorama"), &VisualServer::sky_set_texture); #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); @@ -2171,11 +2171,19 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(ENV_BG_CLEAR_COLOR); BIND_ENUM_CONSTANT(ENV_BG_COLOR); BIND_ENUM_CONSTANT(ENV_BG_SKY); - BIND_ENUM_CONSTANT(ENV_BG_COLOR_SKY); BIND_ENUM_CONSTANT(ENV_BG_CANVAS); BIND_ENUM_CONSTANT(ENV_BG_KEEP); BIND_ENUM_CONSTANT(ENV_BG_MAX); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_BG); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_COLOR); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_SKY); + + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_BG); + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_SKY); + BIND_ENUM_CONSTANT(ENV_DOF_BLUR_QUALITY_LOW); BIND_ENUM_CONSTANT(ENV_DOF_BLUR_QUALITY_MEDIUM); BIND_ENUM_CONSTANT(ENV_DOF_BLUR_QUALITY_HIGH); @@ -2290,12 +2298,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,PCF5,PCF13")); + GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 6); GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true); GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false); - GLOBAL_DEF("rendering/quality/reflections/high_quality_ggx", true); - GLOBAL_DEF("rendering/quality/reflections/high_quality_ggx.mobile", false); - GLOBAL_DEF("rendering/quality/reflections/irradiance_max_size", 128); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/irradiance_max_size", PropertyInfo(Variant::INT, "rendering/quality/reflections/irradiance_max_size", PROPERTY_HINT_RANGE, "32,2048")); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime", 64); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime.mobile", 16); GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false); GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true); diff --git a/servers/visual_server.h b/servers/visual_server.h index e2c27675fb..fe64f1a04c 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -156,11 +156,6 @@ public: virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - /* SKY API */ - - virtual RID sky_create() = 0; - virtual void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) = 0; - /* SHADER API */ enum ShaderMode { @@ -678,6 +673,18 @@ public: virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0; + /* SKY API */ + + enum SkyMode { + SKY_MODE_QUALITY, + SKY_MODE_REALTIME + }; + + 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; + /* ENVIRONMENT API */ virtual RID environment_create() = 0; @@ -687,13 +694,25 @@ public: ENV_BG_CLEAR_COLOR, ENV_BG_COLOR, ENV_BG_SKY, - ENV_BG_COLOR_SKY, ENV_BG_CANVAS, ENV_BG_KEEP, ENV_BG_CAMERA_FEED, ENV_BG_MAX }; + enum EnvironmentAmbientSource { + ENV_AMBIENT_SOURCE_BG, + ENV_AMBIENT_SOURCE_DISABLED, + ENV_AMBIENT_SOURCE_COLOR, + ENV_AMBIENT_SOURCE_SKY, + }; + + enum EnvironmentReflectionSource { + ENV_REFLECTION_SOURCE_BG, + ENV_REFLECTION_SOURCE_DISABLED, + ENV_REFLECTION_SOURCE_SKY, + }; + virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0; 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; @@ -701,7 +720,7 @@ public: 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; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG) = 0; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; @@ -1093,6 +1112,8 @@ VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode); VARIANT_ENUM_CAST(VisualServer::ReflectionProbeUpdateMode); VARIANT_ENUM_CAST(VisualServer::ParticlesDrawOrder); VARIANT_ENUM_CAST(VisualServer::EnvironmentBG); +VARIANT_ENUM_CAST(VisualServer::EnvironmentAmbientSource); +VARIANT_ENUM_CAST(VisualServer::EnvironmentReflectionSource); VARIANT_ENUM_CAST(VisualServer::EnvironmentDOFBlurQuality); VARIANT_ENUM_CAST(VisualServer::EnvironmentGlowBlendMode); VARIANT_ENUM_CAST(VisualServer::EnvironmentToneMapper);