Use subpasses to do 3D rendering and resolve in mobile renderer
This commit is contained in:
parent
2f1bc509dc
commit
b920bf05a4
|
@ -1148,7 +1148,7 @@
|
|||
</constant>
|
||||
<constant name="TEXTURE_USAGE_CAN_COPY_TO_BIT" value="256" enum="TextureUsageBits">
|
||||
</constant>
|
||||
<constant name="TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT" value="512" enum="TextureUsageBits">
|
||||
<constant name="TEXTURE_USAGE_INPUT_ATTACHMENT_BIT" value="512" enum="TextureUsageBits">
|
||||
</constant>
|
||||
<constant name="TEXTURE_SWIZZLE_IDENTITY" value="0" enum="TextureSwizzle">
|
||||
</constant>
|
||||
|
|
|
@ -1804,6 +1804,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
|
|||
image_create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
if (p_format.usage_bits & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT) {
|
||||
image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) {
|
||||
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
|
@ -2134,6 +2138,10 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
|
|||
}
|
||||
}
|
||||
|
||||
if (texture.usage_flags & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT) {
|
||||
usage_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
usage_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
|
@ -3275,8 +3283,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
|||
for (int i = 0; i < p_attachments.size(); i++) {
|
||||
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE);
|
||||
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE);
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)),
|
||||
VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (depth, stencil or resolve) bit set.");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)),
|
||||
VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set.");
|
||||
|
||||
VkAttachmentDescription description = {};
|
||||
description.flags = 0;
|
||||
|
@ -3473,7 +3481,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
|||
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
} else {
|
||||
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), input attachment (" + itos(j) + ").");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as depth, but it's not usable as input attachment.");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it isn't marked as an input texture.");
|
||||
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
||||
reference.attachment = attachment;
|
||||
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
@ -3497,12 +3505,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
|||
} else {
|
||||
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment (" + itos(j) + ").");
|
||||
ERR_FAIL_COND_V_MSG(pass->color_attachments[j] == FramebufferPass::ATTACHMENT_UNUSED, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment (" + itos(j) + "), the respective color attachment is marked as unused.");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as depth, but it's not usable as resolve attachment.");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment, it isn't marked as a color texture.");
|
||||
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
||||
bool multisample = p_attachments[attachment].samples > TEXTURE_SAMPLES_1;
|
||||
ERR_FAIL_COND_V_MSG(multisample, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachments can't be multisample.");
|
||||
reference.attachment = attachment;
|
||||
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
attachment_last_pass[attachment] = i;
|
||||
}
|
||||
resolve_references.push_back(reference);
|
||||
|
@ -3632,8 +3640,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
|||
render_pass_create_info.pDependencies = nullptr;
|
||||
}
|
||||
|
||||
// These are only used if we use multiview but we need to define them in scope.
|
||||
const uint32_t view_mask = (1 << p_view_count) - 1;
|
||||
const uint32_t correlation_mask = (1 << p_view_count) - 1;
|
||||
Vector<uint32_t> view_masks;
|
||||
VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info;
|
||||
|
||||
if (p_view_count > 1) {
|
||||
|
@ -3645,10 +3655,15 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
|||
// Make sure we limit this to the number of views we support.
|
||||
ERR_FAIL_COND_V_MSG(p_view_count > capabilities.max_view_count, VK_NULL_HANDLE, "Hardware does not support requested number of views for Multiview render pass");
|
||||
|
||||
// Set view masks for each subpass
|
||||
for (uint32_t i = 0; i < subpasses.size(); i++) {
|
||||
view_masks.push_back(view_mask);
|
||||
};
|
||||
|
||||
render_pass_multiview_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
|
||||
render_pass_multiview_create_info.pNext = nullptr;
|
||||
render_pass_multiview_create_info.subpassCount = 1;
|
||||
render_pass_multiview_create_info.pViewMasks = &view_mask;
|
||||
render_pass_multiview_create_info.subpassCount = subpasses.size();
|
||||
render_pass_multiview_create_info.pViewMasks = view_masks.ptr();
|
||||
render_pass_multiview_create_info.dependencyCount = 0;
|
||||
render_pass_multiview_create_info.pViewOffsets = nullptr;
|
||||
render_pass_multiview_create_info.correlationMaskCount = 1;
|
||||
|
@ -4506,6 +4521,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
|
|||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
|
||||
ERR_PRINT("Acceleration structure not supported.");
|
||||
|
@ -5490,7 +5506,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
|
|||
img_info.sampler = *sampler;
|
||||
img_info.imageView = texture->view;
|
||||
|
||||
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)) {
|
||||
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
|
||||
UniformSet::AttachableTexture attachable_texture;
|
||||
attachable_texture.bind = set_uniform.binding;
|
||||
attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1];
|
||||
|
@ -5543,7 +5559,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
|
|||
img_info.sampler = VK_NULL_HANDLE;
|
||||
img_info.imageView = texture->view;
|
||||
|
||||
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)) {
|
||||
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
|
||||
UniformSet::AttachableTexture attachable_texture;
|
||||
attachable_texture.bind = set_uniform.binding;
|
||||
attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j];
|
||||
|
@ -7416,6 +7432,10 @@ void RenderingDeviceVulkan::draw_list_disable_scissor(DrawListID p_list) {
|
|||
vkCmdSetScissor(dl->command_buffer, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
uint32_t RenderingDeviceVulkan::draw_list_get_current_pass() {
|
||||
return draw_list_current_subpass;
|
||||
}
|
||||
|
||||
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_switch_to_next_pass() {
|
||||
ERR_FAIL_COND_V(draw_list == nullptr, INVALID_ID);
|
||||
ERR_FAIL_COND_V(draw_list_current_subpass >= draw_list_subpass_count - 1, INVALID_FORMAT_ID);
|
||||
|
|
|
@ -1149,6 +1149,7 @@ public:
|
|||
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);
|
||||
virtual void draw_list_disable_scissor(DrawListID p_list);
|
||||
|
||||
virtual uint32_t draw_list_get_current_pass();
|
||||
virtual DrawListID draw_list_switch_to_next_pass();
|
||||
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids);
|
||||
|
||||
|
|
|
@ -70,6 +70,28 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
|
|||
return uniform_set;
|
||||
}
|
||||
|
||||
RID EffectsRD::_get_uniform_set_for_input(RID p_texture) {
|
||||
if (input_to_uniform_set_cache.has(p_texture)) {
|
||||
RID uniform_set = input_to_uniform_set_cache[p_texture];
|
||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
return uniform_set;
|
||||
}
|
||||
}
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(p_texture);
|
||||
uniforms.push_back(u);
|
||||
// This is specific to our subpass shader
|
||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0);
|
||||
|
||||
input_to_uniform_set_cache[p_texture] = uniform_set;
|
||||
|
||||
return uniform_set;
|
||||
}
|
||||
|
||||
RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
|
||||
if (texture_to_uniform_set_cache.has(p_texture)) {
|
||||
RID uniform_set = texture_to_uniform_set_cache[p_texture];
|
||||
|
@ -85,7 +107,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
|
|||
u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
|
||||
u.ids.push_back(p_texture);
|
||||
uniforms.push_back(u);
|
||||
//anything with the same configuration (one texture in binding 0 for set 0), is good
|
||||
// anything with the same configuration (one texture in binding 0 for set 0), is good
|
||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
|
||||
|
||||
texture_to_uniform_set_cache[p_texture] = uniform_set;
|
||||
|
@ -778,11 +800,11 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
|
|||
|
||||
if (p_settings.view_count > 1) {
|
||||
// Use MULTIVIEW versions
|
||||
mode += 4;
|
||||
mode += 6;
|
||||
}
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2);
|
||||
|
@ -794,6 +816,45 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
|
|||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
|
||||
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
||||
|
||||
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
||||
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
||||
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
||||
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
||||
|
||||
ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
|
||||
tonemap.push_constant.use_glow = p_settings.use_glow;
|
||||
|
||||
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
|
||||
if (p_settings.view_count > 1) {
|
||||
// Use MULTIVIEW versions
|
||||
mode += 6;
|
||||
}
|
||||
|
||||
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
||||
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
||||
tonemap.push_constant.exposure = p_settings.exposure;
|
||||
tonemap.push_constant.white = p_settings.white;
|
||||
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
|
||||
|
||||
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
||||
|
||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); // should be set to a default texture, it's ignored
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
|
||||
}
|
||||
|
||||
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
|
||||
|
||||
|
@ -1813,12 +1874,16 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n");
|
||||
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
|
||||
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
||||
tonemap_modes.push_back("\n#define SUBPASS\n");
|
||||
tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
|
||||
|
||||
// multiview versions of our shaders
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n");
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
|
||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
|
||||
|
||||
tonemap.shader.initialize(tonemap_modes);
|
||||
|
||||
|
@ -1827,6 +1892,8 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
|
||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
|
||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
|
||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
|
||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
|
||||
}
|
||||
|
||||
tonemap.shader_version = tonemap.shader.version_create();
|
||||
|
|
|
@ -238,11 +238,15 @@ private:
|
|||
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
|
||||
TONEMAP_MODE_1D_LUT,
|
||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
|
||||
TONEMAP_MODE_SUBPASS,
|
||||
TONEMAP_MODE_SUBPASS_1D_LUT,
|
||||
|
||||
TONEMAP_MODE_NORMAL_MULTIVIEW,
|
||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
|
||||
TONEMAP_MODE_1D_LUT_MULTIVIEW,
|
||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
|
||||
TONEMAP_MODE_SUBPASS_MULTIVIEW,
|
||||
TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
|
||||
|
||||
TONEMAP_MODE_MAX
|
||||
};
|
||||
|
@ -718,6 +722,7 @@ private:
|
|||
RID index_array;
|
||||
|
||||
Map<RID, RID> texture_to_uniform_set_cache;
|
||||
Map<RID, RID> input_to_uniform_set_cache;
|
||||
|
||||
Map<RID, RID> image_to_uniform_set_cache;
|
||||
|
||||
|
@ -751,6 +756,7 @@ private:
|
|||
Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
|
||||
|
||||
RID _get_uniform_set_from_image(RID p_texture);
|
||||
RID _get_uniform_set_for_input(RID p_texture);
|
||||
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||
RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
|
||||
|
@ -842,6 +848,7 @@ public:
|
|||
};
|
||||
|
||||
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
|
||||
void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
|
||||
|
||||
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
|
||||
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
|
||||
|
|
|
@ -183,7 +183,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
|||
}
|
||||
}
|
||||
|
||||
void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
|
||||
void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
|
||||
clear();
|
||||
|
||||
ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support");
|
||||
|
@ -1555,6 +1555,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
|||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
if (p_render_data->render_buffers.is_valid()) {
|
||||
_debug_draw_cluster(p_render_data->render_buffers);
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
||||
_render_buffers_post_process_and_tonemap(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_render_shadow_begin() {
|
||||
|
|
|
@ -112,7 +112,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
void ensure_specular();
|
||||
void ensure_voxelgi();
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
|
||||
|
||||
~RenderBufferDataForwardClustered();
|
||||
};
|
||||
|
|
|
@ -78,12 +78,16 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
|
|||
|
||||
color = RID();
|
||||
depth = RID();
|
||||
color_fb = RID();
|
||||
for (int i = 0; i < FB_CONFIG_MAX; i++) {
|
||||
color_fbs[i] = RID();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
|
||||
clear();
|
||||
|
||||
bool is_half_resolution = false; // Set this once we support this feature.
|
||||
|
||||
msaa = p_msaa;
|
||||
|
||||
width = p_width;
|
||||
|
@ -93,15 +97,50 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
|||
color = p_color_buffer;
|
||||
depth = p_depth_buffer;
|
||||
|
||||
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
|
||||
// We are creating 4 configurations here for our framebuffers.
|
||||
|
||||
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_color_buffer);
|
||||
fb.push_back(depth);
|
||||
fb.push_back(p_color_buffer); // 0 - color buffer
|
||||
fb.push_back(depth); // 1 - depth buffer
|
||||
|
||||
color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
|
||||
// re-using the same attachments
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
// - add sky pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
// - add alpha pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
if (!is_half_resolution) {
|
||||
// - add blit to 2D pass
|
||||
fb.push_back(p_target_buffer); // 2 - target buffer
|
||||
|
||||
RD::FramebufferPass blit_pass;
|
||||
blit_pass.color_attachments.push_back(2);
|
||||
blit_pass.input_attachments.push_back(0);
|
||||
passes.push_back(blit_pass);
|
||||
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
} else {
|
||||
// can't do our blit pass if resolutions don't match
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
|
||||
}
|
||||
} else {
|
||||
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
|
||||
|
||||
RD::TextureFormat tf;
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
|
@ -134,14 +173,87 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
|||
|
||||
{
|
||||
Vector<RID> fb;
|
||||
fb.push_back(color_msaa);
|
||||
fb.push_back(depth_msaa);
|
||||
fb.push_back(color_msaa); // 0 - msaa color buffer
|
||||
fb.push_back(depth_msaa); // 1 - msaa depth buffer
|
||||
|
||||
color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
|
||||
// re-using the same attachments
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - add sky pass
|
||||
fb.push_back(color); // 2 - color buffer
|
||||
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
|
||||
{
|
||||
// but with resolve for our 2 subpass config
|
||||
Vector<RD::FramebufferPass> two_passes;
|
||||
two_passes.push_back(pass); // opaque subpass without resolve
|
||||
pass.resolve_attachments.push_back(2);
|
||||
two_passes.push_back(pass); // sky subpass with resolve
|
||||
|
||||
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
|
||||
}
|
||||
|
||||
// - add alpha pass (with resolve, we just added that above)
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
{
|
||||
// we also need our one pass with resolve
|
||||
Vector<RD::FramebufferPass> one_pass_with_resolve;
|
||||
one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
|
||||
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
|
||||
}
|
||||
|
||||
if (!is_half_resolution) {
|
||||
// - add blit to 2D pass
|
||||
fb.push_back(p_target_buffer); // 3 - target buffer
|
||||
RD::FramebufferPass blit_pass;
|
||||
blit_pass.color_attachments.push_back(3);
|
||||
blit_pass.input_attachments.push_back(2);
|
||||
passes.push_back(blit_pass);
|
||||
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
} else {
|
||||
// can't do our blit pass if resolutions don't match
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
|
||||
// Our attachments
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_color); // 0
|
||||
fb.push_back(p_depth); // 1
|
||||
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
|
||||
// re-using the same attachments
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - sky pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - alpha pass
|
||||
passes.push_back(pass);
|
||||
|
||||
return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
|
||||
}
|
||||
|
||||
RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
|
||||
clear();
|
||||
}
|
||||
|
@ -365,14 +477,29 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
scene_state.ubo.viewport_size[1] = vp_he.y;
|
||||
scene_state.ubo.directional_light_count = 0;
|
||||
|
||||
Size2i screen_size;
|
||||
RID opaque_framebuffer;
|
||||
RID alpha_framebuffer;
|
||||
bool reverse_cull = false;
|
||||
// We can only use our full subpass approach if we're:
|
||||
// - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
|
||||
// - not using ssr/sss (currently not supported)
|
||||
// - not using glow or other post effects (can't do 4th subpass)
|
||||
// - rendering to a half sized render buffer (can't do 4th subpass)
|
||||
// We'll need to restrict how far we're going with subpasses based on this.
|
||||
|
||||
// I don't think we support either of these in our mobile renderer so probably should phase them out
|
||||
bool using_ssr = false;
|
||||
bool using_sss = false;
|
||||
Size2i screen_size;
|
||||
RID framebuffer;
|
||||
bool reverse_cull = false;
|
||||
bool using_subpass_transparent = true;
|
||||
bool using_subpass_post_process = true;
|
||||
|
||||
bool is_half_resolution = false; // Set this once we support this feature.
|
||||
bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out
|
||||
bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out
|
||||
|
||||
// fill our render lists early so we can find out if we use various features
|
||||
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
|
||||
render_list[RENDER_LIST_OPAQUE].sort_by_key();
|
||||
render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
|
||||
_fill_element_info(RENDER_LIST_OPAQUE);
|
||||
_fill_element_info(RENDER_LIST_ALPHA);
|
||||
|
||||
if (p_render_data->render_info) {
|
||||
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_render_data->instances->size();
|
||||
|
@ -384,15 +511,36 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
screen_size.x = render_buffer->width;
|
||||
screen_size.y = render_buffer->height;
|
||||
|
||||
opaque_framebuffer = render_buffer->color_fb;
|
||||
alpha_framebuffer = opaque_framebuffer;
|
||||
if (is_half_resolution) {
|
||||
// can't do blit subpass
|
||||
using_subpass_post_process = false;
|
||||
} else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
|
||||
// can't do blit subpass
|
||||
using_subpass_post_process = false;
|
||||
}
|
||||
|
||||
if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
|
||||
// can't use our last two subpasses
|
||||
using_subpass_transparent = false;
|
||||
using_subpass_post_process = false;
|
||||
}
|
||||
|
||||
if (using_subpass_post_process) {
|
||||
// all as subpasses
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
|
||||
} else if (using_subpass_transparent) {
|
||||
// our tonemap pass is separate
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
|
||||
} else {
|
||||
// only opaque and sky as subpasses
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
|
||||
}
|
||||
} else if (p_render_data->reflection_probe.is_valid()) {
|
||||
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
|
||||
screen_size.x = resolution;
|
||||
screen_size.y = resolution;
|
||||
|
||||
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
|
||||
alpha_framebuffer = opaque_framebuffer;
|
||||
framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
|
||||
|
||||
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
|
||||
p_render_data->environment = RID(); //no environment on interiors
|
||||
|
@ -400,6 +548,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
}
|
||||
|
||||
reverse_cull = true;
|
||||
using_subpass_transparent = true; // we ignore our screen/depth texture here
|
||||
using_subpass_post_process = false; // not applicable at all for reflection probes.
|
||||
} else {
|
||||
ERR_FAIL(); //bug?
|
||||
}
|
||||
|
@ -411,17 +561,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
|
||||
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
|
||||
|
||||
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
|
||||
render_list[RENDER_LIST_OPAQUE].sort_by_key();
|
||||
render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
|
||||
|
||||
// we no longer use this...
|
||||
_fill_instance_data(RENDER_LIST_OPAQUE);
|
||||
_fill_instance_data(RENDER_LIST_ALPHA);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
// note, no depth prepass here!
|
||||
RD::get_singleton()->draw_command_end_label(); // Render Setup
|
||||
|
||||
// setup environment
|
||||
RID radiance_texture;
|
||||
|
@ -496,97 +636,199 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
// do not try to draw sky if invalid
|
||||
draw_sky = false;
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
RD::get_singleton()->draw_command_end_label(); // Setup Sky
|
||||
}
|
||||
} else {
|
||||
clear_color = p_default_bg_color;
|
||||
}
|
||||
|
||||
// opaque pass
|
||||
|
||||
// !BAS! Look into this, seems most of the code in here related to clustered only, may want to move this code into ForwardClustered/RenderForwardMobile before calling it from here
|
||||
// does trigger shadow map rendering so kinda important
|
||||
_pre_opaque_render(p_render_data, false, false, RID(), RID());
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
|
||||
|
||||
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
|
||||
|
||||
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
|
||||
|
||||
RENDER_TIMESTAMP("Render Opaque Pass");
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true);
|
||||
|
||||
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
|
||||
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
|
||||
|
||||
{
|
||||
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
|
||||
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
|
||||
|
||||
// regular forward for now
|
||||
Vector<Color> c;
|
||||
c.push_back(clear_color.to_linear());
|
||||
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
|
||||
_render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
// update sky buffers (if required)
|
||||
if (draw_sky || draw_sky_fog_only) {
|
||||
RENDER_TIMESTAMP("Render Sky");
|
||||
// !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render
|
||||
// and change Forward Clustered in the same way as we have here (but without using subpasses)
|
||||
RENDER_TIMESTAMP("Setup Sky resolution buffers");
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Draw Sky");
|
||||
RD::get_singleton()->draw_command_begin_label("Setup Sky resolution buffers");
|
||||
|
||||
if (p_render_data->reflection_probe.is_valid()) {
|
||||
CameraMatrix correction;
|
||||
correction.set_depth_correction(true);
|
||||
CameraMatrix projection = correction * p_render_data->cam_projection;
|
||||
sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
|
||||
sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time);
|
||||
} else {
|
||||
sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
|
||||
sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
|
||||
}
|
||||
|
||||
if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
|
||||
/*
|
||||
if (using_separate_specular) {
|
||||
RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
|
||||
}
|
||||
|
||||
// transparent pass
|
||||
RENDER_TIMESTAMP("Render Transparent Pass");
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
|
||||
|
||||
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
|
||||
|
||||
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
|
||||
_pre_opaque_render(p_render_data, false, false, RID(), RID());
|
||||
|
||||
{
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
|
||||
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
|
||||
if (render_buffer) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
|
||||
} else {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
|
||||
}
|
||||
|
||||
// opaque pass
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Opaque Subpass");
|
||||
|
||||
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
|
||||
|
||||
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
|
||||
|
||||
RENDER_TIMESTAMP("Render Opaque Subpass");
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true);
|
||||
|
||||
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
|
||||
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
|
||||
|
||||
{
|
||||
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
|
||||
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
|
||||
|
||||
// regular forward for now
|
||||
Vector<Color> c;
|
||||
c.push_back(clear_color.to_linear()); // our render buffer
|
||||
if (render_buffer) {
|
||||
if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
c.push_back(clear_color.to_linear()); // our resolve buffer
|
||||
}
|
||||
if (using_subpass_post_process) {
|
||||
c.push_back(Color()); // our 2D buffer we're copying into
|
||||
}
|
||||
}
|
||||
|
||||
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
|
||||
render_list_params.framebuffer_format = fb_format;
|
||||
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
|
||||
// secondary command buffers need more testing at this time
|
||||
//multi threaded
|
||||
thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
|
||||
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
|
||||
} else {
|
||||
//single threaded
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
_render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
|
||||
}
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); //Render Opaque Subpass
|
||||
|
||||
if (draw_sky || draw_sky_fog_only) {
|
||||
RENDER_TIMESTAMP("Render Sky Subpass");
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Draw Sky Subpass");
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
|
||||
|
||||
if (p_render_data->reflection_probe.is_valid()) {
|
||||
CameraMatrix correction;
|
||||
correction.set_depth_correction(true);
|
||||
CameraMatrix projection = correction * p_render_data->cam_projection;
|
||||
sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time);
|
||||
} else {
|
||||
sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
|
||||
|
||||
// note, if MSAA is used in 2-subpass approach we should get an automatic resolve here
|
||||
} else {
|
||||
// switch to subpass but we do nothing here so basically we skip (though this should trigger resolve with 2-subpass MSAA).
|
||||
RD::get_singleton()->draw_list_switch_to_next_pass();
|
||||
}
|
||||
|
||||
if (!using_subpass_transparent) {
|
||||
// We're done with our subpasses so end our container pass
|
||||
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
|
||||
}
|
||||
|
||||
// transparent pass
|
||||
RENDER_TIMESTAMP("Render Transparent Subpass");
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Transparent Subpass");
|
||||
|
||||
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
|
||||
|
||||
if (using_subpass_transparent) {
|
||||
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
|
||||
render_list_params.framebuffer_format = fb_format;
|
||||
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
|
||||
// secondary command buffers need more testing at this time
|
||||
//multi threaded
|
||||
thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
|
||||
RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr());
|
||||
render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
|
||||
RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
|
||||
} else {
|
||||
//single threaded
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
|
||||
render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
|
||||
_render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
|
||||
|
||||
// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
|
||||
|
||||
// blit to tonemap
|
||||
if (render_buffer && using_subpass_post_process) {
|
||||
_post_process_subpass(render_buffer->color, framebuffer, p_render_data);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
|
||||
|
||||
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
|
||||
} else {
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
|
||||
|
||||
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
|
||||
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
|
||||
|
||||
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
|
||||
render_list_params.framebuffer_format = fb_format;
|
||||
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
|
||||
// secondary command buffers need more testing at this time
|
||||
//multi threaded
|
||||
thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
|
||||
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
|
||||
RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
|
||||
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
|
||||
} else {
|
||||
//single threaded
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
|
||||
_render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
|
||||
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
|
||||
}
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
if (render_buffer && !using_subpass_post_process) {
|
||||
RD::get_singleton()->draw_command_begin_label("Post process pass");
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Resolve");
|
||||
// If we need extra effects we do this in its own pass
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
||||
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
|
||||
_render_buffers_post_process_and_tonemap(p_render_data);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Post process pass
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
if (render_buffer) {
|
||||
_disable_clear_request(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
|
||||
|
@ -635,7 +877,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
|
|||
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, true);
|
||||
uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from;
|
||||
render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size);
|
||||
_fill_instance_data(RENDER_LIST_SECONDARY, render_list_from, render_list_size, false);
|
||||
_fill_element_info(RENDER_LIST_SECONDARY, render_list_from, render_list_size);
|
||||
|
||||
{
|
||||
//regular forward for now
|
||||
|
@ -713,7 +955,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
|
|||
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
|
||||
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
|
||||
render_list[RENDER_LIST_SECONDARY].sort_by_key();
|
||||
_fill_instance_data(RENDER_LIST_SECONDARY);
|
||||
_fill_element_info(RENDER_LIST_SECONDARY);
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
|
||||
|
||||
|
@ -754,7 +996,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
|
|||
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
|
||||
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
|
||||
render_list[RENDER_LIST_SECONDARY].sort_by_key();
|
||||
_fill_instance_data(RENDER_LIST_SECONDARY);
|
||||
_fill_element_info(RENDER_LIST_SECONDARY);
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
|
||||
|
||||
|
@ -827,7 +1069,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
|
|||
|
||||
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
|
||||
render_list[RENDER_LIST_SECONDARY].sort_by_key();
|
||||
_fill_instance_data(RENDER_LIST_SECONDARY);
|
||||
_fill_element_info(RENDER_LIST_SECONDARY);
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
|
||||
|
||||
|
@ -1413,9 +1655,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
|
|||
RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
|
||||
}
|
||||
|
||||
void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) {
|
||||
// !BAS! Rename this to make clear this is not the same as with the forward renderer and remove p_update_buffer?
|
||||
|
||||
void RenderForwardMobile::_fill_element_info(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements) {
|
||||
RenderList *rl = &render_list[p_render_list];
|
||||
uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size();
|
||||
|
||||
|
@ -1669,7 +1909,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
|||
prev_index_array_rd = index_array_rd;
|
||||
}
|
||||
|
||||
RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
|
||||
RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass);
|
||||
|
||||
if (pipeline_rd != prev_pipeline_rd) {
|
||||
// checking with prev shader does not make so much sense, as
|
||||
|
|
|
@ -92,6 +92,18 @@ protected:
|
|||
|
||||
/* Render Buffer */
|
||||
|
||||
// We can have:
|
||||
// - 4 subpasses combining the full render cycle
|
||||
// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
enum RenderBufferMobileFramebufferConfigType {
|
||||
FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
|
||||
FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
|
||||
FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
|
||||
FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
|
||||
FB_CONFIG_MAX
|
||||
};
|
||||
|
||||
struct RenderBufferDataForwardMobile : public RenderBufferData {
|
||||
RID color;
|
||||
RID depth;
|
||||
|
@ -104,12 +116,12 @@ protected:
|
|||
RID depth_msaa;
|
||||
// RID normal_roughness_buffer_msaa;
|
||||
|
||||
RID color_fb;
|
||||
RID color_fbs[FB_CONFIG_MAX];
|
||||
int width, height;
|
||||
uint32_t view_count;
|
||||
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
|
||||
|
||||
~RenderBufferDataForwardMobile();
|
||||
};
|
||||
|
@ -152,6 +164,7 @@ protected:
|
|||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
uint32_t barrier = RD::BARRIER_MASK_ALL;
|
||||
uint32_t subpass = 0;
|
||||
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
|
||||
elements = p_elements;
|
||||
|
@ -195,7 +208,7 @@ protected:
|
|||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
|
||||
|
||||
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
|
||||
void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
|
||||
void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);
|
||||
// void _update_instance_data_buffer(RenderListType p_render_list);
|
||||
|
||||
static RenderForwardMobile *singleton;
|
||||
|
@ -576,6 +589,8 @@ protected:
|
|||
void _update_shader_quality_settings() override;
|
||||
|
||||
public:
|
||||
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
|
||||
|
||||
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
|
||||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
|
||||
|
||||
|
|
|
@ -679,10 +679,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
|
|||
for (int i = 0; i < atlas->count; i++) {
|
||||
atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
|
||||
fb.push_back(atlas->depth_buffer);
|
||||
atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
|
||||
atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,6 +725,13 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
|
|||
return true;
|
||||
}
|
||||
|
||||
RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_color);
|
||||
fb.push_back(p_depth);
|
||||
return RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
|
||||
bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
@ -1996,6 +2000,75 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
storage->render_target_disable_clear_request(rb->render_target);
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
|
||||
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment);
|
||||
|
||||
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
|
||||
|
||||
EffectsRD::TonemapSettings tonemap;
|
||||
|
||||
if (env) {
|
||||
tonemap.tonemap_mode = env->tone_mapper;
|
||||
tonemap.exposure = env->exposure;
|
||||
tonemap.white = env->white;
|
||||
}
|
||||
|
||||
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
|
||||
// The problem is that we need to use the result so far and process them before we can
|
||||
// apply this to our results.
|
||||
if (can_use_effects && env && env->glow_enabled) {
|
||||
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
|
||||
}
|
||||
if (can_use_effects && env && env->auto_exposure) {
|
||||
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
|
||||
}
|
||||
|
||||
tonemap.use_glow = false;
|
||||
tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
|
||||
tonemap.use_auto_exposure = false;
|
||||
tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
|
||||
|
||||
tonemap.use_color_correction = false;
|
||||
tonemap.use_1d_color_correction = false;
|
||||
tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
|
||||
|
||||
if (can_use_effects && env) {
|
||||
tonemap.use_bcs = env->adjustments_enabled;
|
||||
tonemap.brightness = env->adjustments_brightness;
|
||||
tonemap.contrast = env->adjustments_contrast;
|
||||
tonemap.saturation = env->adjustments_saturation;
|
||||
if (env->adjustments_enabled && env->color_correction.is_valid()) {
|
||||
tonemap.use_color_correction = true;
|
||||
tonemap.use_1d_color_correction = env->use_1d_color_correction;
|
||||
tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction);
|
||||
}
|
||||
}
|
||||
|
||||
tonemap.use_debanding = rb->use_debanding;
|
||||
tonemap.texture_size = Vector2i(rb->width, rb->height);
|
||||
|
||||
tonemap.view_count = p_render_data->view_count;
|
||||
|
||||
storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) {
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
storage->render_target_disable_clear_request(rb->render_target);
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
|
||||
EffectsRD *effects = storage->get_effects();
|
||||
|
||||
|
@ -2283,12 +2356,11 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
|||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.array_layers = rb->view_count; // create a layer for every view
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
|
||||
} else {
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
}
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
|
||||
|
||||
rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
}
|
||||
|
@ -2326,7 +2398,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
|||
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
|
||||
}
|
||||
|
||||
rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
|
||||
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
|
||||
rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count);
|
||||
|
||||
if (is_clustered_enabled()) {
|
||||
rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
|
||||
|
@ -3846,9 +3919,28 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
|
|||
_render_scene(&render_data, clear_color);
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
|
||||
/*
|
||||
_debug_draw_cluster(p_render_buffers);
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
||||
_render_buffers_post_process_and_tonemap(&render_data);
|
||||
*/
|
||||
|
||||
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
|
||||
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
|
||||
rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
|
||||
if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) {
|
||||
RS::ViewportDebugDraw dd = get_debug_draw_mode();
|
||||
|
||||
if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
|
||||
ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX;
|
||||
switch (debug_draw) {
|
||||
switch (dd) {
|
||||
case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS:
|
||||
elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT;
|
||||
break;
|
||||
|
@ -3864,17 +3956,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
|
|||
default: {
|
||||
}
|
||||
}
|
||||
if (current_cluster_builder != nullptr) {
|
||||
current_cluster_builder->debug(elem_type);
|
||||
}
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
||||
_render_buffers_post_process_and_tonemap(&render_data);
|
||||
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
|
||||
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
|
||||
rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
|
||||
current_cluster_builder->debug(elem_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ protected:
|
|||
double time_step = 0;
|
||||
|
||||
struct RenderBufferData {
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
|
||||
virtual ~RenderBufferData() {}
|
||||
};
|
||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||
|
@ -117,6 +117,7 @@ protected:
|
|||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
|
||||
|
||||
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
|
||||
void _debug_draw_cluster(RID p_render_buffers);
|
||||
|
||||
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
|
||||
|
||||
|
@ -133,6 +134,10 @@ protected:
|
|||
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
|
||||
|
||||
void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
|
||||
void _post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data);
|
||||
void _disable_clear_request(const RenderDataRD *p_render_data);
|
||||
|
||||
// needed for a single argument calls (material and uv2)
|
||||
PagedArrayPool<GeometryInstance *> cull_argument_pool;
|
||||
PagedArray<GeometryInstance *> cull_argument; //need this to exist
|
||||
|
@ -146,7 +151,7 @@ protected:
|
|||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//used for mobile renderer mostly
|
||||
|
||||
|
@ -524,7 +529,6 @@ private:
|
|||
void _allocate_luminance_textures(RenderBuffers *rb);
|
||||
|
||||
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
|
||||
void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
|
||||
|
||||
/* Cluster */
|
||||
|
||||
|
@ -923,6 +927,12 @@ public:
|
|||
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
|
||||
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
|
||||
|
||||
bool camera_effects_uses_dof(RID p_camera_effects) {
|
||||
CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
|
||||
|
||||
return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
|
||||
}
|
||||
|
||||
virtual RID light_instance_create(RID p_light) override;
|
||||
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
|
||||
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
|
||||
|
@ -1065,6 +1075,7 @@ public:
|
|||
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
|
||||
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
|
||||
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
|
||||
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth);
|
||||
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
|
||||
|
||||
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
|
||||
|
|
|
@ -283,7 +283,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
|
|||
|
||||
RD::DrawListID draw_list = p_list;
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format, false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
|
||||
if (p_uniform_set.is_valid()) { //material may not have uniform set
|
||||
|
@ -1467,6 +1467,179 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
|
|||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
|
||||
ERR_FAIL_COND(!p_env);
|
||||
|
||||
ERR_FAIL_COND(p_view_count == 0);
|
||||
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
|
||||
|
||||
Sky *sky = get_sky(p_env->sky);
|
||||
ERR_FAIL_COND(!sky);
|
||||
|
||||
SkyMaterialData *material = nullptr;
|
||||
RID sky_material;
|
||||
|
||||
RS::EnvironmentBG background = p_env->background;
|
||||
|
||||
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
|
||||
ERR_FAIL_COND(!sky);
|
||||
sky_material = sky_get_material(p_env->sky);
|
||||
|
||||
if (sky_material.is_valid()) {
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
if (!material || !material->shader_data->valid) {
|
||||
material = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!material) {
|
||||
sky_material = sky_shader.default_material;
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
}
|
||||
}
|
||||
|
||||
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
|
||||
sky_material = sky_scene_state.fog_material;
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(!material);
|
||||
|
||||
SkyShaderData *shader_data = material->shader_data;
|
||||
|
||||
ERR_FAIL_COND(!shader_data);
|
||||
|
||||
Basis sky_transform = p_env->sky_orientation;
|
||||
sky_transform.invert();
|
||||
|
||||
float multiplier = p_env->bg_energy;
|
||||
float custom_fov = p_env->sky_custom_fov;
|
||||
|
||||
// Camera
|
||||
CameraMatrix camera;
|
||||
uint32_t view_count = p_view_count;
|
||||
const CameraMatrix *projections = p_projections;
|
||||
|
||||
if (custom_fov) {
|
||||
// With custom fov we don't support stereo...
|
||||
float near_plane = p_projections[0].get_z_near();
|
||||
float far_plane = p_projections[0].get_z_far();
|
||||
float aspect = p_projections[0].get_aspect();
|
||||
|
||||
camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
|
||||
|
||||
view_count = 1;
|
||||
projections = &camera;
|
||||
}
|
||||
|
||||
sky_transform = p_transform.basis * sky_transform;
|
||||
|
||||
if (shader_data->uses_quarter_res) {
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
|
||||
|
||||
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
clear_colors.push_back(Color(0.0, 0.0, 0.0));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
|
||||
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
if (shader_data->uses_half_res) {
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
|
||||
|
||||
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
clear_colors.push_back(Color(0.0, 0.0, 0.0));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
|
||||
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
|
||||
ERR_FAIL_COND(!p_env);
|
||||
|
||||
ERR_FAIL_COND(p_view_count == 0);
|
||||
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
|
||||
|
||||
Sky *sky = get_sky(p_env->sky);
|
||||
ERR_FAIL_COND(!sky);
|
||||
|
||||
SkyMaterialData *material = nullptr;
|
||||
RID sky_material;
|
||||
|
||||
RS::EnvironmentBG background = p_env->background;
|
||||
|
||||
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
|
||||
ERR_FAIL_COND(!sky);
|
||||
sky_material = sky_get_material(p_env->sky);
|
||||
|
||||
if (sky_material.is_valid()) {
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
if (!material || !material->shader_data->valid) {
|
||||
material = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!material) {
|
||||
sky_material = sky_shader.default_material;
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
}
|
||||
}
|
||||
|
||||
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
|
||||
sky_material = sky_scene_state.fog_material;
|
||||
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(!material);
|
||||
|
||||
SkyShaderData *shader_data = material->shader_data;
|
||||
|
||||
ERR_FAIL_COND(!shader_data);
|
||||
|
||||
Basis sky_transform = p_env->sky_orientation;
|
||||
sky_transform.invert();
|
||||
|
||||
float multiplier = p_env->bg_energy;
|
||||
float custom_fov = p_env->sky_custom_fov;
|
||||
|
||||
// Camera
|
||||
CameraMatrix camera;
|
||||
uint32_t view_count = p_view_count;
|
||||
const CameraMatrix *projections = p_projections;
|
||||
|
||||
if (custom_fov) {
|
||||
// With custom fov we don't support stereo...
|
||||
float near_plane = p_projections[0].get_z_near();
|
||||
float far_plane = p_projections[0].get_z_far();
|
||||
float aspect = p_projections[0].get_aspect();
|
||||
|
||||
camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
|
||||
|
||||
view_count = 1;
|
||||
projections = &camera;
|
||||
}
|
||||
|
||||
sky_transform = p_transform.basis * sky_transform;
|
||||
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
|
||||
|
||||
RID texture_uniform_set;
|
||||
if (sky) {
|
||||
texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
|
||||
} else {
|
||||
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
|
||||
}
|
||||
|
||||
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
|
||||
if (!p_sky->dirty) {
|
||||
p_sky->dirty = true;
|
||||
|
|
|
@ -295,6 +295,8 @@ public:
|
|||
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
|
||||
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
|
||||
void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
|
||||
void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
|
||||
void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
|
||||
|
||||
void invalidate_sky(Sky *p_sky);
|
||||
void update_dirty_skys();
|
||||
|
|
|
@ -35,11 +35,15 @@ void main() {
|
|||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
|
||||
#ifdef MULTIVIEW
|
||||
#ifdef SUBPASS
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput input_color;
|
||||
#else
|
||||
#if MULTIVIEW
|
||||
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
|
||||
#else
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
#endif
|
||||
#endif
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_glow;
|
||||
#ifdef USE_1D_LUT
|
||||
|
@ -291,6 +295,7 @@ vec3 apply_color_correction(vec3 color) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SUBPASS
|
||||
vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
|
||||
const float FXAA_REDUCE_MIN = (1.0 / 128.0);
|
||||
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
|
||||
|
@ -346,6 +351,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
|
|||
return rgbB;
|
||||
}
|
||||
}
|
||||
#endif // !SUBPASS
|
||||
|
||||
// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
|
||||
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
|
||||
|
@ -360,7 +366,10 @@ vec3 screen_space_dither(vec2 frag_coord) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
#ifdef MULTIVIEW
|
||||
#ifdef SUBPASS
|
||||
// SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
|
||||
vec3 color = subpassLoad(input_color).rgb;
|
||||
#elif MULTIVIEW
|
||||
vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
|
||||
#else
|
||||
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
|
||||
|
@ -370,14 +379,16 @@ void main() {
|
|||
|
||||
float exposure = params.exposure;
|
||||
|
||||
#ifndef SUBPASS
|
||||
if (params.use_auto_exposure) {
|
||||
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
|
||||
}
|
||||
#endif
|
||||
|
||||
color *= exposure;
|
||||
|
||||
// Early Tonemap & SRGB Conversion
|
||||
|
||||
#ifndef SUBPASS
|
||||
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
|
||||
vec3 glow = gather_glow(source_glow, uv_interp);
|
||||
color.rgb = mix(color.rgb, glow, params.glow_intensity);
|
||||
|
@ -386,15 +397,19 @@ void main() {
|
|||
if (params.use_fxaa) {
|
||||
color = do_fxaa(color, exposure, uv_interp);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (params.use_debanding) {
|
||||
// For best results, debanding should be done before tonemapping.
|
||||
// Otherwise, we're adding noise to an already-quantized image.
|
||||
color += screen_space_dither(gl_FragCoord.xy);
|
||||
}
|
||||
|
||||
color = apply_tonemapping(color, params.white);
|
||||
|
||||
color = linear_to_srgb(color); // regular linear -> SRGB conversion
|
||||
|
||||
#ifndef SUBPASS
|
||||
// Glow
|
||||
|
||||
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
|
||||
|
@ -406,6 +421,7 @@ void main() {
|
|||
|
||||
color = apply_glow(color, glow);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Additional effects
|
||||
|
||||
|
|
|
@ -739,7 +739,7 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_UPDATE_BIT);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_TO_BIT);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT);
|
||||
|
||||
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO);
|
||||
|
|
|
@ -422,7 +422,7 @@ public:
|
|||
TEXTURE_USAGE_CAN_UPDATE_BIT = (1 << 6),
|
||||
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
|
||||
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
|
||||
TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 9),
|
||||
TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
|
||||
};
|
||||
|
||||
enum TextureSwizzle {
|
||||
|
@ -1065,6 +1065,7 @@ public:
|
|||
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0;
|
||||
virtual void draw_list_disable_scissor(DrawListID p_list) = 0;
|
||||
|
||||
virtual uint32_t draw_list_get_current_pass() = 0;
|
||||
virtual DrawListID draw_list_switch_to_next_pass() = 0;
|
||||
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue