Addition of SDFGI for open world global illumination
Move GI to a deferred pass
This commit is contained in:
parent
b92477d77e
commit
201d606b3d
18
.travis.yml
18
.travis.yml
|
@ -100,15 +100,15 @@ matrix:
|
|||
packages:
|
||||
- *linux_deps
|
||||
|
||||
- name: Javascript export template (release, emscripten latest)
|
||||
stage: build
|
||||
env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes"
|
||||
os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *linux_deps
|
||||
# - name: Javascript export template (release, emscripten latest)
|
||||
# stage: build
|
||||
# env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes"
|
||||
# os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - *linux_deps
|
||||
|
||||
before_install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
|
|
|
@ -45,6 +45,14 @@ private:
|
|||
T *data = nullptr;
|
||||
|
||||
public:
|
||||
T *ptr() {
|
||||
return data;
|
||||
}
|
||||
|
||||
const T *ptr() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void push_back(T p_elem) {
|
||||
if (unlikely(count == capacity)) {
|
||||
if (capacity == 0) {
|
||||
|
|
|
@ -773,7 +773,7 @@ Basis::operator String() const {
|
|||
mtx += ", ";
|
||||
}
|
||||
|
||||
mtx += rtos(elements[i][j]);
|
||||
mtx += rtos(elements[j][i]); //matrix is stored transposed for performance, so print it transposed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -993,6 +993,8 @@ Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Ve
|
|||
}
|
||||
}
|
||||
|
||||
memdelete_arr(work_memory);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -945,6 +945,16 @@ public:
|
|||
return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
|
||||
#undef STP
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ static Vector3 octahedron_map_decode(const Vector2 &p_uv) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
Vector2 f = p_uv * 2.0 - Vector2(1.0, 1.0);
|
||||
Vector3 n = Vector3(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y));
|
||||
float t = CLAMP(-n.z, 0.0, 1.0);
|
||||
n.x += n.x >= 0 ? -t : t;
|
||||
n.y += n.y >= 0 ? -t : t;
|
||||
return n.normalized();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GEOMETRY_3D_H
|
||||
|
|
|
@ -1786,6 +1786,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
|
|||
if (r_valid) {
|
||||
*r_valid = true;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VECTOR2: {
|
||||
const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "thirdparty/spirv-reflect/spirv_reflect.h"
|
||||
|
||||
//#define FORCE_FULL_BARRIER
|
||||
#define FORCE_FULL_BARRIER
|
||||
|
||||
void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) {
|
||||
if (!dependency_map.has(p_depends_on)) {
|
||||
|
@ -3203,6 +3203,63 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
|
|||
return id;
|
||||
}
|
||||
|
||||
RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_empty(const Size2i &p_size) {
|
||||
ERR_FAIL_COND_V(p_size.width <= 0 || p_size.height <= 0, INVALID_FORMAT_ID);
|
||||
|
||||
FramebufferFormatKey key;
|
||||
key.empty_size = p_size;
|
||||
|
||||
const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
|
||||
if (E) {
|
||||
//exists, return
|
||||
return E->get();
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass;
|
||||
subpass.flags = 0;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.inputAttachmentCount = 0; //unsupported for now
|
||||
subpass.pInputAttachments = nullptr;
|
||||
subpass.colorAttachmentCount = 0;
|
||||
subpass.pColorAttachments = nullptr;
|
||||
subpass.pDepthStencilAttachment = nullptr;
|
||||
subpass.pResolveAttachments = nullptr;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = nullptr;
|
||||
|
||||
VkRenderPassCreateInfo render_pass_create_info;
|
||||
render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
render_pass_create_info.pNext = nullptr;
|
||||
render_pass_create_info.flags = 0;
|
||||
render_pass_create_info.attachmentCount = 0;
|
||||
render_pass_create_info.pAttachments = nullptr;
|
||||
render_pass_create_info.subpassCount = 1;
|
||||
render_pass_create_info.pSubpasses = &subpass;
|
||||
render_pass_create_info.dependencyCount = 0;
|
||||
render_pass_create_info.pDependencies = nullptr;
|
||||
|
||||
VkRenderPass render_pass;
|
||||
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass for empty fb failed with error " + itos(res) + ".");
|
||||
|
||||
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
|
||||
return INVALID_ID;
|
||||
}
|
||||
|
||||
FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT));
|
||||
|
||||
E = framebuffer_format_cache.insert(key, id);
|
||||
|
||||
FramebufferFormat fb_format;
|
||||
fb_format.E = E;
|
||||
fb_format.color_attachments = 0;
|
||||
fb_format.render_pass = render_pass;
|
||||
fb_format.samples = TEXTURE_SAMPLES_1;
|
||||
framebuffer_formats[id] = fb_format;
|
||||
return id;
|
||||
}
|
||||
|
||||
RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_texture_samples(FramebufferFormatID p_format) {
|
||||
Map<FramebufferFormatID, FramebufferFormat>::Element *E = framebuffer_formats.find(p_format);
|
||||
ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1);
|
||||
|
@ -3214,6 +3271,16 @@ RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_te
|
|||
/**** RENDER TARGET ****/
|
||||
/***********************/
|
||||
|
||||
RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
Framebuffer framebuffer;
|
||||
framebuffer.format_id = framebuffer_format_create_empty(p_size);
|
||||
ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID());
|
||||
framebuffer.size = p_size;
|
||||
|
||||
return framebuffer_owner.make_rid(framebuffer);
|
||||
}
|
||||
|
||||
RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -4205,13 +4272,18 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve
|
|||
return uniform_buffer_owner.make_rid(buffer);
|
||||
}
|
||||
|
||||
RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data) {
|
||||
RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
|
||||
|
||||
Buffer buffer;
|
||||
Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
buffer.usage = p_usage;
|
||||
uint32_t flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
if (p_usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT) {
|
||||
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
|
||||
}
|
||||
Error err = _buffer_allocate(&buffer, p_size_bytes, flags, VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
ERR_FAIL_COND_V(err != OK, RID());
|
||||
|
||||
if (p_data.size()) {
|
||||
|
@ -4420,7 +4492,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
|
|||
}
|
||||
}
|
||||
ERR_FAIL_COND_V_MSG(uniform_idx == -1, RID(),
|
||||
"All the shader bindings for the given set must be covered by the uniforms provided.");
|
||||
"All the shader bindings for the given set must be covered by the uniforms provided. Binding (" + itos(set_uniform.binding) + ") was not provided.");
|
||||
|
||||
const Uniform &uniform = uniforms[uniform_idx];
|
||||
|
||||
|
@ -5475,7 +5547,7 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents) {
|
||||
Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures) {
|
||||
VkRenderPassBeginInfo render_pass_begin;
|
||||
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
render_pass_begin.pNext = nullptr;
|
||||
|
@ -5520,6 +5592,37 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
|
|||
render_pass_begin.clearValueCount = clear_values.size();
|
||||
render_pass_begin.pClearValues = clear_values.ptr();
|
||||
|
||||
for (int i = 0; i < p_storage_textures.size(); i++) {
|
||||
Texture *texture = texture_owner.getornull(p_storage_textures[i]);
|
||||
ERR_CONTINUE_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), "Supplied storage texture " + itos(i) + " for draw list ist not set to be used for storage.");
|
||||
|
||||
if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
|
||||
//must change layout to general
|
||||
VkImageMemoryBarrier image_memory_barrier;
|
||||
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_memory_barrier.pNext = nullptr;
|
||||
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||
image_memory_barrier.oldLayout = texture->layout;
|
||||
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = texture->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = texture->read_aspect_mask;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = texture->base_mipmap;
|
||||
image_memory_barrier.subresourceRange.levelCount = texture->mipmaps;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer;
|
||||
image_memory_barrier.subresourceRange.layerCount = texture->layers;
|
||||
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
|
||||
texture->layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
draw_list_storage_textures.push_back(p_storage_textures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, subpass_contents);
|
||||
|
||||
//mark textures as bound
|
||||
|
@ -5576,7 +5679,7 @@ void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list,
|
|||
vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr);
|
||||
}
|
||||
|
||||
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
|
||||
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
|
||||
|
@ -5626,7 +5729,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
|
|||
ERR_FAIL_COND_V(err != OK, INVALID_ID);
|
||||
|
||||
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
|
||||
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE);
|
||||
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE, p_storage_textures);
|
||||
|
||||
if (err != OK) {
|
||||
return INVALID_ID;
|
||||
|
@ -5666,7 +5769,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
|
|||
return ID_TYPE_DRAW_LIST;
|
||||
}
|
||||
|
||||
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
|
||||
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
ERR_FAIL_COND_V(p_splits < 1, ERR_INVALID_DECLARATION);
|
||||
|
@ -5748,7 +5851,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
|
|||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||
|
||||
VkCommandBuffer frame_command_buffer = frames[frame].draw_command_buffer;
|
||||
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
|
||||
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, p_storage_textures);
|
||||
|
||||
if (err != OK) {
|
||||
return ERR_CANT_CREATE;
|
||||
|
@ -6229,6 +6332,33 @@ void RenderingDeviceVulkan::draw_list_end() {
|
|||
|
||||
draw_list_bound_textures.clear();
|
||||
|
||||
for (int i = 0; i < draw_list_storage_textures.size(); i++) {
|
||||
Texture *texture = texture_owner.getornull(draw_list_storage_textures[i]);
|
||||
|
||||
VkImageMemoryBarrier image_memory_barrier;
|
||||
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_memory_barrier.pNext = nullptr;
|
||||
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
image_memory_barrier.oldLayout = texture->layout;
|
||||
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = texture->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = texture->read_aspect_mask;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = texture->base_mipmap;
|
||||
image_memory_barrier.subresourceRange.levelCount = texture->mipmaps;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer;
|
||||
image_memory_barrier.subresourceRange.layerCount = texture->layers;
|
||||
|
||||
vkCmdPipelineBarrier(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
|
||||
texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
draw_list_storage_textures.clear();
|
||||
|
||||
// To ensure proper synchronization, we must make sure rendering is done before:
|
||||
// * Some buffer is copied
|
||||
// * Another render pass happens (since we may be done
|
||||
|
@ -6495,6 +6625,62 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
|
|||
vkCmdDispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups);
|
||||
}
|
||||
|
||||
void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) {
|
||||
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
|
||||
ERR_FAIL_COND(!compute_list);
|
||||
|
||||
ComputeList *cl = compute_list;
|
||||
Buffer *buffer = storage_buffer_owner.getornull(p_buffer);
|
||||
ERR_FAIL_COND(!buffer);
|
||||
|
||||
ERR_FAIL_COND_MSG(!(buffer->usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT), "Buffer provided was not created to do indirect dispatch.");
|
||||
|
||||
ERR_FAIL_COND_MSG(p_offset + 12 > buffer->size, "Offset provided (+12) is past the end of buffer.");
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified.");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
|
||||
|
||||
if (cl->validation.pipeline_push_constant_size > 0) {
|
||||
//using push constants, check that they were supplied
|
||||
ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
|
||||
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//Bind descriptor sets
|
||||
|
||||
for (uint32_t i = 0; i < cl->state.set_count; i++) {
|
||||
if (cl->state.sets[i].pipeline_expected_format == 0) {
|
||||
continue; //nothing expected by this pipeline
|
||||
}
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) {
|
||||
if (cl->state.sets[i].uniform_set_format == 0) {
|
||||
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline");
|
||||
} else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) {
|
||||
UniformSet *us = uniform_set_owner.getornull(cl->state.sets[i].uniform_set);
|
||||
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader));
|
||||
} else {
|
||||
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!cl->state.sets[i].bound) {
|
||||
//All good, see if this requires re-binding
|
||||
vkCmdBindDescriptorSets(cl->command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, cl->state.pipeline_layout, i, 1, &cl->state.sets[i].descriptor_set, 0, nullptr);
|
||||
cl->state.sets[i].bound = true;
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdDispatchIndirect(cl->command_buffer, buffer->buffer, p_offset);
|
||||
}
|
||||
|
||||
void RenderingDeviceVulkan::compute_list_add_barrier(ComputeListID p_list) {
|
||||
#ifdef FORCE_FULL_BARRIER
|
||||
_full_barrier(true);
|
||||
|
@ -6534,10 +6720,17 @@ void RenderingDeviceVulkan::compute_list_end() {
|
|||
#ifdef FORCE_FULL_BARRIER
|
||||
_full_barrier(true);
|
||||
#else
|
||||
_memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, true);
|
||||
_memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderingDeviceVulkan::full_barrier() {
|
||||
#ifndef DEBUG_ENABLED
|
||||
ERR_PRINT("Full barrier is debug-only, should not be used in production");
|
||||
#endif
|
||||
_full_barrier(true);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_framebuffer, ID *p_draw_lists, uint32_t p_draw_list_count, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Variant> &p_clear_colors) {
|
||||
|
||||
|
|
|
@ -204,10 +204,17 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
|||
Error _insert_staging_block();
|
||||
|
||||
struct Buffer {
|
||||
uint32_t size = 0;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VmaAllocation allocation = nullptr;
|
||||
uint32_t size;
|
||||
uint32_t usage;
|
||||
VkBuffer buffer;
|
||||
VmaAllocation allocation;
|
||||
VkDescriptorBufferInfo buffer_info; //used for binding
|
||||
Buffer() {
|
||||
size = 0;
|
||||
usage = 0;
|
||||
buffer = VK_NULL_HANDLE;
|
||||
allocation = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
Error _buffer_allocate(Buffer *p_buffer, uint32_t p_size, uint32_t p_usage, VmaMemoryUsage p_mapping);
|
||||
|
@ -229,8 +236,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
|||
// used for the render pipelines.
|
||||
|
||||
struct FramebufferFormatKey {
|
||||
Size2i empty_size;
|
||||
Vector<AttachmentFormat> attachments;
|
||||
bool operator<(const FramebufferFormatKey &p_key) const {
|
||||
if (empty_size != p_key.empty_size) {
|
||||
return empty_size < p_key.empty_size;
|
||||
}
|
||||
|
||||
int as = attachments.size();
|
||||
int bs = p_key.attachments.size();
|
||||
if (as != bs) {
|
||||
|
@ -773,12 +785,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
|||
uint32_t draw_list_count;
|
||||
bool draw_list_split;
|
||||
Vector<RID> draw_list_bound_textures;
|
||||
Vector<RID> draw_list_storage_textures;
|
||||
bool draw_list_unbind_color_textures;
|
||||
bool draw_list_unbind_depth_textures;
|
||||
|
||||
void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
|
||||
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
|
||||
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents);
|
||||
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
|
||||
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
|
||||
|
||||
/**********************/
|
||||
|
@ -923,9 +936,11 @@ public:
|
|||
/*********************/
|
||||
|
||||
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format);
|
||||
virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size);
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format);
|
||||
|
||||
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID);
|
||||
virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID);
|
||||
|
||||
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
|
||||
|
||||
|
@ -961,7 +976,7 @@ public:
|
|||
/*****************/
|
||||
|
||||
virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>());
|
||||
virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>());
|
||||
virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0);
|
||||
virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>());
|
||||
|
||||
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
|
||||
|
@ -998,8 +1013,8 @@ public:
|
|||
|
||||
virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color());
|
||||
|
||||
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
|
||||
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
|
||||
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
|
||||
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
|
||||
|
||||
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline);
|
||||
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index);
|
||||
|
@ -1026,8 +1041,11 @@ public:
|
|||
virtual void compute_list_add_barrier(ComputeListID p_list);
|
||||
|
||||
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);
|
||||
virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset);
|
||||
virtual void compute_list_end();
|
||||
|
||||
virtual void full_barrier();
|
||||
|
||||
/**************/
|
||||
/**** FREE ****/
|
||||
/**************/
|
||||
|
|
|
@ -360,7 +360,7 @@ void EditorNode::_notification(int p_what) {
|
|||
bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter");
|
||||
RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
|
||||
RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
|
||||
RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve"));
|
||||
RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enable"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"));
|
||||
bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
|
||||
RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
|
||||
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
|
||||
|
@ -376,6 +376,12 @@ void EditorNode::_notification(int p_what) {
|
|||
RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
|
||||
float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed");
|
||||
RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);
|
||||
RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/sdfgi/frames_to_converge")));
|
||||
RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
|
||||
RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/sdfgi/probe_ray_count")));
|
||||
RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
|
||||
RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/quality/gi_probes/quality")));
|
||||
RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
|
||||
}
|
||||
|
||||
ResourceImporterTexture::get_singleton()->update_imports();
|
||||
|
|
|
@ -487,6 +487,10 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
|
|||
Vector3 pos = _get_ray_pos(p_pos);
|
||||
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
|
||||
|
||||
if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) {
|
||||
RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray);
|
||||
}
|
||||
|
||||
Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario());
|
||||
Set<Ref<EditorNode3DGizmo>> found_gizmos;
|
||||
|
||||
|
@ -2984,7 +2988,9 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
case VIEW_DISPLAY_DEBUG_SSAO:
|
||||
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS:
|
||||
case VIEW_DISPLAY_DEBUG_DECAL_ATLAS:
|
||||
case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: {
|
||||
case VIEW_DISPLAY_DEBUG_SDFGI:
|
||||
case VIEW_DISPLAY_DEBUG_SDFGI_PROBES:
|
||||
case VIEW_DISPLAY_DEBUG_GI_BUFFER: {
|
||||
static const int display_options[] = {
|
||||
VIEW_DISPLAY_NORMAL,
|
||||
VIEW_DISPLAY_WIREFRAME,
|
||||
|
@ -3000,9 +3006,11 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION,
|
||||
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
|
||||
VIEW_DISPLAY_DEBUG_SSAO,
|
||||
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
||||
VIEW_DISPLAY_DEBUG_GI_BUFFER,
|
||||
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
||||
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI_PROBES,
|
||||
VIEW_MAX
|
||||
};
|
||||
static const Viewport::DebugDraw debug_draw_modes[] = {
|
||||
|
@ -3020,9 +3028,11 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
Viewport::DEBUG_DRAW_GI_PROBE_EMISSION,
|
||||
Viewport::DEBUG_DRAW_SCENE_LUMINANCE,
|
||||
Viewport::DEBUG_DRAW_SSAO,
|
||||
Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||
Viewport::DEBUG_DRAW_GI_BUFFER,
|
||||
Viewport::DEBUG_DRAW_PSSM_SPLITS,
|
||||
Viewport::DEBUG_DRAW_DECAL_ATLAS,
|
||||
Viewport::DEBUG_DRAW_SDFGI,
|
||||
Viewport::DEBUG_DRAW_SDFGI_PROBES,
|
||||
};
|
||||
|
||||
int idx = 0;
|
||||
|
@ -3898,11 +3908,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
|
|||
display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO);
|
||||
display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI);
|
||||
display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("Roughness Limiter"), VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER);
|
||||
display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER);
|
||||
display_submenu->set_name("display_advanced");
|
||||
view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED);
|
||||
view_menu->get_popup()->add_separator();
|
||||
|
|
|
@ -214,9 +214,11 @@ class Node3DEditorViewport : public Control {
|
|||
VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION,
|
||||
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
|
||||
VIEW_DISPLAY_DEBUG_SSAO,
|
||||
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
||||
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
||||
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI_PROBES,
|
||||
VIEW_DISPLAY_DEBUG_GI_BUFFER,
|
||||
VIEW_LOCK_ROTATION,
|
||||
VIEW_CINEMATIC_PREVIEW,
|
||||
VIEW_AUTO_ORTHOGONAL,
|
||||
|
|
|
@ -894,13 +894,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d
|
|||
|
||||
if (Object::cast_to<DirectionalLight3D>(light)) {
|
||||
DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
|
||||
lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
|
||||
lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
|
||||
} else if (Object::cast_to<OmniLight3D>(light)) {
|
||||
OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
|
||||
lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
|
||||
lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
|
||||
} else if (Object::cast_to<SpotLight3D>(light)) {
|
||||
SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
|
||||
lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
|
||||
lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < probes_found.size(); i++) {
|
||||
|
|
|
@ -144,7 +144,7 @@ Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const {
|
|||
|
||||
void Light3D::set_bake_mode(BakeMode p_mode) {
|
||||
bake_mode = p_mode;
|
||||
RS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED);
|
||||
RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode));
|
||||
}
|
||||
|
||||
Light3D::BakeMode Light3D::get_bake_mode() const {
|
||||
|
@ -261,7 +261,7 @@ void Light3D::_bind_methods() {
|
|||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
ADD_GROUP("Shadow", "shadow_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
|
||||
|
@ -296,8 +296,8 @@ void Light3D::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(PARAM_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(BAKE_DISABLED);
|
||||
BIND_ENUM_CONSTANT(BAKE_INDIRECT);
|
||||
BIND_ENUM_CONSTANT(BAKE_ALL);
|
||||
BIND_ENUM_CONSTANT(BAKE_DYNAMIC);
|
||||
BIND_ENUM_CONSTANT(BAKE_STATIC);
|
||||
}
|
||||
|
||||
Light3D::Light3D(RenderingServer::LightType p_type) {
|
||||
|
@ -319,7 +319,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
|
|||
RS::get_singleton()->instance_set_base(get_instance(), light);
|
||||
|
||||
reverse_cull = false;
|
||||
bake_mode = BAKE_INDIRECT;
|
||||
bake_mode = BAKE_DYNAMIC;
|
||||
|
||||
editor_only = false;
|
||||
set_color(Color(1, 1, 1, 1));
|
||||
|
|
|
@ -64,8 +64,8 @@ public:
|
|||
|
||||
enum BakeMode {
|
||||
BAKE_DISABLED,
|
||||
BAKE_INDIRECT,
|
||||
BAKE_ALL
|
||||
BAKE_DYNAMIC,
|
||||
BAKE_STATIC
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -39,31 +39,32 @@ float ReflectionProbe::get_intensity() const {
|
|||
return intensity;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient(Color p_ambient) {
|
||||
interior_ambient = p_ambient;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient);
|
||||
void ReflectionProbe::set_ambient_mode(AmbientMode p_mode) {
|
||||
ambient_mode = p_mode;
|
||||
RS::get_singleton()->reflection_probe_set_ambient_mode(probe, RS::ReflectionProbeAmbientMode(p_mode));
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient_energy(float p_energy) {
|
||||
interior_ambient_energy = p_energy;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy);
|
||||
ReflectionProbe::AmbientMode ReflectionProbe::get_ambient_mode() const {
|
||||
return ambient_mode;
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_interior_ambient_energy() const {
|
||||
return interior_ambient_energy;
|
||||
void ReflectionProbe::set_ambient_color(Color p_ambient) {
|
||||
ambient_color = p_ambient;
|
||||
RS::get_singleton()->reflection_probe_set_ambient_color(probe, p_ambient);
|
||||
}
|
||||
|
||||
Color ReflectionProbe::get_interior_ambient() const {
|
||||
return interior_ambient;
|
||||
void ReflectionProbe::set_ambient_color_energy(float p_energy) {
|
||||
ambient_color_energy = p_energy;
|
||||
RS::get_singleton()->reflection_probe_set_ambient_energy(probe, p_energy);
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) {
|
||||
interior_ambient_probe_contribution = p_contribution;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution);
|
||||
float ReflectionProbe::get_ambient_color_energy() const {
|
||||
return ambient_color_energy;
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_interior_ambient_probe_contribution() const {
|
||||
return interior_ambient_probe_contribution;
|
||||
Color ReflectionProbe::get_ambient_color() const {
|
||||
return ambient_color;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_max_distance(float p_distance) {
|
||||
|
@ -130,7 +131,6 @@ bool ReflectionProbe::is_box_projection_enabled() const {
|
|||
void ReflectionProbe::set_as_interior(bool p_enable) {
|
||||
interior = p_enable;
|
||||
RS::get_singleton()->reflection_probe_set_as_interior(probe, interior);
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
bool ReflectionProbe::is_set_as_interior() const {
|
||||
|
@ -176,8 +176,8 @@ Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
|
|||
}
|
||||
|
||||
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
|
||||
if (property.name == "interior/ambient_color" || property.name == "interior/ambient_energy" || property.name == "interior/ambient_contrib") {
|
||||
if (!interior) {
|
||||
if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") {
|
||||
if (ambient_mode != AMBIENT_COLOR) {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -187,14 +187,14 @@ void ReflectionProbe::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_intensity", "intensity"), &ReflectionProbe::set_intensity);
|
||||
ClassDB::bind_method(D_METHOD("get_intensity"), &ReflectionProbe::get_intensity);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient", "ambient"), &ReflectionProbe::set_interior_ambient);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient"), &ReflectionProbe::get_interior_ambient);
|
||||
ClassDB::bind_method(D_METHOD("set_ambient_mode", "ambient"), &ReflectionProbe::set_ambient_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_ambient_mode"), &ReflectionProbe::get_ambient_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient_energy", "ambient_energy"), &ReflectionProbe::set_interior_ambient_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient_energy"), &ReflectionProbe::get_interior_ambient_energy);
|
||||
ClassDB::bind_method(D_METHOD("set_ambient_color", "ambient"), &ReflectionProbe::set_ambient_color);
|
||||
ClassDB::bind_method(D_METHOD("get_ambient_color"), &ReflectionProbe::get_ambient_color);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient_probe_contribution", "ambient_probe_contribution"), &ReflectionProbe::set_interior_ambient_probe_contribution);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient_probe_contribution"), &ReflectionProbe::get_interior_ambient_probe_contribution);
|
||||
ClassDB::bind_method(D_METHOD("set_ambient_color_energy", "ambient_energy"), &ReflectionProbe::set_ambient_color_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_ambient_color_energy"), &ReflectionProbe::get_ambient_color_energy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_max_distance", "max_distance"), &ReflectionProbe::set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_max_distance"), &ReflectionProbe::get_max_distance);
|
||||
|
@ -226,24 +226,28 @@ void ReflectionProbe::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_as_interior", "is_set_as_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_shadows"), "set_enable_shadows", "are_shadows_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
|
||||
ADD_GROUP("Interior", "interior_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior_enable"), "set_as_interior", "is_set_as_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "interior_ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_interior_ambient", "get_interior_ambient");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution");
|
||||
ADD_GROUP("Ambient", "ambient_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ambient_color", "get_ambient_color");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_color_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_color_energy", "get_ambient_color_energy");
|
||||
|
||||
BIND_ENUM_CONSTANT(UPDATE_ONCE);
|
||||
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
|
||||
|
||||
BIND_ENUM_CONSTANT(AMBIENT_DISABLED);
|
||||
BIND_ENUM_CONSTANT(AMBIENT_ENVIRONMENT);
|
||||
BIND_ENUM_CONSTANT(AMBIENT_COLOR);
|
||||
}
|
||||
|
||||
ReflectionProbe::ReflectionProbe() {
|
||||
intensity = 1.0;
|
||||
interior_ambient = Color(0, 0, 0);
|
||||
interior_ambient_probe_contribution = 0;
|
||||
interior_ambient_energy = 1.0;
|
||||
ambient_mode = AMBIENT_ENVIRONMENT;
|
||||
ambient_color = Color(0, 0, 0);
|
||||
ambient_color_energy = 1.0;
|
||||
max_distance = 0;
|
||||
extents = Vector3(1, 1, 1);
|
||||
origin_offset = Vector3(0, 0, 0);
|
||||
|
|
|
@ -45,6 +45,12 @@ public:
|
|||
UPDATE_ALWAYS,
|
||||
};
|
||||
|
||||
enum AmbientMode {
|
||||
AMBIENT_DISABLED,
|
||||
AMBIENT_ENVIRONMENT,
|
||||
AMBIENT_COLOR
|
||||
};
|
||||
|
||||
private:
|
||||
RID probe;
|
||||
float intensity;
|
||||
|
@ -54,9 +60,9 @@ private:
|
|||
bool box_projection;
|
||||
bool enable_shadows;
|
||||
bool interior;
|
||||
Color interior_ambient;
|
||||
float interior_ambient_energy;
|
||||
float interior_ambient_probe_contribution;
|
||||
AmbientMode ambient_mode;
|
||||
Color ambient_color;
|
||||
float ambient_color_energy;
|
||||
|
||||
uint32_t cull_mask;
|
||||
UpdateMode update_mode;
|
||||
|
@ -69,11 +75,14 @@ public:
|
|||
void set_intensity(float p_intensity);
|
||||
float get_intensity() const;
|
||||
|
||||
void set_interior_ambient(Color p_ambient);
|
||||
Color get_interior_ambient() const;
|
||||
void set_ambient_mode(AmbientMode p_mode);
|
||||
AmbientMode get_ambient_mode() const;
|
||||
|
||||
void set_interior_ambient_energy(float p_energy);
|
||||
float get_interior_ambient_energy() const;
|
||||
void set_ambient_color(Color p_ambient);
|
||||
Color get_ambient_color() const;
|
||||
|
||||
void set_ambient_color_energy(float p_energy);
|
||||
float get_ambient_color_energy() const;
|
||||
|
||||
void set_interior_ambient_probe_contribution(float p_contribution);
|
||||
float get_interior_ambient_probe_contribution() const;
|
||||
|
@ -109,6 +118,7 @@ public:
|
|||
~ReflectionProbe();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(ReflectionProbe::AmbientMode);
|
||||
VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode);
|
||||
|
||||
#endif // REFLECTIONPROBE_H
|
||||
|
|
|
@ -3404,9 +3404,11 @@ void Viewport::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_ROUGHNESS_LIMITER);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_PSSM_SPLITS);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_DECAL_ATLAS);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI_PROBES);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_BUFFER);
|
||||
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
|
||||
|
|
|
@ -137,9 +137,11 @@ public:
|
|||
DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
|
||||
DEBUG_DRAW_SCENE_LUMINANCE,
|
||||
DEBUG_DRAW_SSAO,
|
||||
DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||
DEBUG_DRAW_PSSM_SPLITS,
|
||||
DEBUG_DRAW_DECAL_ATLAS
|
||||
DEBUG_DRAW_DECAL_ATLAS,
|
||||
DEBUG_DRAW_SDFGI,
|
||||
DEBUG_DRAW_SDFGI_PROBES,
|
||||
DEBUG_DRAW_GI_BUFFER,
|
||||
};
|
||||
|
||||
enum DefaultCanvasItemTextureFilter {
|
||||
|
|
|
@ -745,6 +745,135 @@ bool Environment::_set(const StringName &p_name, const Variant &p_value) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void Environment::set_sdfgi_enabled(bool p_enabled) {
|
||||
sdfgi_enabled = p_enabled;
|
||||
_update_sdfgi();
|
||||
}
|
||||
|
||||
bool Environment::is_sdfgi_enabled() const {
|
||||
return sdfgi_enabled;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_cascades(SDFGICascades p_cascades) {
|
||||
sdfgi_cascades = p_cascades;
|
||||
_update_sdfgi();
|
||||
}
|
||||
Environment::SDFGICascades Environment::get_sdfgi_cascades() const {
|
||||
return sdfgi_cascades;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_min_cell_size(float p_size) {
|
||||
sdfgi_min_cell_size = p_size;
|
||||
_change_notify("sdfgi_max_distance");
|
||||
_change_notify("sdfgi_cascade0_distance");
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_min_cell_size() const {
|
||||
return sdfgi_min_cell_size;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_max_distance(float p_size) {
|
||||
p_size /= 64.0;
|
||||
int cc[3] = { 4, 6, 8 };
|
||||
int cascades = cc[sdfgi_cascades];
|
||||
for (int i = 0; i < cascades; i++) {
|
||||
p_size *= 0.5; //halve for each cascade
|
||||
}
|
||||
sdfgi_min_cell_size = p_size;
|
||||
_change_notify("sdfgi_min_cell_size");
|
||||
_change_notify("sdfgi_cascade0_distance");
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_max_distance() const {
|
||||
float md = sdfgi_min_cell_size;
|
||||
md *= 64.0;
|
||||
int cc[3] = { 4, 6, 8 };
|
||||
int cascades = cc[sdfgi_cascades];
|
||||
for (int i = 0; i < cascades; i++) {
|
||||
md *= 2.0;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_cascade0_distance(float p_size) {
|
||||
sdfgi_min_cell_size = p_size / 64.0;
|
||||
_change_notify("sdfgi_min_cell_size");
|
||||
_change_notify("sdfgi_max_distance");
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_cascade0_distance() const {
|
||||
return sdfgi_min_cell_size * 64.0;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_use_occlusion(bool p_enable) {
|
||||
sdfgi_use_occlusion = p_enable;
|
||||
_update_sdfgi();
|
||||
}
|
||||
|
||||
bool Environment::is_sdfgi_using_occlusion() const {
|
||||
return sdfgi_use_occlusion;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_use_multi_bounce(bool p_enable) {
|
||||
sdfgi_use_multibounce = p_enable;
|
||||
_update_sdfgi();
|
||||
}
|
||||
bool Environment::is_sdfgi_using_multi_bounce() const {
|
||||
return sdfgi_use_multibounce;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_use_enhance_ssr(bool p_enable) {
|
||||
sdfgi_enhance_ssr = p_enable;
|
||||
_update_sdfgi();
|
||||
}
|
||||
bool Environment::is_sdfgi_using_enhance_ssr() const {
|
||||
return sdfgi_enhance_ssr;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_read_sky_light(bool p_enable) {
|
||||
sdfgi_read_sky_light = p_enable;
|
||||
_update_sdfgi();
|
||||
}
|
||||
|
||||
bool Environment::is_sdfgi_reading_sky_light() const {
|
||||
return sdfgi_read_sky_light;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_energy(float p_energy) {
|
||||
sdfgi_energy = p_energy;
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_energy() const {
|
||||
return sdfgi_energy;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_normal_bias(float p_bias) {
|
||||
sdfgi_normal_bias = p_bias;
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_normal_bias() const {
|
||||
return sdfgi_normal_bias;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_probe_bias(float p_bias) {
|
||||
sdfgi_probe_bias = p_bias;
|
||||
_update_sdfgi();
|
||||
}
|
||||
float Environment::get_sdfgi_probe_bias() const {
|
||||
return sdfgi_probe_bias;
|
||||
}
|
||||
|
||||
void Environment::set_sdfgi_y_scale(SDFGIYScale p_y_scale) {
|
||||
sdfgi_y_scale = p_y_scale;
|
||||
_update_sdfgi();
|
||||
}
|
||||
Environment::SDFGIYScale Environment::get_sdfgi_y_scale() const {
|
||||
return sdfgi_y_scale;
|
||||
}
|
||||
void Environment::_update_sdfgi() {
|
||||
RS::get_singleton()->environment_set_sdfgi(environment, sdfgi_enabled, RS::EnvironmentSDFGICascades(sdfgi_cascades), sdfgi_min_cell_size, RS::EnvironmentSDFGIYScale(sdfgi_y_scale), sdfgi_use_occlusion, sdfgi_use_multibounce, sdfgi_read_sky_light, sdfgi_enhance_ssr, sdfgi_energy, sdfgi_normal_bias, sdfgi_probe_bias);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -944,6 +1073,56 @@ void Environment::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_enabled", "enabled"), &Environment::set_sdfgi_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_sdfgi_enabled"), &Environment::is_sdfgi_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_cascades", "amount"), &Environment::set_sdfgi_cascades);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_cascades"), &Environment::get_sdfgi_cascades);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_min_cell_size", "strength"), &Environment::set_sdfgi_min_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_min_cell_size"), &Environment::get_sdfgi_min_cell_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_max_distance", "strength"), &Environment::set_sdfgi_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_max_distance"), &Environment::get_sdfgi_max_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_cascade0_distance", "strength"), &Environment::set_sdfgi_cascade0_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_cascade0_distance"), &Environment::get_sdfgi_cascade0_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_use_occlusion", "enable"), &Environment::set_sdfgi_use_occlusion);
|
||||
ClassDB::bind_method(D_METHOD("is_sdfgi_using_occlusion"), &Environment::is_sdfgi_using_occlusion);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_use_multi_bounce", "enable"), &Environment::set_sdfgi_use_multi_bounce);
|
||||
ClassDB::bind_method(D_METHOD("is_sdfgi_using_multi_bounce"), &Environment::is_sdfgi_using_multi_bounce);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_read_sky_light", "enable"), &Environment::set_sdfgi_read_sky_light);
|
||||
ClassDB::bind_method(D_METHOD("is_sdfgi_reading_sky_light"), &Environment::is_sdfgi_reading_sky_light);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_energy", "amount"), &Environment::set_sdfgi_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_energy"), &Environment::get_sdfgi_energy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_normal_bias", "bias"), &Environment::set_sdfgi_normal_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_normal_bias"), &Environment::get_sdfgi_normal_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_probe_bias", "bias"), &Environment::set_sdfgi_probe_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_probe_bias"), &Environment::get_sdfgi_probe_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdfgi_y_scale", "scale"), &Environment::set_sdfgi_y_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_sdfgi_y_scale"), &Environment::get_sdfgi_y_scale);
|
||||
|
||||
ADD_GROUP("SDFGI", "sdfgi_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_enabled"), "set_sdfgi_enabled", "is_sdfgi_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_multi_bounce"), "set_sdfgi_use_multi_bounce", "is_sdfgi_using_multi_bounce");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_y_scale", PROPERTY_HINT_ENUM, "Disable,75%,50%"), "set_sdfgi_y_scale", "get_sdfgi_y_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_energy"), "set_sdfgi_energy", "get_sdfgi_energy");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_normal_bias"), "set_sdfgi_normal_bias", "get_sdfgi_normal_bias");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_probe_bias"), "set_sdfgi_probe_bias", "get_sdfgi_probe_bias");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_glow_enabled", "enabled"), &Environment::set_glow_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_glow_enabled"), &Environment::is_glow_enabled);
|
||||
|
||||
|
@ -1128,6 +1307,19 @@ Environment::Environment() {
|
|||
|
||||
set_fog_color(Color(0.5, 0.6, 0.7));
|
||||
set_fog_sun_color(Color(1.0, 0.9, 0.7));
|
||||
|
||||
sdfgi_enabled = false;
|
||||
sdfgi_cascades = SDFGI_CASCADES_6;
|
||||
sdfgi_min_cell_size = 0.2;
|
||||
sdfgi_use_occlusion = false;
|
||||
sdfgi_use_multibounce = false;
|
||||
sdfgi_read_sky_light = false;
|
||||
sdfgi_enhance_ssr = false;
|
||||
sdfgi_energy = 1.0;
|
||||
sdfgi_normal_bias = 1.1;
|
||||
sdfgi_probe_bias = 1.1;
|
||||
sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED;
|
||||
_update_sdfgi();
|
||||
}
|
||||
|
||||
Environment::~Environment() {
|
||||
|
|
|
@ -86,6 +86,18 @@ public:
|
|||
SSAO_BLUR_3x3
|
||||
};
|
||||
|
||||
enum SDFGICascades {
|
||||
SDFGI_CASCADES_4,
|
||||
SDFGI_CASCADES_6,
|
||||
SDFGI_CASCADES_8,
|
||||
};
|
||||
|
||||
enum SDFGIYScale {
|
||||
SDFGI_Y_SCALE_DISABLED,
|
||||
SDFGI_Y_SCALE_75_PERCENT,
|
||||
SDFGI_Y_SCALE_50_PERCENT,
|
||||
};
|
||||
|
||||
private:
|
||||
RID environment;
|
||||
|
||||
|
@ -163,6 +175,20 @@ private:
|
|||
float fog_height_max;
|
||||
float fog_height_curve;
|
||||
|
||||
bool sdfgi_enabled;
|
||||
SDFGICascades sdfgi_cascades;
|
||||
float sdfgi_min_cell_size;
|
||||
bool sdfgi_use_occlusion;
|
||||
bool sdfgi_use_multibounce;
|
||||
bool sdfgi_read_sky_light;
|
||||
bool sdfgi_enhance_ssr;
|
||||
float sdfgi_energy;
|
||||
float sdfgi_normal_bias;
|
||||
float sdfgi_probe_bias;
|
||||
SDFGIYScale sdfgi_y_scale;
|
||||
|
||||
void _update_sdfgi();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
@ -354,6 +380,45 @@ public:
|
|||
void set_fog_height_curve(float p_distance);
|
||||
float get_fog_height_curve() const;
|
||||
|
||||
void set_sdfgi_enabled(bool p_enabled);
|
||||
bool is_sdfgi_enabled() const;
|
||||
|
||||
void set_sdfgi_cascades(SDFGICascades p_cascades);
|
||||
SDFGICascades get_sdfgi_cascades() const;
|
||||
|
||||
void set_sdfgi_min_cell_size(float p_size);
|
||||
float get_sdfgi_min_cell_size() const;
|
||||
|
||||
void set_sdfgi_cascade0_distance(float p_size);
|
||||
float get_sdfgi_cascade0_distance() const;
|
||||
|
||||
void set_sdfgi_max_distance(float p_size);
|
||||
float get_sdfgi_max_distance() const;
|
||||
|
||||
void set_sdfgi_use_occlusion(bool p_enable);
|
||||
bool is_sdfgi_using_occlusion() const;
|
||||
|
||||
void set_sdfgi_use_multi_bounce(bool p_enable);
|
||||
bool is_sdfgi_using_multi_bounce() const;
|
||||
|
||||
void set_sdfgi_use_enhance_ssr(bool p_enable);
|
||||
bool is_sdfgi_using_enhance_ssr() const;
|
||||
|
||||
void set_sdfgi_read_sky_light(bool p_enable);
|
||||
bool is_sdfgi_reading_sky_light() const;
|
||||
|
||||
void set_sdfgi_energy(float p_energy);
|
||||
float get_sdfgi_energy() const;
|
||||
|
||||
void set_sdfgi_normal_bias(float p_bias);
|
||||
float get_sdfgi_normal_bias() const;
|
||||
|
||||
void set_sdfgi_probe_bias(float p_bias);
|
||||
float get_sdfgi_probe_bias() const;
|
||||
|
||||
void set_sdfgi_y_scale(SDFGIYScale p_y_scale);
|
||||
SDFGIYScale get_sdfgi_y_scale() const;
|
||||
|
||||
virtual RID get_rid() const;
|
||||
|
||||
Environment();
|
||||
|
@ -366,6 +431,8 @@ VARIANT_ENUM_CAST(Environment::ReflectionSource)
|
|||
VARIANT_ENUM_CAST(Environment::ToneMapper)
|
||||
VARIANT_ENUM_CAST(Environment::GlowBlendMode)
|
||||
VARIANT_ENUM_CAST(Environment::SSAOBlur)
|
||||
VARIANT_ENUM_CAST(Environment::SDFGICascades)
|
||||
VARIANT_ENUM_CAST(Environment::SDFGIYScale)
|
||||
|
||||
class CameraEffects : public Resource {
|
||||
GDCLASS(CameraEffects, Resource);
|
||||
|
|
|
@ -50,6 +50,16 @@ public:
|
|||
virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
|
||||
virtual void set_directional_shadow_count(int p_count) = 0;
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
struct InstanceBase;
|
||||
|
||||
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
|
||||
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
|
||||
virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
|
||||
|
||||
/* SKY API */
|
||||
|
||||
virtual RID sky_create() = 0;
|
||||
|
@ -86,6 +96,11 @@ public:
|
|||
|
||||
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0;
|
||||
|
||||
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, bool p_enhance_ssr, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
|
||||
|
||||
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
|
||||
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
|
||||
|
||||
virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
|
||||
|
||||
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
|
||||
|
@ -111,8 +126,6 @@ public:
|
|||
virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
|
||||
virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
|
||||
|
||||
struct InstanceBase;
|
||||
|
||||
struct InstanceDependency {
|
||||
void instance_notify_changed(bool p_aabb, bool p_dependencies);
|
||||
void instance_notify_deleted(RID p_deleted);
|
||||
|
@ -248,6 +261,7 @@ public:
|
|||
|
||||
virtual RID light_instance_create(RID p_light) = 0;
|
||||
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
|
||||
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
|
||||
virtual 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_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
|
||||
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
|
||||
virtual bool light_instances_can_render_shadow_cube() const {
|
||||
|
@ -273,10 +287,14 @@ public:
|
|||
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
|
||||
virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
|
||||
|
||||
virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
|
||||
|
||||
virtual 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_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
|
||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0;
|
||||
|
||||
virtual void set_scene_pass(uint64_t p_pass) = 0;
|
||||
virtual void set_time(double p_time, double p_step) = 0;
|
||||
|
@ -285,7 +303,7 @@ public:
|
|||
virtual RID render_buffers_create() = 0;
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) = 0;
|
||||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0;
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
|
||||
virtual bool screen_space_roughness_limiter_is_active() const = 0;
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
|
||||
|
@ -295,6 +313,8 @@ public:
|
|||
|
||||
virtual bool free(RID p_rid) = 0;
|
||||
|
||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
virtual ~RasterizerScene() {}
|
||||
};
|
||||
|
@ -484,7 +504,8 @@ public:
|
|||
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
|
||||
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
|
||||
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
|
||||
virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
|
||||
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
|
||||
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
|
||||
|
||||
virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
|
||||
|
||||
|
@ -503,7 +524,8 @@ public:
|
|||
virtual AABB light_get_aabb(RID p_light) const = 0;
|
||||
virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
|
||||
virtual Color light_get_color(RID p_light) = 0;
|
||||
virtual bool light_get_use_gi(RID p_light) = 0;
|
||||
virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
|
||||
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
|
||||
virtual uint64_t light_get_version(RID p_light) const = 0;
|
||||
|
||||
/* PROBE API */
|
||||
|
@ -513,9 +535,9 @@ public:
|
|||
virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0;
|
||||
virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
|
||||
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
|
||||
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
|
||||
virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
|
||||
virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
|
||||
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
|
||||
|
|
|
@ -218,7 +218,7 @@ void RasterizerEffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_f
|
|||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
}
|
||||
|
||||
void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero) {
|
||||
void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary) {
|
||||
zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||
|
||||
if (p_flip_y) {
|
||||
|
@ -230,10 +230,16 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr
|
|||
if (p_alpha_to_zero) {
|
||||
copy_to_fb.push_constant.alpha_to_zero = true;
|
||||
}
|
||||
if (p_srgb) {
|
||||
copy_to_fb.push_constant.srgb = true;
|
||||
}
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY].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);
|
||||
if (p_secondary.is_valid()) {
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1);
|
||||
}
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
|
@ -434,7 +440,7 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture,
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
|
||||
void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
|
||||
|
@ -451,7 +457,7 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, R
|
|||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3);
|
||||
|
||||
|
@ -491,7 +497,7 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, R
|
|||
|
||||
if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_roughness), 3);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_normal_roughness), 3);
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
|
||||
|
@ -1201,6 +1207,28 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
|
|||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
}
|
||||
|
||||
void RasterizerEffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples) {
|
||||
ResolvePushConstant push_constant;
|
||||
push_constant.screen_size[0] = p_screen_size.x;
|
||||
push_constant.screen_size[1] = p_screen_size.y;
|
||||
push_constant.samples = p_samples;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_giprobe.is_valid() ? RESOLVE_MODE_GI_GIPROBE : RESOLVE_MODE_GI]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1);
|
||||
if (p_source_giprobe.is_valid()) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_giprobe), 2);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_giprobe), 3);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1, 8, 8, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
RasterizerEffectsRD::RasterizerEffectsRD() {
|
||||
{ // Initialize copy
|
||||
Vector<String> copy_modes;
|
||||
|
@ -1228,6 +1256,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
|
|||
Vector<String> copy_modes;
|
||||
copy_modes.push_back("\n");
|
||||
copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
|
||||
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
|
||||
|
||||
copy_to_fb.shader.initialize(copy_modes);
|
||||
|
||||
|
@ -1517,6 +1546,20 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
Vector<String> resolve_modes;
|
||||
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
|
||||
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define GIPROBE_RESOLVE\n");
|
||||
|
||||
resolve.shader.initialize(resolve_modes);
|
||||
|
||||
resolve.shader_version = resolve.shader.version_create();
|
||||
|
||||
for (int i = 0; i < RESOLVE_MODE_MAX; i++) {
|
||||
resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i));
|
||||
}
|
||||
}
|
||||
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/resolve.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
|
||||
|
@ -114,6 +115,7 @@ class RasterizerEffectsRD {
|
|||
enum CopyToFBMode {
|
||||
COPY_TO_FB_COPY,
|
||||
COPY_TO_FB_COPY_PANORAMA_TO_DP,
|
||||
COPY_TO_FB_COPY2,
|
||||
COPY_TO_FB_MAX,
|
||||
|
||||
};
|
||||
|
@ -126,7 +128,8 @@ class RasterizerEffectsRD {
|
|||
|
||||
uint32_t force_luminance;
|
||||
uint32_t alpha_to_zero;
|
||||
uint32_t pad[2];
|
||||
uint32_t srgb;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct CopyToFb {
|
||||
|
@ -512,6 +515,25 @@ class RasterizerEffectsRD {
|
|||
RID pipelines[3]; //3 quality levels
|
||||
} sss;
|
||||
|
||||
struct ResolvePushConstant {
|
||||
int32_t screen_size[2];
|
||||
int32_t samples;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
enum ResolveMode {
|
||||
RESOLVE_MODE_GI,
|
||||
RESOLVE_MODE_GI_GIPROBE,
|
||||
RESOLVE_MODE_MAX
|
||||
};
|
||||
|
||||
struct Resolve {
|
||||
ResolvePushConstant push_constant;
|
||||
ResolveShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels
|
||||
} resolve;
|
||||
|
||||
RID default_sampler;
|
||||
RID default_mipmap_sampler;
|
||||
RID index_buffer;
|
||||
|
@ -544,7 +566,7 @@ class RasterizerEffectsRD {
|
|||
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
|
||||
|
||||
public:
|
||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false);
|
||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
|
||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false);
|
||||
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
|
||||
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
|
||||
|
@ -605,10 +627,12 @@ public:
|
|||
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
|
||||
void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
|
||||
|
||||
void screen_space_reflection(RID p_diffuse, RID p_normal, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
|
||||
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
|
||||
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
|
||||
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
|
||||
|
||||
void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples);
|
||||
|
||||
RasterizerEffectsRD();
|
||||
~RasterizerEffectsRD();
|
||||
};
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
|
||||
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
|
||||
_ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; }
|
||||
_ALWAYS_INLINE_ double get_total_time() const { return time; }
|
||||
|
||||
static Error is_viable() {
|
||||
return OK;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,18 +47,23 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
MATERIAL_UNIFORM_SET = 5
|
||||
};
|
||||
|
||||
enum {
|
||||
SDFGI_MAX_CASCADES = 8,
|
||||
MAX_GI_PROBES = 8
|
||||
};
|
||||
|
||||
/* Scene Shader */
|
||||
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_DEPTH_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI,
|
||||
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_VCT_COLOR_PASS,
|
||||
SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_MAX
|
||||
|
@ -203,8 +208,11 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
RID color;
|
||||
RID depth;
|
||||
RID specular;
|
||||
RID normal_buffer;
|
||||
RID roughness_buffer;
|
||||
RID normal_roughness_buffer;
|
||||
RID giprobe_buffer;
|
||||
|
||||
RID ambient_buffer;
|
||||
RID reflection_buffer;
|
||||
|
||||
RS::ViewportMSAA msaa;
|
||||
RD::TextureSamples texture_samples;
|
||||
|
@ -212,18 +220,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
RID color_msaa;
|
||||
RID depth_msaa;
|
||||
RID specular_msaa;
|
||||
RID normal_buffer_msaa;
|
||||
RID normal_roughness_buffer_msaa;
|
||||
RID roughness_buffer_msaa;
|
||||
RID giprobe_buffer_msaa;
|
||||
|
||||
RID depth_fb;
|
||||
RID depth_normal_fb;
|
||||
RID depth_normal_roughness_fb;
|
||||
RID depth_normal_roughness_giprobe_fb;
|
||||
RID color_fb;
|
||||
RID color_specular_fb;
|
||||
RID specular_only_fb;
|
||||
int width, height;
|
||||
|
||||
RID render_sdfgi_uniform_set;
|
||||
void ensure_specular();
|
||||
void ensure_gi();
|
||||
void ensure_giprobe();
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
|
||||
|
||||
|
@ -233,8 +245,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
};
|
||||
|
||||
virtual RenderBufferData *_create_render_buffer_data();
|
||||
void _allocate_normal_texture(RenderBufferDataHighEnd *rb);
|
||||
void _allocate_roughness_texture(RenderBufferDataHighEnd *rb);
|
||||
void _allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb);
|
||||
|
||||
RID shadow_sampler;
|
||||
RID render_base_uniform_set;
|
||||
|
@ -245,11 +256,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
virtual void _base_uniforms_changed();
|
||||
void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb);
|
||||
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers);
|
||||
|
||||
void _update_render_base_uniform_set();
|
||||
void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas);
|
||||
void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
|
||||
void _update_render_buffers_uniform_set(RID p_render_buffers);
|
||||
|
||||
/* Scene State UBO */
|
||||
|
@ -260,7 +272,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
float box_offset[3];
|
||||
uint32_t mask;
|
||||
float params[4]; // intensity, 0, interior , boxproject
|
||||
float ambient[4]; // ambient color, energy
|
||||
float ambient[3]; // ambient color,
|
||||
uint32_t ambient_mode;
|
||||
float local_matrix[16]; // up to here for spot and omni, rest is for directional
|
||||
};
|
||||
|
||||
|
@ -315,22 +328,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
float uv_scale4[2];
|
||||
};
|
||||
|
||||
struct GIProbeData {
|
||||
float xform[16];
|
||||
float bounds[3];
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
uint32_t blend_ambient;
|
||||
uint32_t texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ao;
|
||||
float ao_size;
|
||||
uint32_t pad[1];
|
||||
};
|
||||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
};
|
||||
|
@ -358,6 +355,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
};
|
||||
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
|
||||
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
|
||||
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
|
||||
|
@ -430,10 +429,19 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
float ssao_ao_affect;
|
||||
uint32_t roughness_limiter_enabled;
|
||||
|
||||
float roughness_limiter_amount;
|
||||
float roughness_limiter_limit;
|
||||
uint32_t roughness_limiter_pad[2];
|
||||
|
||||
float ao_color[4];
|
||||
|
||||
float sdf_to_bounds[16];
|
||||
|
||||
int32_t sdf_offset[3];
|
||||
uint32_t material_uv2_mode;
|
||||
uint32_t pad_material[3];
|
||||
|
||||
int32_t sdf_size[3];
|
||||
uint32_t gi_upscale_for_msaa;
|
||||
};
|
||||
|
||||
UBO ubo;
|
||||
|
@ -445,11 +453,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
RID reflection_buffer;
|
||||
uint32_t max_reflection_probes_per_instance;
|
||||
|
||||
GIProbeData *gi_probes;
|
||||
uint32_t max_gi_probes;
|
||||
RID gi_probe_buffer;
|
||||
uint32_t max_gi_probe_probes_per_instance;
|
||||
|
||||
LightmapData *lightmaps;
|
||||
uint32_t max_lightmaps;
|
||||
RID lightmap_buffer;
|
||||
|
@ -498,7 +501,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
uint64_t material_index : 15;
|
||||
uint64_t shader_index : 12;
|
||||
uint64_t uses_instancing : 1;
|
||||
uint64_t uses_vct : 1;
|
||||
uint64_t uses_forward_gi : 1;
|
||||
uint64_t uses_lightmap : 1;
|
||||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
|
@ -625,6 +628,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
RID wireframe_material_shader;
|
||||
RID wireframe_material;
|
||||
RID default_shader_rd;
|
||||
RID default_shader_sdfgi_rd;
|
||||
RID default_radiance_uniform_set;
|
||||
RID default_render_buffers_uniform_set;
|
||||
|
||||
|
@ -640,30 +644,33 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
PASS_MODE_SHADOW,
|
||||
PASS_MODE_SHADOW_DP,
|
||||
PASS_MODE_DEPTH,
|
||||
PASS_MODE_DEPTH_NORMAL,
|
||||
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
|
||||
PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
PASS_MODE_SDF,
|
||||
};
|
||||
|
||||
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
|
||||
void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
|
||||
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
|
||||
void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
|
||||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
|
||||
void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
|
||||
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth);
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
|
||||
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, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2());
|
||||
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
|
||||
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index);
|
||||
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
|
||||
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
|
||||
|
||||
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
|
||||
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi = false);
|
||||
|
||||
Map<Size2i, RID> sdfgi_framebuffer_size_cache;
|
||||
|
||||
protected:
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
|
||||
|
||||
public:
|
||||
virtual void set_time(double p_time, double p_step);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,22 +31,22 @@
|
|||
#ifndef RASTERIZER_SCENE_RD_H
|
||||
#define RASTERIZER_SCENE_RD_H
|
||||
|
||||
#include "core/local_vector.h"
|
||||
#include "core/rid_owner.h"
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/gi.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/giprobe.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/sky.glsl.gen.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
class RasterizerSceneRD : public RasterizerScene {
|
||||
public:
|
||||
enum GIProbeQuality {
|
||||
GIPROBE_QUALITY_ULTRA_LOW,
|
||||
GIPROBE_QUALITY_MEDIUM,
|
||||
GIPROBE_QUALITY_HIGH,
|
||||
};
|
||||
|
||||
protected:
|
||||
double time;
|
||||
|
||||
|
@ -81,23 +81,27 @@ protected:
|
|||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0;
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
|
||||
|
||||
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
|
||||
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
|
||||
|
||||
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
|
||||
|
||||
virtual void _base_uniforms_changed() = 0;
|
||||
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers) = 0;
|
||||
|
||||
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
|
||||
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
|
||||
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
|
||||
void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
|
||||
|
||||
void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size);
|
||||
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
|
||||
void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
|
||||
void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
|
||||
|
||||
private:
|
||||
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
|
||||
|
@ -267,6 +271,8 @@ private:
|
|||
SkyMaterialData *prev_material;
|
||||
Vector3 prev_position;
|
||||
float prev_time;
|
||||
|
||||
RID sdfgi_integrate_sky_uniform_set;
|
||||
};
|
||||
|
||||
Sky *dirty_sky_list = nullptr;
|
||||
|
@ -388,13 +394,10 @@ private:
|
|||
struct GIProbeInstance {
|
||||
RID probe;
|
||||
RID texture;
|
||||
RID anisotropy[2]; //only if anisotropy is used
|
||||
RID anisotropy_r16[2]; //only if anisotropy is used
|
||||
RID write_buffer;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
RID anisotropy[2]; //only if anisotropy is used
|
||||
RID uniform_set;
|
||||
RID second_bounce_uniform_set;
|
||||
RID write_uniform_set;
|
||||
|
@ -423,7 +426,7 @@ private:
|
|||
uint32_t last_probe_version = 0;
|
||||
uint32_t last_probe_data_version = 0;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
//uint64_t last_pass = 0;
|
||||
uint32_t render_index = 0;
|
||||
|
||||
bool has_dynamic_object_data = false;
|
||||
|
@ -435,11 +438,6 @@ private:
|
|||
uint32_t gi_probe_max_lights;
|
||||
RID gi_probe_lights_uniform;
|
||||
|
||||
bool gi_probe_use_anisotropy = false;
|
||||
GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM;
|
||||
|
||||
Vector<RID> gi_probe_slots;
|
||||
|
||||
enum {
|
||||
GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT,
|
||||
GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
|
||||
|
@ -458,6 +456,8 @@ private:
|
|||
|
||||
mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
|
||||
|
||||
RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH;
|
||||
|
||||
enum {
|
||||
GI_PROBE_DEBUG_COLOR,
|
||||
GI_PROBE_DEBUG_LIGHT,
|
||||
|
@ -591,6 +591,7 @@ private:
|
|||
|
||||
ShadowTransform shadow_transform[4];
|
||||
|
||||
AABB aabb;
|
||||
RID self;
|
||||
RID light;
|
||||
Transform transform;
|
||||
|
@ -680,6 +681,19 @@ private:
|
|||
float ssr_fade_in = 0.15;
|
||||
float ssr_fade_out = 2.0;
|
||||
float ssr_depth_tolerance = 0.2;
|
||||
|
||||
/// SDFGI
|
||||
bool sdfgi_enabled = false;
|
||||
RS::EnvironmentSDFGICascades sdfgi_cascades;
|
||||
float sdfgi_min_cell_size = 0.2;
|
||||
bool sdfgi_use_occlusion = false;
|
||||
bool sdfgi_use_multibounce = false;
|
||||
bool sdfgi_read_sky_light = false;
|
||||
bool sdfgi_enhance_ssr = false;
|
||||
float sdfgi_energy = 1.0;
|
||||
float sdfgi_normal_bias = 1.1;
|
||||
float sdfgi_probe_bias = 1.1;
|
||||
RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED;
|
||||
};
|
||||
|
||||
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
|
||||
|
@ -719,7 +733,13 @@ private:
|
|||
|
||||
/* RENDER BUFFERS */
|
||||
|
||||
struct SDFGI;
|
||||
|
||||
struct RenderBuffers {
|
||||
enum {
|
||||
MAX_GIPROBES = 8
|
||||
};
|
||||
|
||||
RenderBufferData *data = nullptr;
|
||||
int width = 0, height = 0;
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
|
@ -732,6 +752,9 @@ private:
|
|||
RID texture; //main texture for rendering to, must be filled after done rendering
|
||||
RID depth_texture; //main depth texture
|
||||
|
||||
RID gi_uniform_set;
|
||||
SDFGI *sdfgi = nullptr;
|
||||
|
||||
//built-in textures used for ping pong image processing and blurring
|
||||
struct Blur {
|
||||
RID texture;
|
||||
|
@ -764,10 +787,389 @@ private:
|
|||
RID depth_scaled;
|
||||
RID blur_radius[2];
|
||||
} ssr;
|
||||
|
||||
RID giprobe_textures[MAX_GIPROBES];
|
||||
RID giprobe_buffer;
|
||||
};
|
||||
|
||||
RID default_giprobe_buffer;
|
||||
|
||||
/* SDFGI */
|
||||
|
||||
struct SDFGI {
|
||||
enum {
|
||||
MAX_CASCADES = 8,
|
||||
CASCADE_SIZE = 128,
|
||||
PROBE_DIVISOR = 16,
|
||||
ANISOTROPY_SIZE = 6,
|
||||
MAX_DYNAMIC_LIGHTS = 128,
|
||||
MAX_STATIC_LIGHTS = 1024,
|
||||
LIGHTPROBE_OCT_SIZE = 6,
|
||||
SH_SIZE = 16
|
||||
};
|
||||
|
||||
struct Cascade {
|
||||
struct UBO {
|
||||
float offset[3];
|
||||
float to_cell;
|
||||
int32_t probe_offset[3];
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
//cascade blocks are full-size for volume (128^3), half size for albedo/emission
|
||||
RID sdf_tex;
|
||||
RID light_tex;
|
||||
RID light_aniso_0_tex;
|
||||
RID light_aniso_1_tex;
|
||||
|
||||
RID light_data;
|
||||
RID light_aniso_0_data;
|
||||
RID light_aniso_1_data;
|
||||
|
||||
struct SolidCell { // this struct is unused, but remains as reference for size
|
||||
uint32_t position;
|
||||
uint32_t albedo;
|
||||
uint32_t static_light;
|
||||
uint32_t static_light_aniso;
|
||||
};
|
||||
|
||||
RID solid_cell_dispatch_buffer; //buffer for indirect compute dispatch
|
||||
RID solid_cell_buffer;
|
||||
|
||||
RID lightprobe_history_tex;
|
||||
RID lightprobe_average_tex;
|
||||
|
||||
float cell_size;
|
||||
Vector3i position;
|
||||
|
||||
static const Vector3i DIRTY_ALL;
|
||||
Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all.
|
||||
|
||||
RID sdf_store_uniform_set;
|
||||
RID sdf_direct_light_uniform_set;
|
||||
RID scroll_uniform_set;
|
||||
RID scroll_occlusion_uniform_set;
|
||||
RID integrate_uniform_set;
|
||||
RID lights_buffer;
|
||||
};
|
||||
|
||||
//used for rendering (voxelization)
|
||||
RID render_albedo;
|
||||
RID render_emission;
|
||||
RID render_emission_aniso;
|
||||
RID render_occlusion[8];
|
||||
RID render_geom_facing;
|
||||
|
||||
RID render_sdf[2];
|
||||
RID render_sdf_half[2];
|
||||
|
||||
//used for ping pong processing in cascades
|
||||
RID sdf_initialize_uniform_set;
|
||||
RID sdf_initialize_half_uniform_set;
|
||||
RID jump_flood_uniform_set[2];
|
||||
RID jump_flood_half_uniform_set[2];
|
||||
RID sdf_upscale_uniform_set;
|
||||
int upscale_jfa_uniform_set_index;
|
||||
RID occlusion_uniform_set;
|
||||
|
||||
uint32_t cascade_size = 128;
|
||||
|
||||
LocalVector<Cascade> cascades;
|
||||
|
||||
RID lightprobe_texture;
|
||||
RID lightprobe_data;
|
||||
RID occlusion_texture;
|
||||
RID occlusion_data;
|
||||
|
||||
RID lightprobe_history_scroll; //used for scrolling lightprobes
|
||||
RID lightprobe_average_scroll; //used for scrolling lightprobes
|
||||
|
||||
uint32_t history_size = 0;
|
||||
float solid_cell_ratio = 0;
|
||||
uint32_t solid_cell_count = 0;
|
||||
|
||||
RS::EnvironmentSDFGICascades cascade_mode;
|
||||
float min_cell_size = 0;
|
||||
uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints
|
||||
|
||||
RID debug_uniform_set;
|
||||
RID debug_probes_uniform_set;
|
||||
RID cascades_ubo;
|
||||
|
||||
bool uses_occlusion = false;
|
||||
bool uses_multibounce = false;
|
||||
bool reads_sky = false;
|
||||
float energy = 1.0;
|
||||
float normal_bias = 1.1;
|
||||
float probe_bias = 1.1;
|
||||
RS::EnvironmentSDFGIYScale y_scale_mode = RS::ENV_SDFGI_Y_SCALE_DISABLED;
|
||||
|
||||
float y_mult = 1.0;
|
||||
|
||||
uint32_t render_pass = 0;
|
||||
};
|
||||
|
||||
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
|
||||
RS::EnvironmentSDFGIFramesToConverge sdfgi_frames_to_converge = RS::ENV_SDFGI_CONVERGE_IN_10_FRAMES;
|
||||
float sdfgi_solid_cell_ratio = 0.25;
|
||||
Vector3 sdfgi_debug_probe_pos;
|
||||
Vector3 sdfgi_debug_probe_dir;
|
||||
bool sdfgi_debug_probe_enabled = false;
|
||||
Vector3i sdfgi_debug_probe_index;
|
||||
|
||||
struct SDGIShader {
|
||||
enum SDFGIPreprocessShaderVersion {
|
||||
PRE_PROCESS_SCROLL,
|
||||
PRE_PROCESS_SCROLL_OCCLUSION,
|
||||
PRE_PROCESS_JUMP_FLOOD_INITIALIZE,
|
||||
PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF,
|
||||
PRE_PROCESS_JUMP_FLOOD,
|
||||
PRE_PROCESS_JUMP_FLOOD_OPTIMIZED,
|
||||
PRE_PROCESS_JUMP_FLOOD_UPSCALE,
|
||||
PRE_PROCESS_OCCLUSION,
|
||||
PRE_PROCESS_STORE,
|
||||
PRE_PROCESS_MAX
|
||||
};
|
||||
|
||||
struct PreprocessPushConstant {
|
||||
int32_t scroll[3];
|
||||
int32_t grid_size;
|
||||
|
||||
int32_t probe_offset[3];
|
||||
int32_t step_size;
|
||||
|
||||
int32_t half_size;
|
||||
uint32_t occlusion_index;
|
||||
int32_t cascade;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
SdfgiPreprocessShaderRD preprocess;
|
||||
RID preprocess_shader;
|
||||
RID preprocess_pipeline[PRE_PROCESS_MAX];
|
||||
|
||||
struct DebugPushConstant {
|
||||
float grid_size[3];
|
||||
uint32_t max_cascades;
|
||||
|
||||
int32_t screen_size[2];
|
||||
uint32_t use_occlusion;
|
||||
float y_mult;
|
||||
|
||||
float cam_extent[3];
|
||||
uint32_t probe_axis_size;
|
||||
|
||||
float cam_transform[16];
|
||||
};
|
||||
|
||||
SdfgiDebugShaderRD debug;
|
||||
RID debug_shader;
|
||||
RID debug_shader_version;
|
||||
RID debug_pipeline;
|
||||
|
||||
enum ProbeDebugMode {
|
||||
PROBE_DEBUG_PROBES,
|
||||
PROBE_DEBUG_VISIBILITY,
|
||||
PROBE_DEBUG_MAX
|
||||
};
|
||||
|
||||
struct DebugProbesPushConstant {
|
||||
float projection[16];
|
||||
|
||||
uint32_t band_power;
|
||||
uint32_t sections_in_band;
|
||||
uint32_t band_mask;
|
||||
float section_arc;
|
||||
|
||||
float grid_size[3];
|
||||
uint32_t cascade;
|
||||
|
||||
uint32_t pad;
|
||||
float y_mult;
|
||||
int32_t probe_debug_index;
|
||||
int32_t probe_axis_size;
|
||||
};
|
||||
|
||||
SdfgiDebugProbesShaderRD debug_probes;
|
||||
RID debug_probes_shader;
|
||||
RID debug_probes_shader_version;
|
||||
|
||||
RenderPipelineVertexFormatCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX];
|
||||
|
||||
struct Light {
|
||||
float color[3];
|
||||
float energy;
|
||||
|
||||
float direction[3];
|
||||
uint32_t has_shadow;
|
||||
|
||||
float position[3];
|
||||
float attenuation;
|
||||
|
||||
uint32_t type;
|
||||
float spot_angle;
|
||||
float spot_attenuation;
|
||||
float radius;
|
||||
|
||||
float shadow_color[4];
|
||||
};
|
||||
|
||||
struct DirectLightPushConstant {
|
||||
float grid_size[3];
|
||||
uint32_t max_cascades;
|
||||
|
||||
uint32_t cascade;
|
||||
uint32_t light_count;
|
||||
uint32_t process_offset;
|
||||
uint32_t process_increment;
|
||||
|
||||
int32_t probe_axis_size;
|
||||
uint32_t multibounce;
|
||||
float y_mult;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
enum {
|
||||
DIRECT_LIGHT_MODE_STATIC,
|
||||
DIRECT_LIGHT_MODE_DYNAMIC,
|
||||
DIRECT_LIGHT_MODE_MAX
|
||||
};
|
||||
SdfgiDirectLightShaderRD direct_light;
|
||||
RID direct_light_shader;
|
||||
RID direct_light_pipeline[DIRECT_LIGHT_MODE_MAX];
|
||||
|
||||
enum {
|
||||
INTEGRATE_MODE_PROCESS,
|
||||
INTEGRATE_MODE_STORE,
|
||||
INTEGRATE_MODE_SCROLL,
|
||||
INTEGRATE_MODE_SCROLL_STORE,
|
||||
INTEGRATE_MODE_MAX
|
||||
};
|
||||
struct IntegratePushConstant {
|
||||
enum {
|
||||
SKY_MODE_DISABLED,
|
||||
SKY_MODE_COLOR,
|
||||
SKY_MODE_SKY,
|
||||
};
|
||||
|
||||
float grid_size[3];
|
||||
uint32_t max_cascades;
|
||||
|
||||
uint32_t probe_axis_size;
|
||||
uint32_t cascade;
|
||||
uint32_t history_index;
|
||||
uint32_t history_size;
|
||||
|
||||
uint32_t ray_count;
|
||||
float ray_bias;
|
||||
int32_t image_size[2];
|
||||
|
||||
int32_t world_offset[3];
|
||||
uint32_t sky_mode;
|
||||
|
||||
int32_t scroll[3];
|
||||
float sky_energy;
|
||||
|
||||
float sky_color[3];
|
||||
float y_mult;
|
||||
};
|
||||
|
||||
SdfgiIntegrateShaderRD integrate;
|
||||
RID integrate_shader;
|
||||
RID integrate_pipeline[INTEGRATE_MODE_MAX];
|
||||
|
||||
RID integrate_default_sky_uniform_set;
|
||||
|
||||
} sdfgi_shader;
|
||||
|
||||
void _sdfgi_erase(RenderBuffers *rb);
|
||||
int _sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
|
||||
void _sdfgi_update_cascades(RID p_render_buffers);
|
||||
|
||||
/* GI */
|
||||
|
||||
struct GI {
|
||||
struct SDFGIData {
|
||||
float grid_size[3];
|
||||
uint32_t max_cascades;
|
||||
|
||||
uint32_t use_occlusion;
|
||||
int32_t probe_axis_size;
|
||||
float probe_to_uvw;
|
||||
float normal_bias;
|
||||
|
||||
float lightprobe_tex_pixel_size[3];
|
||||
float energy;
|
||||
|
||||
float lightprobe_uv_offset[3];
|
||||
float y_mult;
|
||||
|
||||
float occlusion_clamp[3];
|
||||
uint32_t pad3;
|
||||
|
||||
float occlusion_renormalize[3];
|
||||
uint32_t pad4;
|
||||
|
||||
float cascade_probe_size[3];
|
||||
uint32_t pad5;
|
||||
|
||||
struct ProbeCascadeData {
|
||||
float position[3]; //offset of (0,0,0) in world coordinates
|
||||
float to_probe; // 1/bounds * grid_size
|
||||
int32_t probe_world_offset[3];
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
};
|
||||
|
||||
ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
|
||||
};
|
||||
|
||||
struct GIProbeData {
|
||||
float xform[16];
|
||||
float bounds[3];
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
uint32_t blend_ambient;
|
||||
uint32_t texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ao;
|
||||
float ao_size;
|
||||
uint32_t pad[1];
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
int32_t screen_size[2];
|
||||
float z_near;
|
||||
float z_far;
|
||||
|
||||
float proj_info[4];
|
||||
|
||||
uint32_t max_giprobes;
|
||||
uint32_t high_quality_vct;
|
||||
uint32_t use_sdfgi;
|
||||
uint32_t orthogonal;
|
||||
|
||||
float ao_color[3];
|
||||
uint32_t pad;
|
||||
|
||||
float cam_rotation[12];
|
||||
};
|
||||
|
||||
RID sdfgi_ubo;
|
||||
enum {
|
||||
MODE_MAX = 1
|
||||
};
|
||||
|
||||
GiShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[MODE_MAX];
|
||||
} gi;
|
||||
|
||||
bool screen_space_roughness_limiter = false;
|
||||
float screen_space_roughness_limiter_curve = 1.0;
|
||||
float screen_space_roughness_limiter_amount = 0.25;
|
||||
float screen_space_roughness_limiter_limit = 0.18;
|
||||
|
||||
mutable RID_Owner<RenderBuffers> render_buffers_owner;
|
||||
|
||||
|
@ -777,10 +1179,16 @@ private:
|
|||
|
||||
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas);
|
||||
void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection);
|
||||
void _sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform);
|
||||
|
||||
uint64_t scene_pass = 0;
|
||||
uint64_t shadow_atlas_realloc_tolerance_msec = 500;
|
||||
|
||||
struct SDFGICosineNeighbour {
|
||||
uint32_t neighbour;
|
||||
float weight;
|
||||
};
|
||||
|
||||
public:
|
||||
/* SHADOW ATLAS API */
|
||||
|
||||
|
@ -818,6 +1226,15 @@ public:
|
|||
return Size2i(directional_shadow.size, directional_shadow.size);
|
||||
}
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
|
||||
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position);
|
||||
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
|
||||
virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
|
||||
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
|
||||
/* SKY API */
|
||||
|
||||
RID sky_create();
|
||||
|
@ -871,6 +1288,11 @@ public:
|
|||
float environment_get_ssao_ao_affect(RID p_env) const;
|
||||
float environment_get_ssao_light_affect(RID p_env) const;
|
||||
bool environment_is_ssr_enabled(RID p_env) const;
|
||||
bool environment_is_sdfgi_enabled(RID p_env) const;
|
||||
|
||||
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, bool p_enhance_ssr, float p_energy, float p_normal_bias, float p_probe_bias);
|
||||
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
|
||||
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
|
||||
|
||||
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
|
||||
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
|
||||
|
@ -894,6 +1316,7 @@ public:
|
|||
|
||||
RID light_instance_create(RID p_light);
|
||||
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
|
||||
void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb);
|
||||
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_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2());
|
||||
void light_instance_mark_visible(RID p_light_instance);
|
||||
|
||||
|
@ -1107,6 +1530,8 @@ public:
|
|||
bool gi_probe_needs_update(RID p_probe) const;
|
||||
void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects);
|
||||
|
||||
void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
|
||||
|
||||
_FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) {
|
||||
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
|
||||
return gi_probe->slot;
|
||||
|
@ -1124,10 +1549,6 @@ public:
|
|||
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
|
||||
return gi_probe->texture;
|
||||
}
|
||||
_FORCE_INLINE_ RID gi_probe_instance_get_aniso_texture(RID p_probe, int p_index) {
|
||||
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
|
||||
return gi_probe->anisotropy[p_index];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
|
||||
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance);
|
||||
|
@ -1141,7 +1562,7 @@ public:
|
|||
|
||||
return gi_probe->render_index;
|
||||
}
|
||||
|
||||
/*
|
||||
_FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
|
||||
GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!g_probe);
|
||||
|
@ -1154,18 +1575,27 @@ public:
|
|||
|
||||
return g_probe->last_pass;
|
||||
}
|
||||
|
||||
const Vector<RID> &gi_probe_get_slots() const;
|
||||
_FORCE_INLINE_ bool gi_probe_is_anisotropic() const {
|
||||
return gi_probe_use_anisotropy;
|
||||
}
|
||||
GIProbeQuality gi_probe_get_quality() const;
|
||||
|
||||
*/
|
||||
RID render_buffers_create();
|
||||
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa);
|
||||
|
||||
RID render_buffers_get_ao_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_gi_probe_buffer(RID p_render_buffers);
|
||||
RID render_buffers_get_default_gi_probe_buffer();
|
||||
|
||||
uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
|
||||
bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
|
||||
RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const;
|
||||
Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const;
|
||||
uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const;
|
||||
uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const;
|
||||
bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const;
|
||||
float render_buffers_get_sdfgi_energy(RID p_render_buffers) const;
|
||||
RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const;
|
||||
|
||||
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_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
|
||||
|
@ -1173,6 +1603,9 @@ public:
|
|||
|
||||
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
|
||||
void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count);
|
||||
void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count);
|
||||
|
||||
virtual void set_scene_pass(uint64_t p_pass) {
|
||||
scene_pass = p_pass;
|
||||
}
|
||||
|
@ -1180,9 +1613,10 @@ public:
|
|||
return scene_pass;
|
||||
}
|
||||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit);
|
||||
virtual bool screen_space_roughness_limiter_is_active() const;
|
||||
virtual float screen_space_roughness_limiter_get_curve() const;
|
||||
virtual float screen_space_roughness_limiter_get_amount() const;
|
||||
virtual float screen_space_roughness_limiter_get_limit() const;
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality);
|
||||
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
|
||||
|
@ -1221,6 +1655,8 @@ public:
|
|||
|
||||
virtual void set_time(double p_time, double p_step);
|
||||
|
||||
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
|
||||
|
||||
RasterizerSceneRD(RasterizerStorageRD *p_storage);
|
||||
~RasterizerSceneRD();
|
||||
};
|
||||
|
|
|
@ -3387,11 +3387,21 @@ void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_e
|
|||
light->instance_dependency.instance_notify_changed(true, false);
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) {
|
||||
void RasterizerStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
|
||||
Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND(!light);
|
||||
|
||||
light->use_gi = p_enabled;
|
||||
light->bake_mode = p_bake_mode;
|
||||
|
||||
light->version++;
|
||||
light->instance_dependency.instance_notify_changed(true, false);
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
|
||||
Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND(!light);
|
||||
|
||||
light->max_sdfgi_cascade = p_cascade;
|
||||
|
||||
light->version++;
|
||||
light->instance_dependency.instance_notify_changed(true, false);
|
||||
|
@ -3460,11 +3470,18 @@ RS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_
|
|||
return light->directional_range_mode;
|
||||
}
|
||||
|
||||
bool RasterizerStorageRD::light_get_use_gi(RID p_light) {
|
||||
Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, false);
|
||||
uint32_t RasterizerStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, 0);
|
||||
|
||||
return light->use_gi;
|
||||
return light->max_sdfgi_cascade;
|
||||
}
|
||||
|
||||
RS::LightBakeMode RasterizerStorageRD::light_get_bake_mode(RID p_light) {
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
|
||||
|
||||
return light->bake_mode;
|
||||
}
|
||||
|
||||
uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
|
||||
|
@ -3517,25 +3534,25 @@ void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_in
|
|||
reflection_probe->intensity = p_intensity;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
|
||||
void RasterizerStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient = p_ambient;
|
||||
reflection_probe->ambient_mode = p_mode;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
|
||||
void RasterizerStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient_energy = p_energy;
|
||||
reflection_probe->ambient_color = p_color;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
|
||||
void RasterizerStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient_probe_contrib = p_contrib;
|
||||
reflection_probe->ambient_color_energy = p_energy;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
|
||||
|
@ -3683,25 +3700,23 @@ bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const
|
|||
return reflection_probe->box_projection;
|
||||
}
|
||||
|
||||
Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const {
|
||||
RS::ReflectionProbeAmbientMode RasterizerStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
|
||||
return reflection_probe->ambient_mode;
|
||||
}
|
||||
|
||||
Color RasterizerStorageRD::reflection_probe_get_ambient_color(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, Color());
|
||||
|
||||
return reflection_probe->interior_ambient;
|
||||
return reflection_probe->ambient_color;
|
||||
}
|
||||
|
||||
float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const {
|
||||
float RasterizerStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->interior_ambient_energy;
|
||||
}
|
||||
|
||||
float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->interior_ambient_probe_contrib;
|
||||
return reflection_probe->ambient_color_energy;
|
||||
}
|
||||
|
||||
RID RasterizerStorageRD::decal_create() {
|
||||
|
@ -5878,6 +5893,20 @@ RasterizerStorageRD::RasterizerStorageRD() {
|
|||
}
|
||||
|
||||
default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
{
|
||||
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
|
||||
Vector<Vector<uint8_t>> vpv;
|
||||
vpv.push_back(pv);
|
||||
default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||
}
|
||||
}
|
||||
|
||||
{ //create default cubemap
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
|
||||
DEFAULT_RD_TEXTURE_3D_WHITE,
|
||||
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
|
||||
DEFAULT_RD_TEXTURE_2D_UINT,
|
||||
DEFAULT_RD_TEXTURE_MAX
|
||||
};
|
||||
|
||||
|
@ -420,7 +421,8 @@ private:
|
|||
bool shadow = false;
|
||||
bool negative = false;
|
||||
bool reverse_cull = false;
|
||||
bool use_gi = true;
|
||||
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
|
||||
uint32_t max_sdfgi_cascade = 2;
|
||||
uint32_t cull_mask = 0xFFFFFFFF;
|
||||
RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
|
||||
RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
|
||||
|
@ -439,9 +441,9 @@ private:
|
|||
RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
|
||||
int resolution = 256;
|
||||
float intensity = 1.0;
|
||||
Color interior_ambient;
|
||||
float interior_ambient_energy = 1.0;
|
||||
float interior_ambient_probe_contrib = 0.0;
|
||||
RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
|
||||
Color ambient_color;
|
||||
float ambient_color_energy = 1.0;
|
||||
float max_distance = 0;
|
||||
Vector3 extents = Vector3(1, 1, 1);
|
||||
Vector3 origin_offset;
|
||||
|
@ -1041,7 +1043,8 @@ public:
|
|||
void light_set_negative(RID p_light, bool p_enable);
|
||||
void light_set_cull_mask(RID p_light, uint32_t p_mask);
|
||||
void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
|
||||
void light_set_use_gi(RID p_light, bool p_enabled);
|
||||
void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode);
|
||||
void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade);
|
||||
|
||||
void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode);
|
||||
|
||||
|
@ -1118,7 +1121,8 @@ public:
|
|||
return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
|
||||
}
|
||||
|
||||
bool light_get_use_gi(RID p_light);
|
||||
RS::LightBakeMode light_get_bake_mode(RID p_light);
|
||||
uint32_t light_get_max_sdfgi_cascade(RID p_light);
|
||||
uint64_t light_get_version(RID p_light) const;
|
||||
|
||||
/* PROBE API */
|
||||
|
@ -1127,9 +1131,9 @@ public:
|
|||
|
||||
void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
|
||||
void reflection_probe_set_intensity(RID p_probe, float p_intensity);
|
||||
void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient);
|
||||
void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy);
|
||||
void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib);
|
||||
void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode);
|
||||
void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color);
|
||||
void reflection_probe_set_ambient_energy(RID p_probe, float p_energy);
|
||||
void reflection_probe_set_max_distance(RID p_probe, float p_distance);
|
||||
void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
|
||||
void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
|
||||
|
@ -1151,9 +1155,9 @@ public:
|
|||
float reflection_probe_get_intensity(RID p_probe) const;
|
||||
bool reflection_probe_is_interior(RID p_probe) const;
|
||||
bool reflection_probe_is_box_projection(RID p_probe) const;
|
||||
Color reflection_probe_get_interior_ambient(RID p_probe) const;
|
||||
float reflection_probe_get_interior_ambient_energy(RID p_probe) const;
|
||||
float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const;
|
||||
RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
|
||||
Color reflection_probe_get_ambient_color(RID p_probe) const;
|
||||
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
|
||||
|
||||
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
|
||||
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
||||
|
|
|
@ -28,3 +28,10 @@ if "RD_GLSL" in env["BUILDERS"]:
|
|||
env.RD_GLSL("screen_space_reflection_scale.glsl")
|
||||
env.RD_GLSL("subsurface_scattering.glsl")
|
||||
env.RD_GLSL("specular_merge.glsl")
|
||||
env.RD_GLSL("gi.glsl")
|
||||
env.RD_GLSL("resolve.glsl")
|
||||
env.RD_GLSL("sdfgi_preprocess.glsl")
|
||||
env.RD_GLSL("sdfgi_integrate.glsl")
|
||||
env.RD_GLSL("sdfgi_direct_light.glsl")
|
||||
env.RD_GLSL("sdfgi_debug.glsl")
|
||||
env.RD_GLSL("sdfgi_debug_probes.glsl")
|
||||
|
|
|
@ -47,16 +47,26 @@ layout(push_constant, binding = 1, std430) uniform Params {
|
|||
|
||||
bool force_luminance;
|
||||
bool alpha_to_zero;
|
||||
uint pad[2];
|
||||
bool srgb;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
|
||||
#ifdef MODE_TWO_SOURCES
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_color2;
|
||||
#endif
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
//if going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = uv_interp;
|
||||
|
||||
|
@ -89,11 +99,17 @@ void main() {
|
|||
}
|
||||
#endif
|
||||
vec4 color = textureLod(source_color, uv, 0.0);
|
||||
#ifdef MODE_TWO_SOURCES
|
||||
color += textureLod(source_color2, uv, 0.0);
|
||||
#endif
|
||||
if (params.force_luminance) {
|
||||
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
||||
}
|
||||
if (params.alpha_to_zero) {
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
if (params.srgb) {
|
||||
color.rgb = linear_to_srgb(color.rgb);
|
||||
}
|
||||
frag_color = color;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,663 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
#define M_PI 3.141592
|
||||
|
||||
#define SDFGI_MAX_CASCADES 8
|
||||
|
||||
//set 0 for SDFGI and render buffers
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture3D sdf_cascades[SDFGI_MAX_CASCADES];
|
||||
layout(set = 0, binding = 2) uniform texture3D light_cascades[SDFGI_MAX_CASCADES];
|
||||
layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[SDFGI_MAX_CASCADES];
|
||||
layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[SDFGI_MAX_CASCADES];
|
||||
layout(set = 0, binding = 5) uniform texture3D occlusion_texture;
|
||||
|
||||
layout(set = 0, binding = 6) uniform sampler linear_sampler;
|
||||
layout(set = 0, binding = 7) uniform sampler linear_sampler_with_mipmaps;
|
||||
|
||||
struct ProbeCascadeData {
|
||||
vec3 position;
|
||||
float to_probe;
|
||||
ivec3 probe_world_offset;
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
};
|
||||
|
||||
layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer;
|
||||
layout(rgba16f, set = 0, binding = 10) uniform restrict writeonly image2D reflection_buffer;
|
||||
|
||||
layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture;
|
||||
|
||||
layout(set = 0, binding = 12) uniform texture2D depth_buffer;
|
||||
layout(set = 0, binding = 13) uniform texture2D normal_roughness_buffer;
|
||||
layout(set = 0, binding = 14) uniform utexture2D giprobe_buffer;
|
||||
|
||||
layout(set = 0, binding = 15, std140) uniform SDFGI {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
bool use_occlusion;
|
||||
int probe_axis_size;
|
||||
float probe_to_uvw;
|
||||
float normal_bias;
|
||||
|
||||
vec3 lightprobe_tex_pixel_size;
|
||||
float energy;
|
||||
|
||||
vec3 lightprobe_uv_offset;
|
||||
float y_mult;
|
||||
|
||||
vec3 occlusion_clamp;
|
||||
uint pad3;
|
||||
|
||||
vec3 occlusion_renormalize;
|
||||
uint pad4;
|
||||
|
||||
vec3 cascade_probe_size;
|
||||
uint pad5;
|
||||
|
||||
ProbeCascadeData cascades[SDFGI_MAX_CASCADES];
|
||||
}
|
||||
sdfgi;
|
||||
|
||||
#define MAX_GI_PROBES 8
|
||||
|
||||
struct GIProbeData {
|
||||
mat4 xform;
|
||||
vec3 bounds;
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
bool blend_ambient;
|
||||
uint texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ambient_occlusion;
|
||||
float ambient_occlusion_size;
|
||||
uint pad2;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 16, std140) uniform GIProbes {
|
||||
GIProbeData data[MAX_GI_PROBES];
|
||||
}
|
||||
gi_probes;
|
||||
|
||||
layout(set = 0, binding = 17) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
ivec2 screen_size;
|
||||
float z_near;
|
||||
float z_far;
|
||||
|
||||
vec4 proj_info;
|
||||
|
||||
uint max_giprobes;
|
||||
bool high_quality_vct;
|
||||
bool use_sdfgi;
|
||||
bool orthogonal;
|
||||
|
||||
vec3 ao_color;
|
||||
uint pad;
|
||||
|
||||
mat3x4 cam_rotation;
|
||||
}
|
||||
params;
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
vec4 blend_color(vec4 src, vec4 dst) {
|
||||
vec4 res;
|
||||
float sa = 1.0 - src.a;
|
||||
res.a = dst.a * sa + src.a;
|
||||
if (res.a == 0.0) {
|
||||
res.rgb = vec3(0);
|
||||
} else {
|
||||
res.rgb = (dst.rgb * dst.a * sa + src.rgb * src.a) / res.a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vec3 reconstruct_position(ivec2 screen_pos) {
|
||||
vec3 pos;
|
||||
pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
|
||||
|
||||
pos.z = pos.z * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
|
||||
}
|
||||
pos.z = -pos.z;
|
||||
|
||||
pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw;
|
||||
if (!params.orthogonal) {
|
||||
pos.xy *= pos.z;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void sdfgi_probe_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
|
||||
cascade_pos += cam_normal * sdfgi.normal_bias;
|
||||
|
||||
vec3 base_pos = floor(cascade_pos);
|
||||
//cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal;
|
||||
ivec3 probe_base_pos = ivec3(base_pos);
|
||||
|
||||
vec4 diffuse_accum = vec4(0.0);
|
||||
vec3 specular_accum;
|
||||
|
||||
ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade));
|
||||
tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
|
||||
tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1);
|
||||
|
||||
vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
|
||||
vec3 specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
|
||||
specular_accum = vec3(0.0);
|
||||
|
||||
vec4 light_accum = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
|
||||
ivec3 probe_posi = probe_base_pos;
|
||||
probe_posi += offset;
|
||||
|
||||
// Compute weight
|
||||
|
||||
vec3 probe_pos = vec3(probe_posi);
|
||||
vec3 probe_to_pos = cascade_pos - probe_pos;
|
||||
vec3 probe_dir = normalize(-probe_to_pos);
|
||||
|
||||
vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
|
||||
float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir));
|
||||
|
||||
// Compute lightprobe occlusion
|
||||
|
||||
if (sdfgi.use_occlusion) {
|
||||
ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
|
||||
vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
|
||||
|
||||
vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
|
||||
occ_pos.z += float(cascade);
|
||||
if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
|
||||
occ_pos.x += 1.0;
|
||||
}
|
||||
|
||||
occ_pos *= sdfgi.occlusion_renormalize;
|
||||
float occlusion = dot(textureLod(sampler3D(occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
|
||||
|
||||
weight *= max(occlusion, 0.01);
|
||||
}
|
||||
|
||||
// Compute lightprobe texture position
|
||||
|
||||
vec3 diffuse;
|
||||
vec3 pos_uvw = diffuse_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
|
||||
|
||||
diffuse_accum += vec4(diffuse * weight, weight);
|
||||
|
||||
{
|
||||
vec3 specular = vec3(0.0);
|
||||
vec3 pos_uvw = specular_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
if (roughness < 0.99) {
|
||||
specular = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb;
|
||||
}
|
||||
if (roughness > 0.2) {
|
||||
specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25);
|
||||
}
|
||||
|
||||
specular_accum += specular * weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
diffuse_accum.rgb /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
diffuse_light = diffuse_accum.rgb;
|
||||
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
specular_accum /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
specular_light = specular_accum;
|
||||
}
|
||||
|
||||
void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, out vec4 ambient_light, out vec4 reflection_light) {
|
||||
//make vertex orientation the world one, but still align to camera
|
||||
vertex.y *= sdfgi.y_mult;
|
||||
normal.y *= sdfgi.y_mult;
|
||||
reflection.y *= sdfgi.y_mult;
|
||||
|
||||
//renormalize
|
||||
normal = normalize(normal);
|
||||
reflection = normalize(reflection);
|
||||
|
||||
vec3 cam_pos = vertex;
|
||||
vec3 cam_normal = normal;
|
||||
|
||||
vec4 light_accum = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
|
||||
vec4 light_blend_accum = vec4(0.0);
|
||||
float weight_blend_accum = 0.0;
|
||||
|
||||
float blend = -1.0;
|
||||
|
||||
// helper constants, compute once
|
||||
|
||||
uint cascade = 0xFFFFFFFF;
|
||||
vec3 cascade_pos;
|
||||
vec3 cascade_normal;
|
||||
|
||||
for (uint i = 0; i < sdfgi.max_cascades; i++) {
|
||||
cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
|
||||
|
||||
if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
|
||||
continue; //skip cascade
|
||||
}
|
||||
|
||||
cascade = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cascade < SDFGI_MAX_CASCADES) {
|
||||
ambient_light = vec4(0, 0, 0, 1);
|
||||
reflection_light = vec4(0, 0, 0, 1);
|
||||
|
||||
float blend;
|
||||
vec3 diffuse, specular;
|
||||
sdfgi_probe_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular);
|
||||
|
||||
{
|
||||
//process blend
|
||||
float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5;
|
||||
float blend_to = blend_from + 2.0;
|
||||
|
||||
vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe;
|
||||
|
||||
float len = length(inner_pos);
|
||||
|
||||
inner_pos = abs(normalize(inner_pos));
|
||||
len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
if (len >= blend_from) {
|
||||
blend = smoothstep(blend_from, blend_to, len);
|
||||
} else {
|
||||
blend = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (blend > 0.0) {
|
||||
//blend
|
||||
if (cascade == sdfgi.max_cascades - 1) {
|
||||
ambient_light.a = 1.0 - blend;
|
||||
reflection_light.a = 1.0 - blend;
|
||||
|
||||
} else {
|
||||
vec3 diffuse2, specular2;
|
||||
cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe;
|
||||
sdfgi_probe_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2);
|
||||
diffuse = mix(diffuse, diffuse2, blend);
|
||||
specular = mix(specular, specular2, blend);
|
||||
}
|
||||
}
|
||||
|
||||
ambient_light.rgb = diffuse;
|
||||
#if 1
|
||||
if (roughness < 0.2) {
|
||||
vec3 pos_to_uvw = 1.0 / sdfgi.grid_size;
|
||||
vec4 light_accum = vec4(0.0);
|
||||
|
||||
float blend_size = (sdfgi.grid_size.x / float(sdfgi.probe_axis_size - 1)) * 0.5;
|
||||
|
||||
float radius_sizes[SDFGI_MAX_CASCADES];
|
||||
cascade = 0xFFFF;
|
||||
|
||||
float base_distance = length(cam_pos);
|
||||
for (uint i = 0; i < sdfgi.max_cascades; i++) {
|
||||
radius_sizes[i] = (1.0 / sdfgi.cascades[i].to_cell) * (sdfgi.grid_size.x * 0.5 - blend_size);
|
||||
if (cascade == 0xFFFF && base_distance < radius_sizes[i]) {
|
||||
cascade = i;
|
||||
}
|
||||
}
|
||||
|
||||
cascade = min(cascade, sdfgi.max_cascades - 1);
|
||||
|
||||
float max_distance = radius_sizes[sdfgi.max_cascades - 1];
|
||||
vec3 ray_pos = cam_pos;
|
||||
vec3 ray_dir = reflection;
|
||||
|
||||
{
|
||||
float prev_radius = cascade > 0 ? radius_sizes[cascade - 1] : 0.0;
|
||||
float base_blend = (base_distance - prev_radius) / (radius_sizes[cascade] - prev_radius);
|
||||
float bias = (1.0 + base_blend) * 1.1;
|
||||
vec3 abs_ray_dir = abs(ray_dir);
|
||||
//ray_pos += ray_dir * (bias / sdfgi.cascades[cascade].to_cell); //bias to avoid self occlusion
|
||||
ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell;
|
||||
}
|
||||
|
||||
float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade
|
||||
while (length(ray_pos) < max_distance) {
|
||||
for (uint i = 0; i < sdfgi.max_cascades; i++) {
|
||||
if (i >= cascade && length(ray_pos) < radius_sizes[i]) {
|
||||
cascade = max(i, cascade); //never go down
|
||||
|
||||
vec3 pos = ray_pos - sdfgi.cascades[i].position;
|
||||
pos *= sdfgi.cascades[i].to_cell * pos_to_uvw;
|
||||
|
||||
float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.1;
|
||||
|
||||
vec4 hit_light = vec4(0.0);
|
||||
if (distance < softness) {
|
||||
hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb;
|
||||
hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
|
||||
hit_light.a = clamp(1.0 - (distance / softness), 0.0, 1.0);
|
||||
hit_light.rgb *= hit_light.a;
|
||||
}
|
||||
|
||||
distance /= sdfgi.cascades[i].to_cell;
|
||||
|
||||
if (i < (sdfgi.max_cascades - 1)) {
|
||||
pos = ray_pos - sdfgi.cascades[i + 1].position;
|
||||
pos *= sdfgi.cascades[i + 1].to_cell * pos_to_uvw;
|
||||
|
||||
float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.1;
|
||||
|
||||
vec4 hit_light2 = vec4(0.0);
|
||||
if (distance2 < softness) {
|
||||
hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb;
|
||||
hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
|
||||
hit_light2.a = clamp(1.0 - (distance2 / softness), 0.0, 1.0);
|
||||
hit_light2.rgb *= hit_light2.a;
|
||||
}
|
||||
|
||||
float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1];
|
||||
float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0);
|
||||
|
||||
distance2 /= sdfgi.cascades[i + 1].to_cell;
|
||||
|
||||
hit_light = mix(hit_light, hit_light2, blend);
|
||||
distance = mix(distance, distance2, blend);
|
||||
}
|
||||
|
||||
light_accum += hit_light;
|
||||
ray_pos += ray_dir * distance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (light_accum.a > 0.99) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 light = light_accum.rgb / max(light_accum.a, 0.00001);
|
||||
float alpha = min(1.0, light_accum.a);
|
||||
|
||||
float b = min(1.0, roughness * 5.0);
|
||||
|
||||
float sa = 1.0 - b;
|
||||
|
||||
reflection_light.a = alpha * sa + b;
|
||||
if (reflection_light.a == 0) {
|
||||
specular = vec3(0.0);
|
||||
} else {
|
||||
specular = (light * alpha * sa + specular * b) / reflection_light.a;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
reflection_light.rgb = specular;
|
||||
|
||||
ambient_light.rgb *= sdfgi.energy;
|
||||
reflection_light.rgb *= sdfgi.energy;
|
||||
} else {
|
||||
ambient_light = vec4(0);
|
||||
reflection_light = vec4(0);
|
||||
}
|
||||
}
|
||||
|
||||
//standard voxel cone trace
|
||||
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
float half_diameter = diameter * 0.5;
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, log2(diameter));
|
||||
float a = (1.0 - color.a);
|
||||
color += a * scolor;
|
||||
dist += half_diameter;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
float radius = max(0.5, dist);
|
||||
float lod_level = log2(radius * 2.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, lod_level);
|
||||
lod_level += 1.0;
|
||||
|
||||
float a = (1.0 - color.a);
|
||||
scolor *= a;
|
||||
color += scolor;
|
||||
dist += radius;
|
||||
radius = max(0.5, dist);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) {
|
||||
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
|
||||
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
|
||||
normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
|
||||
|
||||
position += normal * gi_probes.data[index].normal_bias;
|
||||
|
||||
//this causes corrupted pixels, i have no idea why..
|
||||
if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat3 dir_xform = mat3(gi_probes.data[index].xform) * normal_xform;
|
||||
|
||||
vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
|
||||
float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
|
||||
//float blend=1.0;
|
||||
|
||||
float max_distance = length(gi_probes.data[index].bounds);
|
||||
vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
|
||||
|
||||
//irradiance
|
||||
|
||||
vec4 light = vec4(0.0);
|
||||
|
||||
if (params.high_quality_vct) {
|
||||
const uint cone_dir_count = 6;
|
||||
vec3 cone_dirs[cone_dir_count] = vec3[](
|
||||
vec3(0.0, 0.0, 1.0),
|
||||
vec3(0.866025, 0.0, 0.5),
|
||||
vec3(0.267617, 0.823639, 0.5),
|
||||
vec3(-0.700629, 0.509037, 0.5),
|
||||
vec3(-0.700629, -0.509037, 0.5),
|
||||
vec3(0.267617, -0.823639, 0.5));
|
||||
|
||||
float cone_weights[cone_dir_count] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
|
||||
float cone_angle_tan = 0.577;
|
||||
|
||||
for (uint i = 0; i < cone_dir_count; i++) {
|
||||
vec3 dir = normalize(dir_xform * cone_dirs[i]);
|
||||
light += cone_weights[i] * voxel_cone_trace(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
}
|
||||
} else {
|
||||
const uint cone_dir_count = 4;
|
||||
vec3 cone_dirs[cone_dir_count] = vec3[](
|
||||
vec3(0.707107, 0.0, 0.707107),
|
||||
vec3(0.0, 0.707107, 0.707107),
|
||||
vec3(-0.707107, 0.0, 0.707107),
|
||||
vec3(0.0, -0.707107, 0.707107));
|
||||
|
||||
float cone_weights[cone_dir_count] = float[](0.25, 0.25, 0.25, 0.25);
|
||||
for (int i = 0; i < cone_dir_count; i++) {
|
||||
vec3 dir = normalize(dir_xform * cone_dirs[i]);
|
||||
light += cone_weights[i] * voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, max_distance, gi_probes.data[index].bias);
|
||||
}
|
||||
}
|
||||
|
||||
if (gi_probes.data[index].ambient_occlusion > 0.001) {
|
||||
float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0;
|
||||
|
||||
float taps, blend;
|
||||
blend = modf(size, taps);
|
||||
float ao = 0.0;
|
||||
for (float i = 1.0; i <= taps; i++) {
|
||||
vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size;
|
||||
ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i;
|
||||
}
|
||||
|
||||
if (blend > 0.001) {
|
||||
vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size;
|
||||
ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend;
|
||||
}
|
||||
|
||||
ao = 1.0 - min(1.0, ao);
|
||||
|
||||
light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, gi_probes.data[index].ambient_occlusion));
|
||||
}
|
||||
|
||||
light.rgb *= gi_probes.data[index].dynamic_range;
|
||||
if (!gi_probes.data[index].blend_ambient) {
|
||||
light.a = 1.0;
|
||||
}
|
||||
|
||||
out_diff += light * blend;
|
||||
|
||||
//radiance
|
||||
vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
|
||||
irr_light.rgb *= gi_probes.data[index].dynamic_range;
|
||||
if (!gi_probes.data[index].blend_ambient) {
|
||||
irr_light.a = 1.0;
|
||||
}
|
||||
|
||||
out_spec += irr_light * blend;
|
||||
|
||||
out_blend += blend;
|
||||
}
|
||||
|
||||
vec4 fetch_normal_and_roughness(ivec2 pos) {
|
||||
vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0);
|
||||
|
||||
normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0);
|
||||
return normal_roughness;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Pixel being shaded
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 vertex = reconstruct_position(pos);
|
||||
vertex.y = -vertex.y;
|
||||
|
||||
vec4 normal_roughness = fetch_normal_and_roughness(pos);
|
||||
vec3 normal = normal_roughness.xyz;
|
||||
|
||||
vec4 ambient_light = vec4(0.0), reflection_light = vec4(0.0);
|
||||
|
||||
if (normal.length() > 0.5) {
|
||||
//valid normal, can do GI
|
||||
float roughness = normal_roughness.w;
|
||||
|
||||
vertex = mat3(params.cam_rotation) * vertex;
|
||||
normal = normalize(mat3(params.cam_rotation) * normal);
|
||||
|
||||
vec3 reflection = normalize(reflect(normalize(vertex), normal));
|
||||
|
||||
if (params.use_sdfgi) {
|
||||
sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light);
|
||||
}
|
||||
|
||||
if (params.max_giprobes > 0) {
|
||||
uvec2 giprobe_tex = texelFetch(usampler2D(giprobe_buffer, linear_sampler), pos, 0).rg;
|
||||
roughness *= roughness;
|
||||
//find arbitrary tangent and bitangent, then build a matrix
|
||||
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
|
||||
vec3 tangent = normalize(cross(v0, normal));
|
||||
vec3 bitangent = normalize(cross(tangent, normal));
|
||||
mat3 normal_mat = mat3(tangent, bitangent, normal);
|
||||
|
||||
vec4 amb_accum = vec4(0.0);
|
||||
vec4 spec_accum = vec4(0.0);
|
||||
float blend_accum = 0.0;
|
||||
|
||||
for (uint i = 0; i < params.max_giprobes; i++) {
|
||||
if (any(equal(uvec2(i), giprobe_tex))) {
|
||||
gi_probe_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum);
|
||||
}
|
||||
}
|
||||
if (blend_accum > 0.0) {
|
||||
amb_accum /= blend_accum;
|
||||
spec_accum /= blend_accum;
|
||||
}
|
||||
|
||||
if (params.use_sdfgi) {
|
||||
reflection_light = blend_color(spec_accum, reflection_light);
|
||||
ambient_light = blend_color(amb_accum, ambient_light);
|
||||
} else {
|
||||
reflection_light = spec_accum;
|
||||
ambient_light = amb_accum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(ambient_buffer, pos, ambient_light);
|
||||
imageStore(reflection_buffer, pos, reflection_light);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
#ifdef MODE_RESOLVE_GI
|
||||
layout(set = 0, binding = 0) uniform sampler2DMS source_depth;
|
||||
layout(set = 0, binding = 1) uniform sampler2DMS source_normal_roughness;
|
||||
|
||||
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_depth;
|
||||
layout(rgba8, set = 1, binding = 1) uniform restrict writeonly image2D dest_normal_roughness;
|
||||
|
||||
#ifdef GIPROBE_RESOLVE
|
||||
layout(set = 2, binding = 0) uniform usampler2DMS source_giprobe;
|
||||
layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_giprobe;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
layout(push_constant, binding = 16, std430) uniform Params {
|
||||
ivec2 screen_size;
|
||||
int sample_count;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
// Pixel being shaded
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MODE_RESOLVE_GI
|
||||
|
||||
float best_depth = 1e20;
|
||||
vec4 best_normal_roughness = vec4(0.0);
|
||||
#ifdef GIPROBE_RESOLVE
|
||||
uvec2 best_giprobe;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
for(int i=0;i<params.sample_count;i++) {
|
||||
float depth = texelFetch(source_depth,pos,i).r;
|
||||
if (depth < best_depth) { //use the depth closest to camera
|
||||
best_depth = depth;
|
||||
best_normal_roughness = texelFetch(source_normal_roughness,pos,i);
|
||||
|
||||
#ifdef GIPROBE_RESOLVE
|
||||
best_giprobe = texelFetch(source_giprobe,pos,i).rg;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
float depths[16];
|
||||
int depth_indices[16];
|
||||
int depth_amount[16];
|
||||
int depth_count = 0;
|
||||
|
||||
for (int i = 0; i < params.sample_count; i++) {
|
||||
float depth = texelFetch(source_depth, pos, i).r;
|
||||
int depth_index = -1;
|
||||
for (int j = 0; j < depth_count; j++) {
|
||||
if (abs(depths[j] - depth) < 0.000001) {
|
||||
depth_index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_index == -1) {
|
||||
depths[depth_count] = depth;
|
||||
depth_indices[depth_count] = i;
|
||||
depth_amount[depth_count] = 1;
|
||||
depth_count += 1;
|
||||
} else {
|
||||
depth_amount[depth_index] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int depth_least = 0xFFFF;
|
||||
int best_index = 0;
|
||||
for (int j = 0; j < depth_count; j++) {
|
||||
if (depth_amount[j] < depth_least) {
|
||||
best_index = depth_indices[j];
|
||||
depth_least = depth_amount[j];
|
||||
}
|
||||
}
|
||||
|
||||
best_depth = texelFetch(source_depth, pos, best_index).r;
|
||||
best_normal_roughness = texelFetch(source_normal_roughness, pos, best_index);
|
||||
#ifdef GIPROBE_RESOLVE
|
||||
best_giprobe = texelFetch(source_giprobe, pos, best_index).rg;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
imageStore(dest_depth, pos, vec4(best_depth));
|
||||
imageStore(dest_normal_roughness, pos, vec4(best_normal_roughness));
|
||||
#ifdef GIPROBE_RESOLVE
|
||||
imageStore(dest_giprobe, pos, uvec4(best_giprobe, 0, 0));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
|
@ -258,7 +258,6 @@ VERTEX_SHADER_CODE
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_MATERIAL
|
||||
if (scene_data.material_uv2_mode) {
|
||||
gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0;
|
||||
|
@ -341,11 +340,13 @@ layout(location = 4) out float depth_output_buffer;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_NORMAL
|
||||
layout(location = 0) out vec4 normal_output_buffer;
|
||||
#ifdef MODE_RENDER_ROUGHNESS
|
||||
layout(location = 1) out float roughness_output_buffer;
|
||||
#endif //MODE_RENDER_ROUGHNESS
|
||||
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
|
||||
layout(location = 0) out vec4 normal_roughness_output_buffer;
|
||||
|
||||
#ifdef MODE_RENDER_GIPROBE
|
||||
layout(location = 1) out uvec2 giprobe_buffer;
|
||||
#endif
|
||||
|
||||
#endif //MODE_RENDER_NORMAL
|
||||
#else // RENDER DEPTH
|
||||
|
||||
|
@ -1321,37 +1322,39 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
|
|||
reflection_accum += reflection;
|
||||
}
|
||||
|
||||
#if !defined(USE_LIGHTMAP) && !defined(USE_VOXEL_CONE_TRACING)
|
||||
if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
|
||||
switch (reflections.data[ref_index].ambient_mode) {
|
||||
case REFLECTION_AMBIENT_DISABLED: {
|
||||
//do nothing
|
||||
} break;
|
||||
case REFLECTION_AMBIENT_ENVIRONMENT: {
|
||||
//do nothing
|
||||
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
||||
|
||||
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
||||
vec4 ambient_out;
|
||||
|
||||
vec4 ambient_out;
|
||||
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
|
||||
ambient_out.a = blend;
|
||||
if (reflections.data[ref_index].params.z < 0.5) { //interior
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
|
||||
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
|
||||
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} else {
|
||||
vec4 ambient_out;
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} break;
|
||||
case REFLECTION_AMBIENT_COLOR: {
|
||||
vec4 ambient_out;
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = reflections.data[ref_index].ambient;
|
||||
if (reflections.data[ref_index].params.z < 0.5) {
|
||||
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
|
||||
}
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} break;
|
||||
}
|
||||
#endif //USE_LIGHTMAP or VCT
|
||||
}
|
||||
|
||||
#ifdef USE_VOXEL_CONE_TRACING
|
||||
#ifdef USE_FORWARD_GI
|
||||
|
||||
//standard voxel cone trace
|
||||
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
|
@ -1375,42 +1378,6 @@ vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction,
|
|||
return color;
|
||||
}
|
||||
|
||||
#ifndef GI_PROBE_HIGH_QUALITY
|
||||
//faster version for 45 degrees
|
||||
|
||||
#ifdef GI_PROBE_USE_ANISOTROPY
|
||||
|
||||
vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
float radius = max(0.5, tan_half_angle * dist);
|
||||
float lod_level = log2(radius * 2.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
|
||||
vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
|
||||
vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
|
||||
|
||||
scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0));
|
||||
lod_level += 1.0;
|
||||
|
||||
float a = (1.0 - color.a);
|
||||
scolor *= a;
|
||||
color += scolor;
|
||||
dist += radius;
|
||||
radius = max(0.5, tan_half_angle * dist);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
#else
|
||||
|
||||
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
|
@ -1437,41 +1404,6 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
|
|||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(GI_PROBE_USE_ANISOTROPY)
|
||||
|
||||
//standard voxel cone trace
|
||||
vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
float half_diameter = diameter * 0.5;
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
float log2_diameter = log2(diameter);
|
||||
vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter);
|
||||
vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
|
||||
vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
|
||||
|
||||
scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0));
|
||||
|
||||
float a = (1.0 - color.a);
|
||||
scolor *= a;
|
||||
color += scolor;
|
||||
dist += half_diameter;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
|
||||
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
|
||||
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
|
||||
|
@ -1493,31 +1425,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
|
|||
|
||||
//radiance
|
||||
|
||||
#ifdef GI_PROBE_HIGH_QUALITY
|
||||
|
||||
#define MAX_CONE_DIRS 6
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
|
||||
vec3(0.0, 0.0, 1.0),
|
||||
vec3(0.866025, 0.0, 0.5),
|
||||
vec3(0.267617, 0.823639, 0.5),
|
||||
vec3(-0.700629, 0.509037, 0.5),
|
||||
vec3(-0.700629, -0.509037, 0.5),
|
||||
vec3(0.267617, -0.823639, 0.5));
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
|
||||
float cone_angle_tan = 0.577;
|
||||
|
||||
#elif defined(GI_PROBE_LOW_QUALITY)
|
||||
|
||||
#define MAX_CONE_DIRS 1
|
||||
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
|
||||
vec3(0.0, 0.0, 1.0));
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](1.0);
|
||||
float cone_angle_tan = 4; //~76 degrees
|
||||
#else // MEDIUM QUALITY
|
||||
|
||||
#define MAX_CONE_DIRS 4
|
||||
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
|
||||
|
@ -1529,31 +1436,13 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
|
|||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25);
|
||||
float cone_angle_tan = 0.98269;
|
||||
|
||||
#endif
|
||||
vec3 light = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < MAX_CONE_DIRS; i++) {
|
||||
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
|
||||
|
||||
#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY)
|
||||
vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
|
||||
#ifdef GI_PROBE_USE_ANISOTROPY
|
||||
vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
#else
|
||||
|
||||
vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
|
||||
#endif // GI_PROBE_USE_ANISOTROPY
|
||||
|
||||
#else
|
||||
|
||||
#ifdef GI_PROBE_USE_ANISOTROPY
|
||||
vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
#else
|
||||
vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
#endif // GI_PROBE_USE_ANISOTROPY
|
||||
|
||||
#endif
|
||||
if (gi_probes.data[index].blend_ambient) {
|
||||
cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
|
||||
}
|
||||
|
@ -1562,33 +1451,10 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
|
|||
}
|
||||
|
||||
light *= gi_probes.data[index].dynamic_range;
|
||||
|
||||
if (gi_probes.data[index].ambient_occlusion > 0.001) {
|
||||
float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0;
|
||||
|
||||
float taps, blend;
|
||||
blend = modf(size, taps);
|
||||
float ao = 0.0;
|
||||
for (float i = 1.0; i <= taps; i++) {
|
||||
vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size;
|
||||
ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, i - 1.0).a * i;
|
||||
}
|
||||
|
||||
if (blend > 0.001) {
|
||||
vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size;
|
||||
ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, taps).a * (taps + 1.0) * blend;
|
||||
}
|
||||
|
||||
ao = 1.0 - min(1.0, ao);
|
||||
|
||||
light = mix(scene_data.ao_color.rgb, light, mix(1.0, ao, gi_probes.data[index].ambient_occlusion));
|
||||
}
|
||||
|
||||
out_diff += vec4(light * blend, blend);
|
||||
|
||||
//irradiance
|
||||
#ifndef GI_PROBE_LOW_QUALITY
|
||||
vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
|
||||
vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
|
||||
if (gi_probes.data[index].blend_ambient) {
|
||||
irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));
|
||||
}
|
||||
|
@ -1596,10 +1462,142 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
|
|||
//irr_light=vec3(0.0);
|
||||
|
||||
out_spec += vec4(irr_light.rgb * blend, blend);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //USE_VOXEL_CONE_TRACING
|
||||
#endif //USE_FORWARD_GI
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, bool use_specular, float roughness, out vec3 diffuse_light, out vec3 specular_light, out float blend) {
|
||||
cascade_pos += cam_normal * sdfgi.normal_bias;
|
||||
|
||||
vec3 base_pos = floor(cascade_pos);
|
||||
//cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal;
|
||||
ivec3 probe_base_pos = ivec3(base_pos);
|
||||
|
||||
vec4 diffuse_accum = vec4(0.0);
|
||||
vec3 specular_accum;
|
||||
|
||||
ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade));
|
||||
tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
|
||||
tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1);
|
||||
|
||||
vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
|
||||
vec3 specular_posf;
|
||||
|
||||
if (use_specular) {
|
||||
specular_accum = vec3(0.0);
|
||||
specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
}
|
||||
|
||||
vec4 light_accum = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
|
||||
ivec3 probe_posi = probe_base_pos;
|
||||
probe_posi += offset;
|
||||
|
||||
// Compute weight
|
||||
|
||||
vec3 probe_pos = vec3(probe_posi);
|
||||
vec3 probe_to_pos = cascade_pos - probe_pos;
|
||||
vec3 probe_dir = normalize(-probe_to_pos);
|
||||
|
||||
vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
|
||||
float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir));
|
||||
|
||||
// Compute lightprobe occlusion
|
||||
|
||||
if (sdfgi.use_occlusion) {
|
||||
ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
|
||||
vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
|
||||
|
||||
vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
|
||||
occ_pos.z += float(cascade);
|
||||
if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
|
||||
occ_pos.x += 1.0;
|
||||
}
|
||||
|
||||
occ_pos *= sdfgi.occlusion_renormalize;
|
||||
float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_cascades, material_samplers[SAMPLER_LINEAR_CLAMP]), occ_pos, 0.0), occ_mask);
|
||||
|
||||
weight *= max(occlusion, 0.01);
|
||||
}
|
||||
|
||||
// Compute lightprobe texture position
|
||||
|
||||
vec3 diffuse;
|
||||
vec3 pos_uvw = diffuse_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb;
|
||||
|
||||
diffuse_accum += vec4(diffuse * weight, weight);
|
||||
|
||||
if (use_specular) {
|
||||
vec3 specular = vec3(0.0);
|
||||
vec3 pos_uvw = specular_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
if (roughness < 0.99) {
|
||||
specular = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb;
|
||||
}
|
||||
if (roughness > 0.5) {
|
||||
specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0);
|
||||
}
|
||||
|
||||
specular_accum += specular * weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
diffuse_accum.rgb /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
diffuse_light = diffuse_accum.rgb;
|
||||
|
||||
if (use_specular) {
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
specular_accum /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
specular_light = specular_accum;
|
||||
}
|
||||
|
||||
{
|
||||
//process blend
|
||||
float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5;
|
||||
float blend_to = blend_from + 2.0;
|
||||
|
||||
vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe;
|
||||
|
||||
float len = length(inner_pos);
|
||||
|
||||
inner_pos = abs(normalize(inner_pos));
|
||||
len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
if (len >= blend_from) {
|
||||
blend = smoothstep(blend_from, blend_to, len);
|
||||
} else {
|
||||
blend = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
|
||||
|
@ -1812,6 +1810,15 @@ FRAGMENT_SHADER_CODE
|
|||
#endif //not render depth
|
||||
/////////////////////// LIGHTING //////////////////////////////
|
||||
|
||||
if (scene_data.roughness_limiter_enabled) {
|
||||
//http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
|
||||
float roughness2 = roughness * roughness;
|
||||
vec3 dndu = dFdx(normal), dndv = dFdx(normal);
|
||||
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
|
||||
float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
|
||||
float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
|
||||
roughness = sqrt(filteredRoughness2);
|
||||
}
|
||||
//apply energy conservation
|
||||
|
||||
vec3 specular_light = vec3(0.0, 0.0, 0.0);
|
||||
|
@ -1820,11 +1827,6 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
|
||||
if (scene_data.roughness_limiter_enabled) {
|
||||
float limit = texelFetch(sampler2D(roughness_buffer, material_samplers[SAMPLER_NEAREST_CLAMP]), ivec2(gl_FragCoord.xy), 0).r;
|
||||
roughness = max(roughness, limit);
|
||||
}
|
||||
|
||||
if (scene_data.use_reflection_cubemap) {
|
||||
vec3 ref_vec = reflect(-view, normal);
|
||||
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
|
||||
|
@ -1871,7 +1873,6 @@ FRAGMENT_SHADER_CODE
|
|||
#endif
|
||||
|
||||
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
//gi probes
|
||||
|
||||
#ifdef USE_LIGHTMAP
|
||||
|
||||
|
@ -1928,10 +1929,80 @@ FRAGMENT_SHADER_CODE
|
|||
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//lightmap capture
|
||||
#elif defined(USE_FORWARD_GI)
|
||||
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
|
||||
|
||||
//make vertex orientation the world one, but still align to camera
|
||||
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
|
||||
vec3 cam_normal = mat3(scene_data.camera_matrix) * normal;
|
||||
vec3 cam_reflection = mat3(scene_data.camera_matrix) * reflect(-view, normal);
|
||||
|
||||
//apply y-mult
|
||||
cam_pos.y *= sdfgi.y_mult;
|
||||
cam_normal.y *= sdfgi.y_mult;
|
||||
cam_normal = normalize(cam_normal);
|
||||
cam_reflection.y *= sdfgi.y_mult;
|
||||
cam_normal = normalize(cam_normal);
|
||||
cam_reflection = normalize(cam_reflection);
|
||||
|
||||
vec4 light_accum = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
|
||||
vec4 light_blend_accum = vec4(0.0);
|
||||
float weight_blend_accum = 0.0;
|
||||
|
||||
float blend = -1.0;
|
||||
|
||||
// helper constants, compute once
|
||||
|
||||
uint cascade = 0xFFFFFFFF;
|
||||
vec3 cascade_pos;
|
||||
vec3 cascade_normal;
|
||||
|
||||
for (uint i = 0; i < sdfgi.max_cascades; i++) {
|
||||
cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
|
||||
|
||||
if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
|
||||
continue; //skip cascade
|
||||
}
|
||||
|
||||
cascade = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cascade < SDFGI_MAX_CASCADES) {
|
||||
bool use_specular = true;
|
||||
float blend;
|
||||
vec3 diffuse, specular;
|
||||
sdfgi_process(cascade, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse, specular, blend);
|
||||
|
||||
if (blend > 0.0) {
|
||||
//blend
|
||||
if (cascade == sdfgi.max_cascades - 1) {
|
||||
diffuse = mix(diffuse, ambient_light, blend);
|
||||
if (use_specular) {
|
||||
specular = mix(specular, specular_light, blend);
|
||||
}
|
||||
} else {
|
||||
vec3 diffuse2, specular2;
|
||||
float blend2;
|
||||
cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe;
|
||||
sdfgi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse2, specular2, blend2);
|
||||
diffuse = mix(diffuse, diffuse2, blend);
|
||||
if (use_specular) {
|
||||
specular = mix(specular, specular2, blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ambient_light = diffuse;
|
||||
if (use_specular) {
|
||||
specular_light = specular;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_VOXEL_CONE_TRACING
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
|
||||
|
||||
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
|
||||
|
@ -1963,6 +2034,56 @@ FRAGMENT_SHADER_CODE
|
|||
specular_light = spec_accum.rgb;
|
||||
ambient_light = amb_accum.rgb;
|
||||
}
|
||||
#else
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
|
||||
|
||||
ivec2 coord;
|
||||
|
||||
if (scene_data.gi_upscale_for_msaa) {
|
||||
/*
|
||||
//find the closest depth to upscale from, based on neighbours
|
||||
ivec2 base_coord = ivec2(gl_FragCoord.xy);
|
||||
float z_dist = gl_FragCoord.z;
|
||||
ivec2 closest_coord = base_coord;
|
||||
float closest_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord,0).r-z_dist);
|
||||
|
||||
for(int i=0;i<4;i++) {
|
||||
const ivec2 neighbours[4]=ivec2[](ivec2(-1,0),ivec2(1,0),ivec2(0,-1),ivec2(0,1));
|
||||
ivec2 neighbour_coord = base_coord + neighbours[i];
|
||||
float neighbour_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord,0).r-z_dist);
|
||||
if (neighbour_z_dist < closest_z_dist) {
|
||||
closest_z_dist = neighbour_z_dist;
|
||||
closest_coord = neighbour_coord;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
ivec2 base_coord = ivec2(gl_FragCoord.xy);
|
||||
ivec2 closest_coord = base_coord;
|
||||
float closest_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0).xyz * 2.0 - 1.0);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const ivec2 neighbours[4] = ivec2[](ivec2(-1, 0), ivec2(1, 0), ivec2(0, -1), ivec2(0, 1));
|
||||
ivec2 neighbour_coord = base_coord + neighbours[i];
|
||||
float neighbour_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0).xyz * 2.0 - 1.0);
|
||||
if (neighbour_ang > closest_ang) {
|
||||
closest_ang = neighbour_ang;
|
||||
closest_coord = neighbour_coord;
|
||||
}
|
||||
}
|
||||
|
||||
coord = closest_coord;
|
||||
|
||||
} else {
|
||||
coord = ivec2(gl_FragCoord.xy);
|
||||
}
|
||||
|
||||
vec4 buffer_ambient = texelFetch(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0);
|
||||
vec4 buffer_reflection = texelFetch(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0);
|
||||
|
||||
ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
|
||||
specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
{ // process reflections
|
||||
|
@ -2376,6 +2497,93 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#ifdef MODE_RENDER_DEPTH
|
||||
|
||||
#ifdef MODE_RENDER_SDF
|
||||
|
||||
{
|
||||
vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
|
||||
ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
|
||||
|
||||
uint albedo16 = 0x1; //solid flag
|
||||
albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
|
||||
albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
|
||||
albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
|
||||
|
||||
imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
|
||||
|
||||
uint facing_bits = 0;
|
||||
const vec3 aniso_dir[6] = vec3[](
|
||||
vec3(1, 0, 0),
|
||||
vec3(0, 1, 0),
|
||||
vec3(0, 0, 1),
|
||||
vec3(-1, 0, 0),
|
||||
vec3(0, -1, 0),
|
||||
vec3(0, 0, -1));
|
||||
|
||||
vec3 cam_normal = mat3(scene_data.camera_matrix) * normal;
|
||||
|
||||
for (uint i = 0; i < 6; i++) {
|
||||
if (dot(cam_normal, aniso_dir[i]) > 0.001) {
|
||||
facing_bits |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
|
||||
|
||||
if (length(emission) > 0.001) {
|
||||
float lumas[6];
|
||||
vec3 light_total = vec3(0);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
|
||||
vec3 light = emission * strength;
|
||||
light_total += light;
|
||||
lumas[i] = max(light.r, max(light.g, light.b));
|
||||
}
|
||||
|
||||
float luma_total = max(light_total.r, max(light_total.g, light_total.b));
|
||||
|
||||
uint light_aniso = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
|
||||
}
|
||||
|
||||
//compress to RGBE9995 to save space
|
||||
|
||||
const float pow2to9 = 512.0f;
|
||||
const float B = 15.0f;
|
||||
const float N = 9.0f;
|
||||
const float LN2 = 0.6931471805599453094172321215;
|
||||
|
||||
float cRed = clamp(light_total.r, 0.0, 65408.0);
|
||||
float cGreen = clamp(light_total.g, 0.0, 65408.0);
|
||||
float cBlue = clamp(light_total.b, 0.0, 65408.0);
|
||||
|
||||
float cMax = max(cRed, max(cGreen, cBlue));
|
||||
|
||||
float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
|
||||
|
||||
float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
|
||||
|
||||
float exps = expp + 1.0f;
|
||||
|
||||
if (0.0 <= sMax && sMax < pow2to9) {
|
||||
exps = expp;
|
||||
}
|
||||
|
||||
float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
//store as 8985 to have 2 extra neighbour bits
|
||||
uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
|
||||
|
||||
imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
|
||||
imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_MATERIAL
|
||||
|
||||
albedo_output_buffer.rgb = albedo;
|
||||
|
@ -2398,11 +2606,21 @@ FRAGMENT_SHADER_CODE
|
|||
emission_output_buffer.a = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_NORMAL
|
||||
normal_output_buffer = vec4(normal * 0.5 + 0.5, 0.0);
|
||||
#ifdef MODE_RENDER_ROUGHNESS
|
||||
roughness_output_buffer = roughness;
|
||||
#endif //MODE_RENDER_ROUGHNESS
|
||||
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
|
||||
normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
|
||||
|
||||
#ifdef MODE_RENDER_GIPROBE
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
|
||||
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
|
||||
uint index2 = instances.data[instance_index].gi_offset >> 16;
|
||||
giprobe_buffer.x = index1 & 0xFF;
|
||||
giprobe_buffer.y = index2 & 0xFF;
|
||||
} else {
|
||||
giprobe_buffer.x = 0xFF;
|
||||
giprobe_buffer.y = 0xFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //MODE_RENDER_NORMAL
|
||||
|
||||
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
|
||||
|
@ -2455,7 +2673,6 @@ FRAGMENT_SHADER_CODE
|
|||
#endif
|
||||
diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength);
|
||||
specular_buffer = vec4(specular_light, metallic);
|
||||
|
||||
#endif
|
||||
|
||||
#else //MODE_MULTIPLE_RENDER_TARGETS
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#define M_PI 3.14159265359
|
||||
#define ROUGHNESS_MAX_LOD 5
|
||||
|
||||
#define MAX_GI_PROBES 8
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform DrawCall {
|
||||
uint instance_index;
|
||||
uint pad; //16 bits minimum size
|
||||
|
@ -27,6 +29,8 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
|
|||
|
||||
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
||||
|
||||
#define SDFGI_MAX_CASCADES 8
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform SceneData {
|
||||
mat4 projection_matrix;
|
||||
mat4 inv_projection_matrix;
|
||||
|
@ -76,11 +80,19 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
|
|||
float ssao_ao_affect;
|
||||
bool roughness_limiter_enabled;
|
||||
|
||||
float roughness_limiter_amount;
|
||||
float roughness_limiter_limit;
|
||||
uvec2 roughness_limiter_pad;
|
||||
|
||||
vec4 ao_color;
|
||||
|
||||
mat4 sdf_to_bounds;
|
||||
|
||||
ivec3 sdf_offset;
|
||||
bool material_uv2_mode;
|
||||
uint pad_material0;
|
||||
uint pad_material1;
|
||||
uint pad_material2;
|
||||
|
||||
ivec3 sdf_size;
|
||||
bool gi_upscale_for_msaa;
|
||||
|
||||
#if 0
|
||||
vec4 ambient_light_color;
|
||||
|
@ -120,6 +132,8 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
|
|||
|
||||
scene_data;
|
||||
|
||||
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
|
||||
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
|
||||
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
|
||||
#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
|
||||
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
|
||||
|
@ -175,13 +189,18 @@ layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
|
|||
}
|
||||
lights;
|
||||
|
||||
#define REFLECTION_AMBIENT_DISABLED 0
|
||||
#define REFLECTION_AMBIENT_ENVIRONMENT 1
|
||||
#define REFLECTION_AMBIENT_COLOR 2
|
||||
|
||||
struct ReflectionData {
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
vec4 params; // intensity, 0, interior , boxproject
|
||||
vec4 ambient; // ambient color, energy
|
||||
vec3 ambient; // ambient color
|
||||
uint ambient_mode;
|
||||
mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
// notes: for ambientblend, use distance to edge to blend between already existing global environment
|
||||
};
|
||||
|
@ -229,29 +248,6 @@ layout(set = 0, binding = 7, std140) uniform DirectionalLights {
|
|||
}
|
||||
directional_lights;
|
||||
|
||||
struct GIProbeData {
|
||||
mat4 xform;
|
||||
vec3 bounds;
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
bool blend_ambient;
|
||||
uint texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ambient_occlusion;
|
||||
float ambient_occlusion_size;
|
||||
uint pad2;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 8, std140) uniform GIProbes {
|
||||
GIProbeData data[MAX_GI_PROBES];
|
||||
}
|
||||
gi_probes;
|
||||
|
||||
layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
|
||||
|
||||
#define LIGHTMAP_FLAG_USE_DIRECTION 1
|
||||
#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
|
||||
|
||||
|
@ -319,6 +315,41 @@ layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableDat
|
|||
}
|
||||
global_variables;
|
||||
|
||||
struct SDFGIProbeCascadeData {
|
||||
vec3 position;
|
||||
float to_probe;
|
||||
ivec3 probe_world_offset;
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 20, std140) uniform SDFGI {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
bool use_occlusion;
|
||||
int probe_axis_size;
|
||||
float probe_to_uvw;
|
||||
float normal_bias;
|
||||
|
||||
vec3 lightprobe_tex_pixel_size;
|
||||
float energy;
|
||||
|
||||
vec3 lightprobe_uv_offset;
|
||||
float y_mult;
|
||||
|
||||
vec3 occlusion_clamp;
|
||||
uint pad3;
|
||||
|
||||
vec3 occlusion_renormalize;
|
||||
uint pad4;
|
||||
|
||||
vec3 cascade_probe_size;
|
||||
uint pad5;
|
||||
|
||||
SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES];
|
||||
}
|
||||
sdfgi;
|
||||
|
||||
// decal atlas
|
||||
|
||||
/* Set 1, Radiance */
|
||||
|
@ -339,13 +370,57 @@ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas;
|
|||
|
||||
layout(set = 2, binding = 1) uniform texture2D shadow_atlas;
|
||||
|
||||
layout(set = 2, binding = 2) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
|
||||
|
||||
/* Set 3, Render Buffers */
|
||||
|
||||
#ifdef MODE_RENDER_SDF
|
||||
|
||||
layout(r16ui, set = 3, binding = 0) uniform restrict writeonly uimage3D albedo_volume_grid;
|
||||
layout(r32ui, set = 3, binding = 1) uniform restrict writeonly uimage3D emission_grid;
|
||||
layout(r32ui, set = 3, binding = 2) uniform restrict writeonly uimage3D emission_aniso_grid;
|
||||
layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid;
|
||||
|
||||
//still need to be present for shaders that use it, so remap them to something
|
||||
#define depth_buffer shadow_atlas
|
||||
#define color_buffer shadow_atlas
|
||||
#define normal_roughness_buffer shadow_atlas
|
||||
|
||||
#else
|
||||
|
||||
layout(set = 3, binding = 0) uniform texture2D depth_buffer;
|
||||
layout(set = 3, binding = 1) uniform texture2D color_buffer;
|
||||
layout(set = 3, binding = 2) uniform texture2D normal_buffer;
|
||||
layout(set = 3, binding = 3) uniform texture2D roughness_buffer;
|
||||
layout(set = 3, binding = 2) uniform texture2D normal_roughness_buffer;
|
||||
layout(set = 3, binding = 4) uniform texture2D ao_buffer;
|
||||
layout(set = 3, binding = 5) uniform texture2D ambient_buffer;
|
||||
layout(set = 3, binding = 6) uniform texture2D reflection_buffer;
|
||||
|
||||
layout(set = 3, binding = 7) uniform texture2DArray sdfgi_lightprobe_texture;
|
||||
|
||||
layout(set = 3, binding = 8) uniform texture3D sdfgi_occlusion_cascades;
|
||||
|
||||
struct GIProbeData {
|
||||
mat4 xform;
|
||||
vec3 bounds;
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
bool blend_ambient;
|
||||
uint texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ambient_occlusion;
|
||||
float ambient_occlusion_size;
|
||||
uint pad2;
|
||||
};
|
||||
|
||||
layout(set = 3, binding = 9, std140) uniform GIProbes {
|
||||
GIProbeData data[MAX_GI_PROBES];
|
||||
}
|
||||
gi_probes;
|
||||
|
||||
#endif
|
||||
|
||||
/* Set 4 Skeleton & Instancing (Multimesh) */
|
||||
|
||||
|
|
|
@ -12,11 +12,8 @@ layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D ssr_ima
|
|||
#ifdef MODE_ROUGH
|
||||
layout(r8, set = 1, binding = 1) uniform restrict writeonly image2D blur_radius_image;
|
||||
#endif
|
||||
layout(rgba8, set = 2, binding = 0) uniform restrict readonly image2D source_normal;
|
||||
layout(rgba8, set = 2, binding = 0) uniform restrict readonly image2D source_normal_roughness;
|
||||
layout(set = 3, binding = 0) uniform sampler2D source_metallic;
|
||||
#ifdef MODE_ROUGH
|
||||
layout(set = 3, binding = 1) uniform sampler2D source_roughness;
|
||||
#endif
|
||||
|
||||
layout(push_constant, binding = 2, std430) uniform Params {
|
||||
vec4 proj_info;
|
||||
|
@ -75,7 +72,8 @@ void main() {
|
|||
// World space point being shaded
|
||||
vec3 vertex = reconstructCSPosition(uv * vec2(params.screen_size), base_depth);
|
||||
|
||||
vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
|
||||
vec4 normal_roughness = imageLoad(source_normal_roughness, ssC);
|
||||
vec3 normal = normal_roughness.xyz * 2.0 - 1.0;
|
||||
normal = normalize(normal);
|
||||
normal.y = -normal.y; //because this code reads flipped
|
||||
|
||||
|
@ -208,7 +206,7 @@ void main() {
|
|||
|
||||
// if roughness is enabled, do screen space cone tracing
|
||||
float blur_radius = 0.0;
|
||||
float roughness = texelFetch(source_roughness, ssC << 1, 0).r;
|
||||
float roughness = normal_roughness.w;
|
||||
|
||||
if (roughness > 0.001) {
|
||||
float cone_angle = min(roughness, 0.999) * M_PI * 0.5;
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
#define MAX_CASCADES 8
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 2) uniform texture3D light_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 5) uniform texture3D occlusion_texture;
|
||||
|
||||
layout(set = 0, binding = 8) uniform sampler linear_sampler;
|
||||
|
||||
struct CascadeData {
|
||||
vec3 offset; //offset of (0,0,0) in world coordinates
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
ivec3 probe_world_offset;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 9, std140) uniform Cascades {
|
||||
CascadeData data[MAX_CASCADES];
|
||||
}
|
||||
cascades;
|
||||
|
||||
layout(rgba16f, set = 0, binding = 10) uniform restrict writeonly image2D screen_buffer;
|
||||
|
||||
layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
ivec2 screen_size;
|
||||
bool use_occlusion;
|
||||
float y_mult;
|
||||
|
||||
vec3 cam_extent;
|
||||
int probe_axis_size;
|
||||
|
||||
mat4 cam_transform;
|
||||
}
|
||||
params;
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
//if going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Pixel being shaded
|
||||
ivec2 screen_pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(screen_pos, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 ray_pos;
|
||||
vec3 ray_dir;
|
||||
{
|
||||
ray_pos = params.cam_transform[3].xyz;
|
||||
|
||||
ray_dir.xy = params.cam_extent.xy * ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);
|
||||
ray_dir.z = params.cam_extent.z;
|
||||
|
||||
ray_dir = normalize(mat3(params.cam_transform) * ray_dir);
|
||||
}
|
||||
|
||||
ray_pos.y *= params.y_mult;
|
||||
ray_dir.y *= params.y_mult;
|
||||
ray_dir = normalize(ray_dir);
|
||||
|
||||
vec3 pos_to_uvw = 1.0 / params.grid_size;
|
||||
|
||||
vec3 light = vec3(0.0);
|
||||
float blend = 0.0;
|
||||
|
||||
#if 1
|
||||
vec3 inv_dir = 1.0 / ray_dir;
|
||||
|
||||
float rough = 0.5;
|
||||
bool hit = false;
|
||||
|
||||
for (uint i = 0; i < params.max_cascades; i++) {
|
||||
//convert to local bounds
|
||||
vec3 pos = ray_pos - cascades.data[i].offset;
|
||||
pos *= cascades.data[i].to_cell;
|
||||
|
||||
// Should never happen for debug, since we start mostly at the bounds center,
|
||||
// but add anyway.
|
||||
//if (any(lessThan(pos,vec3(0.0))) || any(greaterThanEqual(pos,params.grid_size))) {
|
||||
// continue; //already past bounds for this cascade, goto next
|
||||
//}
|
||||
|
||||
//find maximum advance distance (until reaching bounds)
|
||||
vec3 t0 = -pos * inv_dir;
|
||||
vec3 t1 = (params.grid_size - pos) * inv_dir;
|
||||
vec3 tmax = max(t0, t1);
|
||||
float max_advance = min(tmax.x, min(tmax.y, tmax.z));
|
||||
|
||||
float advance = 0.0;
|
||||
vec3 uvw;
|
||||
hit = false;
|
||||
|
||||
while (advance < max_advance) {
|
||||
//read how much to advance from SDF
|
||||
uvw = (pos + ray_dir * advance) * pos_to_uvw;
|
||||
|
||||
float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), uvw).r * 255.0 - 1.7;
|
||||
|
||||
if (distance < 0.001) {
|
||||
//consider hit
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
advance += distance;
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
pos += ray_dir * min(advance, max_advance);
|
||||
pos /= cascades.data[i].to_cell;
|
||||
pos += cascades.data[i].offset;
|
||||
ray_pos = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
//compute albedo, emission and normal at hit point
|
||||
|
||||
const float EPSILON = 0.001;
|
||||
vec3 hit_normal = normalize(vec3(
|
||||
texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
|
||||
texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
|
||||
texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
|
||||
|
||||
vec3 hit_light = texture(sampler3D(light_cascades[i], linear_sampler), uvw).rgb;
|
||||
vec4 aniso0 = texture(sampler3D(aniso0_cascades[i], linear_sampler), uvw);
|
||||
vec3 hit_aniso0 = aniso0.rgb;
|
||||
vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[i], linear_sampler), uvw).rg);
|
||||
|
||||
hit_light *= (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
|
||||
|
||||
if (blend > 0.0) {
|
||||
light = mix(light, hit_light, blend);
|
||||
blend = 0.0;
|
||||
} else {
|
||||
light = hit_light;
|
||||
|
||||
//process blend
|
||||
float blend_from = (float(params.probe_axis_size - 1) / 2.0) - 2.5;
|
||||
float blend_to = blend_from + 2.0;
|
||||
|
||||
vec3 cam_pos = params.cam_transform[3].xyz - cascades.data[i].offset;
|
||||
cam_pos *= cascades.data[i].to_cell;
|
||||
|
||||
pos += ray_dir * min(advance, max_advance);
|
||||
vec3 inner_pos = pos - cam_pos;
|
||||
|
||||
inner_pos = inner_pos * float(params.probe_axis_size - 1) / params.grid_size.x;
|
||||
|
||||
float len = length(inner_pos);
|
||||
|
||||
inner_pos = abs(normalize(inner_pos));
|
||||
len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
if (len >= blend_from) {
|
||||
blend = smoothstep(blend_from, blend_to, len);
|
||||
|
||||
pos /= cascades.data[i].to_cell;
|
||||
pos += cascades.data[i].offset;
|
||||
ray_pos = pos;
|
||||
hit = false; //continue trace for blend
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
light = mix(light, vec3(0.0), blend);
|
||||
|
||||
#else
|
||||
|
||||
vec3 inv_dir = 1.0 / ray_dir;
|
||||
|
||||
bool hit = false;
|
||||
vec4 light_accum = vec4(0.0);
|
||||
|
||||
float blend_size = (params.grid_size.x / float(params.probe_axis_size - 1)) * 0.5;
|
||||
|
||||
float radius_sizes[MAX_CASCADES];
|
||||
for (uint i = 0; i < params.max_cascades; i++) {
|
||||
radius_sizes[i] = (1.0 / cascades.data[i].to_cell) * (params.grid_size.x * 0.5 - blend_size);
|
||||
}
|
||||
|
||||
float max_distance = radius_sizes[params.max_cascades - 1];
|
||||
float advance = 0;
|
||||
while (advance < max_distance) {
|
||||
for (uint i = 0; i < params.max_cascades; i++) {
|
||||
if (advance < radius_sizes[i]) {
|
||||
vec3 pos = (ray_pos + ray_dir * advance) - cascades.data[i].offset;
|
||||
pos *= cascades.data[i].to_cell * pos_to_uvw;
|
||||
|
||||
float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.0;
|
||||
|
||||
vec4 hit_light = vec4(0.0);
|
||||
if (distance < 1.0) {
|
||||
hit_light.a = max(0.0, 1.0 - distance);
|
||||
hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb;
|
||||
hit_light.rgb *= hit_light.a;
|
||||
}
|
||||
|
||||
distance /= cascades.data[i].to_cell;
|
||||
|
||||
if (i < (params.max_cascades - 1)) {
|
||||
pos = (ray_pos + ray_dir * advance) - cascades.data[i + 1].offset;
|
||||
pos *= cascades.data[i + 1].to_cell * pos_to_uvw;
|
||||
|
||||
float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.0;
|
||||
|
||||
vec4 hit_light2 = vec4(0.0);
|
||||
if (distance2 < 1.0) {
|
||||
hit_light2.a = max(0.0, 1.0 - distance2);
|
||||
hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb;
|
||||
hit_light2.rgb *= hit_light2.a;
|
||||
}
|
||||
|
||||
float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1];
|
||||
float blend = (advance - prev_radius) / (radius_sizes[i] - prev_radius);
|
||||
|
||||
distance2 /= cascades.data[i + 1].to_cell;
|
||||
|
||||
hit_light = mix(hit_light, hit_light2, blend);
|
||||
distance = mix(distance, distance2, blend);
|
||||
}
|
||||
|
||||
light_accum += hit_light;
|
||||
advance += distance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (light_accum.a > 0.98) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
light = light_accum.rgb / light_accum.a;
|
||||
|
||||
#endif
|
||||
|
||||
imageStore(screen_buffer, screen_pos, vec4(linear_to_srgb(light), 1.0));
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define MAX_CASCADES 8
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
mat4 projection;
|
||||
|
||||
uint band_power;
|
||||
uint sections_in_band;
|
||||
uint band_mask;
|
||||
float section_arc;
|
||||
|
||||
vec3 grid_size;
|
||||
uint cascade;
|
||||
|
||||
uint pad;
|
||||
float y_mult;
|
||||
uint probe_debug_index;
|
||||
int probe_axis_size;
|
||||
}
|
||||
params;
|
||||
|
||||
// http://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm
|
||||
|
||||
vec3 get_sphere_vertex(uint p_vertex_id) {
|
||||
float x_angle = float(p_vertex_id & 1u) + (p_vertex_id >> params.band_power);
|
||||
|
||||
float y_angle =
|
||||
float((p_vertex_id & params.band_mask) >> 1) + ((p_vertex_id >> params.band_power) * params.sections_in_band);
|
||||
|
||||
x_angle *= params.section_arc * 0.5f; // remember - 180AA x rot not 360
|
||||
y_angle *= -params.section_arc;
|
||||
|
||||
vec3 point = vec3(sin(x_angle) * sin(y_angle), cos(x_angle), sin(x_angle) * cos(y_angle));
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
#ifdef MODE_PROBES
|
||||
|
||||
layout(location = 0) out vec3 normal_interp;
|
||||
layout(location = 1) out flat uint probe_index;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_VISIBILITY
|
||||
|
||||
layout(location = 0) out float visibility;
|
||||
|
||||
#endif
|
||||
|
||||
struct CascadeData {
|
||||
vec3 offset; //offset of (0,0,0) in world coordinates
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
ivec3 probe_world_offset;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1, std140) uniform Cascades {
|
||||
CascadeData data[MAX_CASCADES];
|
||||
}
|
||||
cascades;
|
||||
|
||||
layout(set = 0, binding = 4) uniform texture3D occlusion_texture;
|
||||
layout(set = 0, binding = 3) uniform sampler linear_sampler;
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_PROBES
|
||||
probe_index = gl_InstanceIndex;
|
||||
|
||||
normal_interp = get_sphere_vertex(gl_VertexIndex);
|
||||
|
||||
vec3 vertex = normal_interp * 0.2;
|
||||
|
||||
float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
|
||||
|
||||
ivec3 probe_cell;
|
||||
probe_cell.x = int(probe_index % params.probe_axis_size);
|
||||
probe_cell.y = int(probe_index / (params.probe_axis_size * params.probe_axis_size));
|
||||
probe_cell.z = int((probe_index / params.probe_axis_size) % params.probe_axis_size);
|
||||
|
||||
vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0);
|
||||
|
||||
gl_Position = params.projection * vec4(vertex, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_VISIBILITY
|
||||
|
||||
int probe_index = int(params.probe_debug_index);
|
||||
|
||||
vec3 vertex = get_sphere_vertex(gl_VertexIndex) * 0.01;
|
||||
|
||||
float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
|
||||
|
||||
ivec3 probe_cell;
|
||||
probe_cell.x = int(probe_index % params.probe_axis_size);
|
||||
probe_cell.y = int((probe_index % (params.probe_axis_size * params.probe_axis_size)) / params.probe_axis_size);
|
||||
probe_cell.z = int(probe_index / (params.probe_axis_size * params.probe_axis_size));
|
||||
|
||||
vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0);
|
||||
|
||||
int probe_voxels = int(params.grid_size.x) / int(params.probe_axis_size - 1);
|
||||
int occluder_index = int(gl_InstanceIndex);
|
||||
|
||||
int diameter = probe_voxels * 2;
|
||||
ivec3 occluder_pos;
|
||||
occluder_pos.x = int(occluder_index % diameter);
|
||||
occluder_pos.y = int(occluder_index / (diameter * diameter));
|
||||
occluder_pos.z = int((occluder_index / diameter) % diameter);
|
||||
|
||||
float cell_size = 1.0 / cascades.data[params.cascade].to_cell;
|
||||
|
||||
ivec3 occluder_offset = occluder_pos - ivec3(diameter / 2);
|
||||
vertex += ((vec3(occluder_offset) + vec3(0.5)) * cell_size) / vec3(1.0, params.y_mult, 1.0);
|
||||
|
||||
ivec3 global_cell = probe_cell + cascades.data[params.cascade].probe_world_offset;
|
||||
uint occlusion_layer = 0;
|
||||
if ((global_cell.x & 1) != 0) {
|
||||
occlusion_layer |= 1;
|
||||
}
|
||||
if ((global_cell.y & 1) != 0) {
|
||||
occlusion_layer |= 2;
|
||||
}
|
||||
if ((global_cell.z & 1) != 0) {
|
||||
occlusion_layer |= 4;
|
||||
}
|
||||
ivec3 tex_pos = probe_cell * probe_voxels + occluder_offset;
|
||||
|
||||
const vec4 layer_axis[4] = vec4[](
|
||||
vec4(1, 0, 0, 0),
|
||||
vec4(0, 1, 0, 0),
|
||||
vec4(0, 0, 1, 0),
|
||||
vec4(0, 0, 0, 1));
|
||||
|
||||
tex_pos.z += int(params.cascade) * int(params.grid_size);
|
||||
if (occlusion_layer >= 4) {
|
||||
tex_pos.x += int(params.grid_size.x);
|
||||
occlusion_layer &= 3;
|
||||
}
|
||||
|
||||
visibility = dot(texelFetch(sampler3D(occlusion_texture, linear_sampler), tex_pos, 0), layer_axis[occlusion_layer]);
|
||||
|
||||
gl_Position = params.projection * vec4(vertex, 1.0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
layout(set = 0, binding = 2) uniform texture2DArray lightprobe_texture;
|
||||
layout(set = 0, binding = 3) uniform sampler linear_sampler;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
mat4 projection;
|
||||
|
||||
uint band_power;
|
||||
uint sections_in_band;
|
||||
uint band_mask;
|
||||
float section_arc;
|
||||
|
||||
vec3 grid_size;
|
||||
uint cascade;
|
||||
|
||||
uint pad;
|
||||
float y_mult;
|
||||
uint probe_debug_index;
|
||||
int probe_axis_size;
|
||||
}
|
||||
params;
|
||||
|
||||
#ifdef MODE_PROBES
|
||||
|
||||
layout(location = 0) in vec3 normal_interp;
|
||||
layout(location = 1) in flat uint probe_index;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_VISIBILITY
|
||||
layout(location = 0) in float visibility;
|
||||
#endif
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_PROBES
|
||||
|
||||
ivec3 tex_pos;
|
||||
tex_pos.x = int(probe_index) % params.probe_axis_size; //x
|
||||
tex_pos.y = int(probe_index) / (params.probe_axis_size * params.probe_axis_size);
|
||||
tex_pos.x += params.probe_axis_size * ((int(probe_index) / params.probe_axis_size) % params.probe_axis_size); //z
|
||||
tex_pos.z = int(params.cascade);
|
||||
|
||||
vec3 tex_pos_ofs = vec3(octahedron_encode(normal_interp) * float(OCT_SIZE), 0.0);
|
||||
vec3 tex_posf = vec3(vec2(tex_pos.xy * (OCT_SIZE + 2) + ivec2(1)), float(tex_pos.z)) + tex_pos_ofs;
|
||||
|
||||
tex_posf.xy /= vec2(ivec2(params.probe_axis_size * params.probe_axis_size * (OCT_SIZE + 2), params.probe_axis_size * (OCT_SIZE + 2)));
|
||||
|
||||
vec4 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), tex_posf, 0.0);
|
||||
|
||||
frag_color = indirect_light;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_VISIBILITY
|
||||
|
||||
frag_color = vec4(vec3(1, visibility, visibility), 1.0);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,472 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
#define MAX_CASCADES 8
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 2) uniform sampler linear_sampler;
|
||||
|
||||
layout(set = 0, binding = 3, std430) restrict readonly buffer DispatchData {
|
||||
uint x;
|
||||
uint y;
|
||||
uint z;
|
||||
uint total_count;
|
||||
}
|
||||
dispatch_data;
|
||||
|
||||
struct ProcessVoxel {
|
||||
uint position; //xyz 7 bit packed, extra 11 bits for neigbours
|
||||
uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
|
||||
uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous
|
||||
uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
|
||||
//total neighbours: 26
|
||||
};
|
||||
|
||||
#ifdef MODE_PROCESS_STATIC
|
||||
layout(set = 0, binding = 4, std430) restrict buffer ProcessVoxels {
|
||||
#else
|
||||
layout(set = 0, binding = 4, std430) restrict buffer readonly ProcessVoxels {
|
||||
#endif
|
||||
ProcessVoxel data[];
|
||||
}
|
||||
process_voxels;
|
||||
|
||||
layout(r32ui, set = 0, binding = 5) uniform restrict uimage3D dst_light;
|
||||
layout(rgba8, set = 0, binding = 6) uniform restrict image3D dst_aniso0;
|
||||
layout(rg8, set = 0, binding = 7) uniform restrict image3D dst_aniso1;
|
||||
|
||||
struct CascadeData {
|
||||
vec3 offset; //offset of (0,0,0) in world coordinates
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
ivec3 probe_world_offset;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 8, std140) uniform Cascades {
|
||||
CascadeData data[MAX_CASCADES];
|
||||
}
|
||||
cascades;
|
||||
|
||||
#define LIGHT_TYPE_DIRECTIONAL 0
|
||||
#define LIGHT_TYPE_OMNI 1
|
||||
#define LIGHT_TYPE_SPOT 2
|
||||
|
||||
struct Light {
|
||||
vec3 color;
|
||||
float energy;
|
||||
|
||||
vec3 direction;
|
||||
bool has_shadow;
|
||||
|
||||
vec3 position;
|
||||
float attenuation;
|
||||
|
||||
uint type;
|
||||
float spot_angle;
|
||||
float spot_attenuation;
|
||||
float radius;
|
||||
|
||||
vec4 shadow_color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 9, std140) buffer restrict readonly Lights {
|
||||
Light data[];
|
||||
}
|
||||
lights;
|
||||
|
||||
layout(set = 0, binding = 10) uniform texture2DArray lightprobe_texture;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
uint cascade;
|
||||
uint light_count;
|
||||
uint process_offset;
|
||||
uint process_increment;
|
||||
|
||||
int probe_axis_size;
|
||||
bool multibounce;
|
||||
float y_mult;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint voxel_index = uint(gl_GlobalInvocationID.x);
|
||||
|
||||
//used for skipping voxels every N frames
|
||||
voxel_index = params.process_offset + voxel_index * params.process_increment;
|
||||
|
||||
if (voxel_index >= dispatch_data.total_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint voxel_position = process_voxels.data[voxel_index].position;
|
||||
|
||||
//keep for storing to texture
|
||||
ivec3 positioni = ivec3((uvec3(voxel_position, voxel_position, voxel_position) >> uvec3(0, 7, 14)) & uvec3(0x7F));
|
||||
|
||||
vec3 position = vec3(positioni) + vec3(0.5);
|
||||
position /= cascades.data[params.cascade].to_cell;
|
||||
position += cascades.data[params.cascade].offset;
|
||||
|
||||
uint voxel_albedo = process_voxels.data[voxel_index].albedo;
|
||||
|
||||
vec3 albedo = vec3(uvec3(voxel_albedo >> 10, voxel_albedo >> 5, voxel_albedo) & uvec3(0x1F)) / float(0x1F);
|
||||
vec3 light_accum[6];
|
||||
|
||||
uint valid_aniso = (voxel_albedo >> 15) & 0x3F;
|
||||
|
||||
{
|
||||
uint rgbe = process_voxels.data[voxel_index].light;
|
||||
|
||||
//read rgbe8985
|
||||
float r = float((rgbe & 0xff) << 1);
|
||||
float g = float((rgbe >> 8) & 0x1ff);
|
||||
float b = float(((rgbe >> 17) & 0xff) << 1);
|
||||
float e = float((rgbe >> 25) & 0x1F);
|
||||
float m = pow(2.0, e - 15.0 - 9.0);
|
||||
|
||||
vec3 l = vec3(r, g, b) * m;
|
||||
|
||||
uint aniso = process_voxels.data[voxel_index].light_aniso;
|
||||
for (uint i = 0; i < 6; i++) {
|
||||
float strength = ((aniso >> (i * 5)) & 0x1F) / float(0x1F);
|
||||
light_accum[i] = l * strength;
|
||||
}
|
||||
}
|
||||
|
||||
const vec3 aniso_dir[6] = vec3[](
|
||||
vec3(1, 0, 0),
|
||||
vec3(0, 1, 0),
|
||||
vec3(0, 0, 1),
|
||||
vec3(-1, 0, 0),
|
||||
vec3(0, -1, 0),
|
||||
vec3(0, 0, -1));
|
||||
|
||||
// Raytrace light
|
||||
|
||||
vec3 pos_to_uvw = 1.0 / params.grid_size;
|
||||
vec3 uvw_ofs = pos_to_uvw * 0.5;
|
||||
|
||||
for (uint i = 0; i < params.light_count; i++) {
|
||||
float attenuation = 1.0;
|
||||
vec3 direction;
|
||||
float light_distance = 1e20;
|
||||
|
||||
switch (lights.data[i].type) {
|
||||
case LIGHT_TYPE_DIRECTIONAL: {
|
||||
direction = -lights.data[i].direction;
|
||||
} break;
|
||||
case LIGHT_TYPE_OMNI: {
|
||||
vec3 rel_vec = lights.data[i].position - position;
|
||||
direction = normalize(rel_vec);
|
||||
light_distance = length(rel_vec);
|
||||
rel_vec.y /= params.y_mult;
|
||||
attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
|
||||
} break;
|
||||
case LIGHT_TYPE_SPOT: {
|
||||
vec3 rel_vec = lights.data[i].position - position;
|
||||
direction = normalize(rel_vec);
|
||||
light_distance = length(rel_vec);
|
||||
rel_vec.y /= params.y_mult;
|
||||
attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
|
||||
|
||||
float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));
|
||||
if (angle > lights.data[i].spot_angle) {
|
||||
attenuation = 0.0;
|
||||
} else {
|
||||
float d = clamp(angle / lights.data[i].spot_angle, 0, 1);
|
||||
attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (attenuation < 0.001) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
|
||||
vec3 ray_pos = position;
|
||||
vec3 ray_dir = direction;
|
||||
vec3 inv_dir = 1.0 / ray_dir;
|
||||
|
||||
//this is how to properly bias outgoing rays
|
||||
float cell_size = 1.0 / cascades.data[params.cascade].to_cell;
|
||||
ray_pos += sign(direction) * cell_size * 0.48; // go almost to the box edge but remain inside
|
||||
ray_pos += ray_dir * 0.4 * cell_size; //apply a small bias from there
|
||||
|
||||
for (uint j = params.cascade; j < params.max_cascades; j++) {
|
||||
//convert to local bounds
|
||||
vec3 pos = ray_pos - cascades.data[j].offset;
|
||||
pos *= cascades.data[j].to_cell;
|
||||
float local_distance = light_distance * cascades.data[j].to_cell;
|
||||
|
||||
if (any(lessThan(pos, vec3(0.0))) || any(greaterThanEqual(pos, params.grid_size))) {
|
||||
continue; //already past bounds for this cascade, goto next
|
||||
}
|
||||
|
||||
//find maximum advance distance (until reaching bounds)
|
||||
vec3 t0 = -pos * inv_dir;
|
||||
vec3 t1 = (params.grid_size - pos) * inv_dir;
|
||||
vec3 tmax = max(t0, t1);
|
||||
float max_advance = min(tmax.x, min(tmax.y, tmax.z));
|
||||
|
||||
max_advance = min(local_distance, max_advance);
|
||||
|
||||
float advance = 0.0;
|
||||
float occlusion = 1.0;
|
||||
|
||||
while (advance < max_advance) {
|
||||
//read how much to advance from SDF
|
||||
vec3 uvw = (pos + ray_dir * advance) * pos_to_uvw;
|
||||
|
||||
float distance = texture(sampler3D(sdf_cascades[j], linear_sampler), uvw).r * 255.0 - 1.0;
|
||||
if (distance < 0.001) {
|
||||
//consider hit
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
occlusion = min(occlusion, distance);
|
||||
|
||||
advance += distance;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
attenuation *= occlusion;
|
||||
break;
|
||||
}
|
||||
|
||||
if (advance >= local_distance) {
|
||||
break; //past light distance, abandon search
|
||||
}
|
||||
//change ray origin to collision with bounds
|
||||
pos += ray_dir * max_advance;
|
||||
pos /= cascades.data[j].to_cell;
|
||||
pos += cascades.data[j].offset;
|
||||
light_distance -= max_advance / cascades.data[j].to_cell;
|
||||
ray_pos = pos;
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
vec3 light = albedo * lights.data[i].color.rgb * lights.data[i].energy * attenuation;
|
||||
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (bool(valid_aniso & (1 << j))) {
|
||||
light_accum[j] += max(0.0, dot(aniso_dir[j], direction)) * light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add indirect light
|
||||
|
||||
if (params.multibounce) {
|
||||
vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size;
|
||||
ivec3 probe_base_pos = ivec3(pos);
|
||||
|
||||
vec4 probe_accum[6] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
|
||||
float weight_accum[6] = float[](0, 0, 0, 0, 0, 0);
|
||||
|
||||
ivec3 tex_pos = ivec3(probe_base_pos.xy, int(params.cascade));
|
||||
tex_pos.x += probe_base_pos.z * int(params.probe_axis_size);
|
||||
|
||||
tex_pos.xy = tex_pos.xy * (OCT_SIZE + 2) + ivec2(1);
|
||||
|
||||
vec3 base_tex_posf = vec3(tex_pos);
|
||||
vec2 tex_pixel_size = 1.0 / vec2(ivec2((OCT_SIZE + 2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE + 2) * params.probe_axis_size));
|
||||
vec3 probe_uv_offset = (ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
|
||||
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
|
||||
ivec3 probe_posi = probe_base_pos;
|
||||
probe_posi += offset;
|
||||
|
||||
// Compute weight
|
||||
|
||||
vec3 probe_pos = vec3(probe_posi);
|
||||
vec3 probe_to_pos = pos - probe_pos;
|
||||
vec3 probe_dir = normalize(-probe_to_pos);
|
||||
|
||||
// Compute lightprobe texture position
|
||||
|
||||
vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
|
||||
|
||||
for (uint k = 0; k < 6; k++) {
|
||||
if (bool(valid_aniso & (1 << k))) {
|
||||
vec3 n = aniso_dir[k];
|
||||
float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir));
|
||||
|
||||
vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
|
||||
tex_posf.xy *= tex_pixel_size;
|
||||
|
||||
vec3 pos_uvw = tex_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * probe_uv_offset.z;
|
||||
vec4 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0);
|
||||
|
||||
probe_accum[k] += indirect_light * weight;
|
||||
weight_accum[k] += weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint k = 0; k < 6; k++) {
|
||||
if (weight_accum[k] > 0.0) {
|
||||
light_accum[k] += probe_accum[k].rgb * albedo / weight_accum[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the light in the light texture
|
||||
|
||||
float lumas[6];
|
||||
vec3 light_total = vec3(0);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
light_total += light_accum[i];
|
||||
lumas[i] = max(light_accum[i].r, max(light_accum[i].g, light_accum[i].b));
|
||||
}
|
||||
|
||||
float luma_total = max(light_total.r, max(light_total.g, light_total.b));
|
||||
|
||||
uint light_total_rgbe;
|
||||
|
||||
{
|
||||
//compress to RGBE9995 to save space
|
||||
|
||||
const float pow2to9 = 512.0f;
|
||||
const float B = 15.0f;
|
||||
const float N = 9.0f;
|
||||
const float LN2 = 0.6931471805599453094172321215;
|
||||
|
||||
float cRed = clamp(light_total.r, 0.0, 65408.0);
|
||||
float cGreen = clamp(light_total.g, 0.0, 65408.0);
|
||||
float cBlue = clamp(light_total.b, 0.0, 65408.0);
|
||||
|
||||
float cMax = max(cRed, max(cGreen, cBlue));
|
||||
|
||||
float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
|
||||
|
||||
float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
|
||||
|
||||
float exps = expp + 1.0f;
|
||||
|
||||
if (0.0 <= sMax && sMax < pow2to9) {
|
||||
exps = expp;
|
||||
}
|
||||
|
||||
float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
#ifdef MODE_PROCESS_STATIC
|
||||
//since its self-save, use RGBE8985
|
||||
light_total_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
|
||||
|
||||
#else
|
||||
light_total_rgbe = (uint(sRed) & 0x1FF) | ((uint(sGreen) & 0x1FF) << 9) | ((uint(sBlue) & 0x1FF) << 18) | ((uint(exps) & 0x1F) << 27);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MODE_PROCESS_DYNAMIC
|
||||
|
||||
vec4 aniso0;
|
||||
aniso0.r = lumas[0] / luma_total;
|
||||
aniso0.g = lumas[1] / luma_total;
|
||||
aniso0.b = lumas[2] / luma_total;
|
||||
aniso0.a = lumas[3] / luma_total;
|
||||
|
||||
vec2 aniso1;
|
||||
aniso1.r = lumas[4] / luma_total;
|
||||
aniso1.g = lumas[5] / luma_total;
|
||||
|
||||
//save to 3D textures
|
||||
imageStore(dst_aniso0, positioni, aniso0);
|
||||
imageStore(dst_aniso1, positioni, vec4(aniso1, 0.0, 0.0));
|
||||
imageStore(dst_light, positioni, uvec4(light_total_rgbe));
|
||||
|
||||
//also fill neighbours, so light interpolation during the indirect pass works
|
||||
|
||||
//recover the neighbour list from the leftover bits
|
||||
uint neighbours = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24);
|
||||
|
||||
const uint max_neighbours = 26;
|
||||
const ivec3 neighbour_positions[max_neighbours] = ivec3[](
|
||||
ivec3(-1, -1, -1),
|
||||
ivec3(-1, -1, 0),
|
||||
ivec3(-1, -1, 1),
|
||||
ivec3(-1, 0, -1),
|
||||
ivec3(-1, 0, 0),
|
||||
ivec3(-1, 0, 1),
|
||||
ivec3(-1, 1, -1),
|
||||
ivec3(-1, 1, 0),
|
||||
ivec3(-1, 1, 1),
|
||||
ivec3(0, -1, -1),
|
||||
ivec3(0, -1, 0),
|
||||
ivec3(0, -1, 1),
|
||||
ivec3(0, 0, -1),
|
||||
ivec3(0, 0, 1),
|
||||
ivec3(0, 1, -1),
|
||||
ivec3(0, 1, 0),
|
||||
ivec3(0, 1, 1),
|
||||
ivec3(1, -1, -1),
|
||||
ivec3(1, -1, 0),
|
||||
ivec3(1, -1, 1),
|
||||
ivec3(1, 0, -1),
|
||||
ivec3(1, 0, 0),
|
||||
ivec3(1, 0, 1),
|
||||
ivec3(1, 1, -1),
|
||||
ivec3(1, 1, 0),
|
||||
ivec3(1, 1, 1));
|
||||
|
||||
for (uint i = 0; i < max_neighbours; i++) {
|
||||
if (bool(neighbours & (1 << i))) {
|
||||
ivec3 neighbour_pos = positioni + neighbour_positions[i];
|
||||
imageStore(dst_light, neighbour_pos, uvec4(light_total_rgbe));
|
||||
imageStore(dst_aniso0, neighbour_pos, aniso0);
|
||||
imageStore(dst_aniso1, neighbour_pos, vec4(aniso1, 0.0, 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_PROCESS_STATIC
|
||||
|
||||
//save back the anisotropic
|
||||
|
||||
uint light = process_voxels.data[voxel_index].light & (3 << 30);
|
||||
light |= light_total_rgbe;
|
||||
process_voxels.data[voxel_index].light = light; //replace
|
||||
|
||||
uint light_aniso = process_voxels.data[voxel_index].light_aniso & (3 << 30);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
|
||||
}
|
||||
|
||||
process_voxels.data[voxel_index].light_aniso = light_aniso;
|
||||
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = OCT_RES, local_size_y = OCT_RES, local_size_z = 1) in;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#define MAX_CASCADES 8
|
||||
|
||||
layout(rgba16f, set = 0, binding = 1) uniform restrict image2DArray irradiance_texture;
|
||||
layout(rg16f, set = 0, binding = 2) uniform restrict image2DArray depth_texture;
|
||||
|
||||
ayout(rgba32ui, set = 0, binding = 3) uniform restrict uimage2DArray irradiance_history_texture;
|
||||
layout(rg32ui, set = 0, binding = 4) uniform restrict uimage2DArray depth_history_texture;
|
||||
|
||||
struct CascadeData {
|
||||
vec3 offset; //offset of (0,0,0) in world coordinates
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 5, std140) uniform Cascades {
|
||||
CascadeData data[MAX_CASCADES];
|
||||
}
|
||||
cascades;
|
||||
|
||||
#define DEPTH_HISTORY_BITS 24
|
||||
#define IRRADIANCE_HISTORY_BITS 16
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
uint probe_axis_size;
|
||||
uint cascade;
|
||||
uint history_size;
|
||||
uint pad0;
|
||||
|
||||
ivec3 scroll; //scroll in probes
|
||||
uint pad1;
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
ivec2 local = ivec2(gl_LocalInvocationID.xy);
|
||||
ivec2 probe = ivec2(gl_WorkGroupID.xy);
|
||||
|
||||
ivec3 probe_cell;
|
||||
probe_cell.x = probe.x % int(params.probe_axis_size);
|
||||
probe_cell.y = probe.y;
|
||||
probe_cell.z = probe.x / int(params.probe_axis_size);
|
||||
|
||||
#ifdef MODE_SCROLL_BEGIN
|
||||
|
||||
ivec3 read_cell = probe_cell - params.scroll;
|
||||
|
||||
uint src_layer = (params.history_size + 1) * params.cascade;
|
||||
uint dst_layer = (params.history_size + 1) * params.max_cascades;
|
||||
|
||||
for (uint i = 0; i <= params.history_size; i++) {
|
||||
ivec3 write_pos = ivec3(probe * OCT_RES + local, int(i));
|
||||
|
||||
if (any(lessThan(read_pos, ivec3(0))) || any(greaterThanEqual(read_pos, ivec3(params.probe_axis_size)))) {
|
||||
// nowhere to read from for scrolling, try finding the value from upper probes
|
||||
|
||||
#ifdef MODE_IRRADIANCE
|
||||
imageStore(irradiance_history_texture, write_pos, uvec4(0));
|
||||
#endif
|
||||
#ifdef MODE_DEPTH
|
||||
imageStore(depth_history_texture, write_pos, uvec4(0));
|
||||
#endif
|
||||
} else {
|
||||
ivec3 read_pos;
|
||||
read_pos.xy = read_cell.xy;
|
||||
read_pos.x += read_cell.z * params.probe_axis_size;
|
||||
read_pos.xy = read_pos.xy * OCT_RES + local;
|
||||
read_pos.z = int(i);
|
||||
|
||||
#ifdef MODE_IRRADIANCE
|
||||
uvec4 value = imageLoad(irradiance_history_texture, read_pos);
|
||||
imageStore(irradiance_history_texture, write_pos, value);
|
||||
#endif
|
||||
#ifdef MODE_DEPTH
|
||||
uvec2 value = imageLoad(depth_history_texture, read_pos);
|
||||
imageStore(depth_history_texture, write_pos, value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MODE_SCROLL_BEGIN
|
||||
|
||||
#ifdef MODE_SCROLL_END
|
||||
|
||||
uint src_layer = (params.history_size + 1) * params.max_cascades;
|
||||
uint dst_layer = (params.history_size + 1) * params.cascade;
|
||||
|
||||
for (uint i = 0; i <= params.history_size; i++) {
|
||||
ivec3 pos = ivec3(probe * OCT_RES + local, int(i));
|
||||
|
||||
#ifdef MODE_IRRADIANCE
|
||||
uvec4 value = imageLoad(irradiance_history_texture, read_pos);
|
||||
imageStore(irradiance_history_texture, write_pos, value);
|
||||
#endif
|
||||
#ifdef MODE_DEPTH
|
||||
uvec2 value = imageLoad(depth_history_texture, read_pos);
|
||||
imageStore(depth_history_texture, write_pos, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //MODE_SCROLL_END
|
||||
|
||||
#ifdef MODE_STORE
|
||||
|
||||
uint src_layer = (params.history_size + 1) * params.cascade + params.history_size;
|
||||
ivec3 read_pos = ivec3(probe * OCT_RES + local, int(src_layer));
|
||||
|
||||
ivec3 write_pos = ivec3(probe * (OCT_RES + 2) + ivec2(1), int(params.cascade));
|
||||
|
||||
ivec3 copy_to[4] = ivec3[](write_pos, ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2));
|
||||
|
||||
#ifdef MODE_IRRADIANCE
|
||||
uvec4 average = imageLoad(irradiance_history_texture, read_pos);
|
||||
vec4 light_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS);
|
||||
|
||||
#endif
|
||||
#ifdef MODE_DEPTH
|
||||
uvec2 value = imageLoad(depth_history_texture, read_pos);
|
||||
vec2 depth_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS);
|
||||
|
||||
float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
|
||||
float max_depth = length(params.grid_size / cascades.data[params.max_cascades - 1].to_cell);
|
||||
max_depth /= probe_cell_size;
|
||||
|
||||
depth_value = (vec2(average / params.history_size) / float(1 << DEPTH_HISTORY_BITS)) * vec2(max_depth, max_depth * max_depth);
|
||||
|
||||
#endif
|
||||
|
||||
/* Fill the border if required */
|
||||
|
||||
if (local == ivec2(0, 0)) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_RES - 1, -1, 0);
|
||||
copy_to[2] = texture_pos + ivec3(-1, OCT_RES - 1, 0);
|
||||
copy_to[3] = texture_pos + ivec3(OCT_RES, OCT_RES, 0);
|
||||
} else if (local == ivec2(OCT_RES - 1, 0)) {
|
||||
copy_to[1] = texture_pos + ivec3(0, -1, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_RES, OCT_RES - 1, 0);
|
||||
copy_to[3] = texture_pos + ivec3(-1, OCT_RES, 0);
|
||||
} else if (local == ivec2(0, OCT_RES - 1)) {
|
||||
copy_to[1] = texture_pos + ivec3(-1, 0, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_RES - 1, OCT_RES, 0);
|
||||
copy_to[3] = texture_pos + ivec3(OCT_RES, -1, 0);
|
||||
} else if (local == ivec2(OCT_RES - 1, OCT_RES - 1)) {
|
||||
copy_to[1] = texture_pos + ivec3(0, OCT_RES, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_RES, 0, 0);
|
||||
copy_to[3] = texture_pos + ivec3(-1, -1, 0);
|
||||
} else if (local.y == 0) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y - 1, 0);
|
||||
} else if (local.x == 0) {
|
||||
copy_to[1] = texture_pos + ivec3(local.x - 1, OCT_RES - local.y - 1, 0);
|
||||
} else if (local.y == OCT_RES - 1) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y + 1, 0);
|
||||
} else if (local.x == OCT_RES - 1) {
|
||||
copy_to[1] = texture_pos + ivec3(local.x + 1, OCT_RES - local.y - 1, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (copy_to[i] == ivec3(-2, -2, -2)) {
|
||||
continue;
|
||||
}
|
||||
#ifdef MODE_IRRADIANCE
|
||||
imageStore(irradiance_texture, copy_to[i], light_accum);
|
||||
#endif
|
||||
#ifdef MODE_DEPTH
|
||||
imageStore(depth_texture, copy_to[i], vec4(depth_value, 0.0, 0.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // MODE_STORE
|
||||
}
|
|
@ -0,0 +1,605 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
#define MAX_CASCADES 8
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 2) uniform texture3D light_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[MAX_CASCADES];
|
||||
layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[MAX_CASCADES];
|
||||
|
||||
layout(set = 0, binding = 6) uniform sampler linear_sampler;
|
||||
|
||||
struct CascadeData {
|
||||
vec3 offset; //offset of (0,0,0) in world coordinates
|
||||
float to_cell; // 1/bounds * grid_size
|
||||
ivec3 probe_world_offset;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) uniform Cascades {
|
||||
CascadeData data[MAX_CASCADES];
|
||||
}
|
||||
cascades;
|
||||
|
||||
layout(r32ui, set = 0, binding = 8) uniform restrict uimage2DArray lightprobe_texture_data;
|
||||
layout(rgba16i, set = 0, binding = 9) uniform restrict iimage2DArray lightprobe_history_texture;
|
||||
layout(rgba32i, set = 0, binding = 10) uniform restrict iimage2D lightprobe_average_texture;
|
||||
|
||||
//used for scrolling
|
||||
layout(rgba16i, set = 0, binding = 11) uniform restrict iimage2DArray lightprobe_history_scroll_texture;
|
||||
layout(rgba32i, set = 0, binding = 12) uniform restrict iimage2D lightprobe_average_scroll_texture;
|
||||
|
||||
layout(rgba32i, set = 0, binding = 13) uniform restrict iimage2D lightprobe_average_parent_texture;
|
||||
|
||||
layout(set = 1, binding = 0) uniform textureCube sky_irradiance;
|
||||
|
||||
layout(set = 1, binding = 1) uniform sampler linear_sampler_mipmaps;
|
||||
|
||||
#define HISTORY_BITS 10
|
||||
|
||||
#define SKY_MODE_DISABLED 0
|
||||
#define SKY_MODE_COLOR 1
|
||||
#define SKY_MODE_SKY 2
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
vec3 grid_size;
|
||||
uint max_cascades;
|
||||
|
||||
uint probe_axis_size;
|
||||
uint cascade;
|
||||
uint history_index;
|
||||
uint history_size;
|
||||
|
||||
uint ray_count;
|
||||
float ray_bias;
|
||||
ivec2 image_size;
|
||||
|
||||
ivec3 world_offset;
|
||||
uint sky_mode;
|
||||
|
||||
ivec3 scroll;
|
||||
float sky_energy;
|
||||
|
||||
vec3 sky_color;
|
||||
float y_mult;
|
||||
}
|
||||
params;
|
||||
|
||||
const float PI = 3.14159265f;
|
||||
const float GOLDEN_ANGLE = PI * (3.0 - sqrt(5.0));
|
||||
|
||||
vec3 vogel_hemisphere(uint p_index, uint p_count, float p_offset) {
|
||||
float r = sqrt(float(p_index) + 0.5f) / sqrt(float(p_count));
|
||||
float theta = float(p_index) * GOLDEN_ANGLE + p_offset;
|
||||
float y = cos(r * PI * 0.5);
|
||||
float l = sin(r * PI * 0.5);
|
||||
return vec3(l * cos(theta), l * sin(theta), y * (float(p_index & 1) * 2.0 - 1.0));
|
||||
}
|
||||
|
||||
uvec3 hash3(uvec3 x) {
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = (x >> 16) ^ x;
|
||||
return x;
|
||||
}
|
||||
|
||||
float hashf3(vec3 co) {
|
||||
return fract(sin(dot(co, vec3(12.9898, 78.233, 137.13451))) * 43758.5453);
|
||||
}
|
||||
|
||||
vec3 octahedron_encode(vec2 f) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
f = f * 2.0 - 1.0;
|
||||
vec3 n = vec3(f.x, f.y, 1.0f - abs(f.x) - abs(f.y));
|
||||
float t = clamp(-n.z, 0.0, 1.0);
|
||||
n.x += n.x >= 0 ? -t : t;
|
||||
n.y += n.y >= 0 ? -t : t;
|
||||
return normalize(n);
|
||||
}
|
||||
|
||||
uint rgbe_encode(vec3 color) {
|
||||
const float pow2to9 = 512.0f;
|
||||
const float B = 15.0f;
|
||||
const float N = 9.0f;
|
||||
const float LN2 = 0.6931471805599453094172321215;
|
||||
|
||||
float cRed = clamp(color.r, 0.0, 65408.0);
|
||||
float cGreen = clamp(color.g, 0.0, 65408.0);
|
||||
float cBlue = clamp(color.b, 0.0, 65408.0);
|
||||
|
||||
float cMax = max(cRed, max(cGreen, cBlue));
|
||||
|
||||
float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
|
||||
|
||||
float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
|
||||
|
||||
float exps = expp + 1.0f;
|
||||
|
||||
if (0.0 <= sMax && sMax < pow2to9) {
|
||||
exps = expp;
|
||||
}
|
||||
|
||||
float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
return (uint(sRed) & 0x1FF) | ((uint(sGreen) & 0x1FF) << 9) | ((uint(sBlue) & 0x1FF) << 18) | ((uint(exps) & 0x1F) << 27);
|
||||
}
|
||||
|
||||
void main() {
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(pos, params.image_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MODE_PROCESS
|
||||
|
||||
float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
|
||||
|
||||
ivec3 probe_cell;
|
||||
probe_cell.x = pos.x % int(params.probe_axis_size);
|
||||
probe_cell.y = pos.y;
|
||||
probe_cell.z = pos.x / int(params.probe_axis_size);
|
||||
|
||||
vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size;
|
||||
vec3 pos_to_uvw = 1.0 / params.grid_size;
|
||||
|
||||
vec4 probe_sh_accum[SH_SIZE] = vec4[](
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0)
|
||||
#if (SH_SIZE == 16)
|
||||
,
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0),
|
||||
vec4(0.0)
|
||||
#endif
|
||||
);
|
||||
|
||||
// quickly ensure each probe has a different "offset" for the vogel function, based on integer world position
|
||||
uvec3 h3 = hash3(uvec3(params.world_offset + probe_cell));
|
||||
float offset = hashf3(vec3(h3 & uvec3(0xFFFFF)));
|
||||
|
||||
//for a more homogeneous hemisphere, alternate based on history frames
|
||||
uint ray_offset = params.history_index;
|
||||
uint ray_mult = params.history_size;
|
||||
uint ray_total = ray_mult * params.ray_count;
|
||||
|
||||
for (uint i = 0; i < params.ray_count; i++) {
|
||||
vec3 ray_dir = vogel_hemisphere(ray_offset + i * ray_mult, ray_total, offset);
|
||||
ray_dir.y *= params.y_mult;
|
||||
ray_dir = normalize(ray_dir);
|
||||
|
||||
//needs to be visible
|
||||
vec3 ray_pos = probe_pos;
|
||||
vec3 inv_dir = 1.0 / ray_dir;
|
||||
|
||||
bool hit = false;
|
||||
vec3 hit_normal;
|
||||
vec3 hit_light;
|
||||
vec3 hit_aniso0;
|
||||
vec3 hit_aniso1;
|
||||
|
||||
float bias = params.ray_bias;
|
||||
vec3 abs_ray_dir = abs(ray_dir);
|
||||
ray_pos += ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) * bias / cascades.data[params.cascade].to_cell;
|
||||
|
||||
for (uint j = params.cascade; j < params.max_cascades; j++) {
|
||||
//convert to local bounds
|
||||
vec3 pos = ray_pos - cascades.data[j].offset;
|
||||
pos *= cascades.data[j].to_cell;
|
||||
|
||||
if (any(lessThan(pos, vec3(0.0))) || any(greaterThanEqual(pos, params.grid_size))) {
|
||||
continue; //already past bounds for this cascade, goto next
|
||||
}
|
||||
|
||||
//find maximum advance distance (until reaching bounds)
|
||||
vec3 t0 = -pos * inv_dir;
|
||||
vec3 t1 = (params.grid_size - pos) * inv_dir;
|
||||
vec3 tmax = max(t0, t1);
|
||||
float max_advance = min(tmax.x, min(tmax.y, tmax.z));
|
||||
|
||||
float advance = 0.0;
|
||||
|
||||
vec3 uvw;
|
||||
|
||||
while (advance < max_advance) {
|
||||
//read how much to advance from SDF
|
||||
uvw = (pos + ray_dir * advance) * pos_to_uvw;
|
||||
|
||||
float distance = texture(sampler3D(sdf_cascades[j], linear_sampler), uvw).r * 255.0 - 1.0;
|
||||
if (distance < 0.001) {
|
||||
//consider hit
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
advance += distance;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
const float EPSILON = 0.001;
|
||||
hit_normal = normalize(vec3(
|
||||
texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
|
||||
texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
|
||||
texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
|
||||
|
||||
hit_light = texture(sampler3D(light_cascades[j], linear_sampler), uvw).rgb;
|
||||
vec4 aniso0 = texture(sampler3D(aniso0_cascades[j], linear_sampler), uvw);
|
||||
hit_aniso0 = aniso0.rgb;
|
||||
hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[j], linear_sampler), uvw).rg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//change ray origin to collision with bounds
|
||||
pos += ray_dir * max_advance;
|
||||
pos /= cascades.data[j].to_cell;
|
||||
pos += cascades.data[j].offset;
|
||||
ray_pos = pos;
|
||||
}
|
||||
|
||||
vec4 light;
|
||||
if (hit) {
|
||||
//one liner magic
|
||||
light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
|
||||
light.a = 1.0;
|
||||
} else if (params.sky_mode == SKY_MODE_SKY) {
|
||||
light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates
|
||||
light.rgb *= params.sky_energy;
|
||||
light.a = 0.0;
|
||||
|
||||
} else if (params.sky_mode == SKY_MODE_COLOR) {
|
||||
light.rgb = params.sky_color;
|
||||
light.rgb *= params.sky_energy;
|
||||
light.a = 0.0;
|
||||
} else {
|
||||
light = vec4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
vec3 ray_dir2 = ray_dir * ray_dir;
|
||||
float c[SH_SIZE] = float[](
|
||||
|
||||
0.282095, //l0
|
||||
0.488603 * ray_dir.y, //l1n1
|
||||
0.488603 * ray_dir.z, //l1n0
|
||||
0.488603 * ray_dir.x, //l1p1
|
||||
1.092548 * ray_dir.x * ray_dir.y, //l2n2
|
||||
1.092548 * ray_dir.y * ray_dir.z, //l2n1
|
||||
0.315392 * (3.0 * ray_dir2.z - 1.0), //l20
|
||||
1.092548 * ray_dir.x * ray_dir.z, //l2p1
|
||||
0.546274 * (ray_dir2.x - ray_dir2.y) //l2p2
|
||||
#if (SH_SIZE == 16)
|
||||
,
|
||||
0.590043 * ray_dir.y * (3.0f * ray_dir2.x - ray_dir2.y),
|
||||
2.890611 * ray_dir.y * ray_dir.x * ray_dir.z,
|
||||
0.646360 * ray_dir.y * (-1.0f + 5.0f * ray_dir2.z),
|
||||
0.373176 * (5.0f * ray_dir2.z * ray_dir.z - 3.0f * ray_dir.z),
|
||||
0.457045 * ray_dir.x * (-1.0f + 5.0f * ray_dir2.z),
|
||||
1.445305 * (ray_dir2.x - ray_dir2.y) * ray_dir.z,
|
||||
0.590043 * ray_dir.x * (ray_dir2.x - 3.0f * ray_dir2.y)
|
||||
|
||||
#endif
|
||||
);
|
||||
|
||||
for (uint j = 0; j < SH_SIZE; j++) {
|
||||
probe_sh_accum[j] += light * c[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < SH_SIZE; i++) {
|
||||
// store in history texture
|
||||
ivec3 prev_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(params.history_index));
|
||||
ivec2 average_pos = prev_pos.xy;
|
||||
|
||||
vec4 value = probe_sh_accum[i] * 4.0 / float(params.ray_count);
|
||||
|
||||
ivec4 ivalue = clamp(ivec4(value * float(1 << HISTORY_BITS)), -32768, 32767); //clamp to 16 bits, so higher values don't break average
|
||||
|
||||
ivec4 prev_value = imageLoad(lightprobe_history_texture, prev_pos);
|
||||
ivec4 average = imageLoad(lightprobe_average_texture, average_pos);
|
||||
|
||||
average -= prev_value;
|
||||
average += ivalue;
|
||||
|
||||
imageStore(lightprobe_history_texture, prev_pos, ivalue);
|
||||
imageStore(lightprobe_average_texture, average_pos, average);
|
||||
}
|
||||
#endif // MODE PROCESS
|
||||
|
||||
#ifdef MODE_STORE
|
||||
|
||||
// converting to octahedral in this step is requiered because
|
||||
// octahedral is much faster to read from the screen than spherical harmonics,
|
||||
// despite the very slight quality loss
|
||||
|
||||
ivec2 sh_pos = (pos / OCT_SIZE) * ivec2(1, SH_SIZE);
|
||||
ivec2 oct_pos = (pos / OCT_SIZE) * (OCT_SIZE + 2) + ivec2(1);
|
||||
ivec2 local_pos = pos % OCT_SIZE;
|
||||
|
||||
//fill the spherical harmonic
|
||||
vec4 sh[SH_SIZE];
|
||||
|
||||
for (uint i = 0; i < SH_SIZE; i++) {
|
||||
// store in history texture
|
||||
ivec2 average_pos = sh_pos + ivec2(0, i);
|
||||
ivec4 average = imageLoad(lightprobe_average_texture, average_pos);
|
||||
|
||||
sh[i] = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS);
|
||||
}
|
||||
|
||||
//compute the octahedral normal for this texel
|
||||
vec3 normal = octahedron_encode(vec2(local_pos) / float(OCT_SIZE));
|
||||
/*
|
||||
// read the spherical harmonic
|
||||
const float c1 = 0.429043;
|
||||
const float c2 = 0.511664;
|
||||
const float c3 = 0.743125;
|
||||
const float c4 = 0.886227;
|
||||
const float c5 = 0.247708;
|
||||
vec4 light = (c1 * sh[8] * (normal.x * normal.x - normal.y * normal.y) +
|
||||
c3 * sh[6] * normal.z * normal.z +
|
||||
c4 * sh[0] -
|
||||
c5 * sh[6] +
|
||||
2.0 * c1 * sh[4] * normal.x * normal.y +
|
||||
2.0 * c1 * sh[7] * normal.x * normal.z +
|
||||
2.0 * c1 * sh[5] * normal.y * normal.z +
|
||||
2.0 * c2 * sh[3] * normal.x +
|
||||
2.0 * c2 * sh[1] * normal.y +
|
||||
2.0 * c2 * sh[2] * normal.z);
|
||||
*/
|
||||
vec3 normal2 = normal * normal;
|
||||
float c[SH_SIZE] = float[](
|
||||
|
||||
0.282095, //l0
|
||||
0.488603 * normal.y, //l1n1
|
||||
0.488603 * normal.z, //l1n0
|
||||
0.488603 * normal.x, //l1p1
|
||||
1.092548 * normal.x * normal.y, //l2n2
|
||||
1.092548 * normal.y * normal.z, //l2n1
|
||||
0.315392 * (3.0 * normal2.z - 1.0), //l20
|
||||
1.092548 * normal.x * normal.z, //l2p1
|
||||
0.546274 * (normal2.x - normal2.y) //l2p2
|
||||
#if (SH_SIZE == 16)
|
||||
,
|
||||
0.590043 * normal.y * (3.0f * normal2.x - normal2.y),
|
||||
2.890611 * normal.y * normal.x * normal.z,
|
||||
0.646360 * normal.y * (-1.0f + 5.0f * normal2.z),
|
||||
0.373176 * (5.0f * normal2.z * normal.z - 3.0f * normal.z),
|
||||
0.457045 * normal.x * (-1.0f + 5.0f * normal2.z),
|
||||
1.445305 * (normal2.x - normal2.y) * normal.z,
|
||||
0.590043 * normal.x * (normal2.x - 3.0f * normal2.y)
|
||||
|
||||
#endif
|
||||
);
|
||||
|
||||
const float l_mult[SH_SIZE] = float[](
|
||||
1.0,
|
||||
2.0 / 3.0,
|
||||
2.0 / 3.0,
|
||||
2.0 / 3.0,
|
||||
1.0 / 4.0,
|
||||
1.0 / 4.0,
|
||||
1.0 / 4.0,
|
||||
1.0 / 4.0,
|
||||
1.0 / 4.0
|
||||
#if (SH_SIZE == 16)
|
||||
, // l4 does not contribute to irradiance
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
#endif
|
||||
);
|
||||
|
||||
vec3 irradiance = vec3(0.0);
|
||||
vec3 radiance = vec3(0.0);
|
||||
|
||||
for (uint i = 0; i < SH_SIZE; i++) {
|
||||
vec3 m = sh[i].rgb * c[i] * 4.0;
|
||||
irradiance += m * l_mult[i];
|
||||
radiance += m;
|
||||
}
|
||||
|
||||
//encode RGBE9995 for the final texture
|
||||
|
||||
uint irradiance_rgbe = rgbe_encode(irradiance);
|
||||
uint radiance_rgbe = rgbe_encode(radiance);
|
||||
|
||||
//store in octahedral map
|
||||
|
||||
ivec3 texture_pos = ivec3(oct_pos, int(params.cascade));
|
||||
ivec3 copy_to[4] = ivec3[](ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2));
|
||||
copy_to[0] = texture_pos + ivec3(local_pos, 0);
|
||||
|
||||
if (local_pos == ivec2(0, 0)) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_SIZE - 1, -1, 0);
|
||||
copy_to[2] = texture_pos + ivec3(-1, OCT_SIZE - 1, 0);
|
||||
copy_to[3] = texture_pos + ivec3(OCT_SIZE, OCT_SIZE, 0);
|
||||
} else if (local_pos == ivec2(OCT_SIZE - 1, 0)) {
|
||||
copy_to[1] = texture_pos + ivec3(0, -1, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_SIZE, OCT_SIZE - 1, 0);
|
||||
copy_to[3] = texture_pos + ivec3(-1, OCT_SIZE, 0);
|
||||
} else if (local_pos == ivec2(0, OCT_SIZE - 1)) {
|
||||
copy_to[1] = texture_pos + ivec3(-1, 0, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_SIZE - 1, OCT_SIZE, 0);
|
||||
copy_to[3] = texture_pos + ivec3(OCT_SIZE, -1, 0);
|
||||
} else if (local_pos == ivec2(OCT_SIZE - 1, OCT_SIZE - 1)) {
|
||||
copy_to[1] = texture_pos + ivec3(0, OCT_SIZE, 0);
|
||||
copy_to[2] = texture_pos + ivec3(OCT_SIZE, 0, 0);
|
||||
copy_to[3] = texture_pos + ivec3(-1, -1, 0);
|
||||
} else if (local_pos.y == 0) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_SIZE - local_pos.x - 1, local_pos.y - 1, 0);
|
||||
} else if (local_pos.x == 0) {
|
||||
copy_to[1] = texture_pos + ivec3(local_pos.x - 1, OCT_SIZE - local_pos.y - 1, 0);
|
||||
} else if (local_pos.y == OCT_SIZE - 1) {
|
||||
copy_to[1] = texture_pos + ivec3(OCT_SIZE - local_pos.x - 1, local_pos.y + 1, 0);
|
||||
} else if (local_pos.x == OCT_SIZE - 1) {
|
||||
copy_to[1] = texture_pos + ivec3(local_pos.x + 1, OCT_SIZE - local_pos.y - 1, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (copy_to[i] == ivec3(-2, -2, -2)) {
|
||||
continue;
|
||||
}
|
||||
imageStore(lightprobe_texture_data, copy_to[i], uvec4(irradiance_rgbe));
|
||||
imageStore(lightprobe_texture_data, copy_to[i] + ivec3(0, 0, int(params.max_cascades)), uvec4(radiance_rgbe));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SCROLL
|
||||
|
||||
ivec3 probe_cell;
|
||||
probe_cell.x = pos.x % int(params.probe_axis_size);
|
||||
probe_cell.y = pos.y;
|
||||
probe_cell.z = pos.x / int(params.probe_axis_size);
|
||||
|
||||
ivec3 read_probe = probe_cell - params.scroll;
|
||||
|
||||
if (all(greaterThanEqual(read_probe, ivec3(0))) && all(lessThan(read_probe, ivec3(params.probe_axis_size)))) {
|
||||
// can scroll
|
||||
ivec2 tex_pos;
|
||||
tex_pos = read_probe.xy;
|
||||
tex_pos.x += read_probe.z * int(params.probe_axis_size);
|
||||
|
||||
//scroll
|
||||
for (uint j = 0; j < params.history_size; j++) {
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from history texture
|
||||
ivec3 src_pos = ivec3(tex_pos.x, tex_pos.y * SH_SIZE + i, int(j));
|
||||
ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j));
|
||||
ivec4 value = imageLoad(lightprobe_history_texture, src_pos);
|
||||
imageStore(lightprobe_history_scroll_texture, dst_pos, value);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from average texture
|
||||
ivec2 src_pos = ivec2(tex_pos.x, tex_pos.y * SH_SIZE + i);
|
||||
ivec2 dst_pos = ivec2(pos.x, pos.y * SH_SIZE + i);
|
||||
ivec4 value = imageLoad(lightprobe_average_texture, src_pos);
|
||||
imageStore(lightprobe_average_scroll_texture, dst_pos, value);
|
||||
}
|
||||
} else if (params.cascade < params.max_cascades - 1) {
|
||||
//cant scroll, must look for position in parent cascade
|
||||
|
||||
//to global coords
|
||||
float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
|
||||
vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size;
|
||||
|
||||
//to parent local coords
|
||||
probe_pos -= cascades.data[params.cascade + 1].offset;
|
||||
probe_pos *= cascades.data[params.cascade + 1].to_cell;
|
||||
probe_pos = probe_pos * float(params.probe_axis_size - 1) / float(params.grid_size.x);
|
||||
|
||||
ivec3 probe_posi = ivec3(probe_pos);
|
||||
//add up all light, no need to use occlusion here, since occlusion will do its work afterwards
|
||||
|
||||
vec4 average_light[SH_SIZE] = vec4[](vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0)
|
||||
#if (SH_SIZE == 16)
|
||||
,
|
||||
vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0)
|
||||
#endif
|
||||
);
|
||||
float total_weight = 0.0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ivec3 offset = probe_posi + ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1));
|
||||
|
||||
vec3 trilinear = vec3(1.0) - abs(probe_pos - vec3(offset));
|
||||
float weight = trilinear.x * trilinear.y * trilinear.z;
|
||||
|
||||
ivec2 tex_pos;
|
||||
tex_pos = offset.xy;
|
||||
tex_pos.x += offset.z * int(params.probe_axis_size);
|
||||
|
||||
for (int j = 0; j < SH_SIZE; j++) {
|
||||
// copy from history texture
|
||||
ivec2 src_pos = ivec2(tex_pos.x, tex_pos.y * SH_SIZE + j);
|
||||
ivec4 average = imageLoad(lightprobe_average_parent_texture, src_pos);
|
||||
vec4 value = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS);
|
||||
average_light[j] += value * weight;
|
||||
}
|
||||
|
||||
total_weight += weight;
|
||||
}
|
||||
|
||||
if (total_weight > 0.0) {
|
||||
total_weight = 1.0 / total_weight;
|
||||
}
|
||||
//store the averaged values everywhere
|
||||
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
ivec4 ivalue = clamp(ivec4(average_light[i] * total_weight * float(1 << HISTORY_BITS)), ivec4(-32768), ivec4(32767)); //clamp to 16 bits, so higher values don't break average
|
||||
// copy from history texture
|
||||
ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, 0);
|
||||
for (uint j = 0; j < params.history_size; j++) {
|
||||
dst_pos.z = int(j);
|
||||
imageStore(lightprobe_history_scroll_texture, dst_pos, ivalue);
|
||||
}
|
||||
|
||||
ivalue *= int(params.history_size); //average needs to have all history added up
|
||||
imageStore(lightprobe_average_scroll_texture, dst_pos.xy, ivalue);
|
||||
}
|
||||
|
||||
} else {
|
||||
// clear and let it re-raytrace, only for the last cascade, which happens very un-often
|
||||
//scroll
|
||||
for (uint j = 0; j < params.history_size; j++) {
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from history texture
|
||||
ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j));
|
||||
imageStore(lightprobe_history_scroll_texture, dst_pos, ivec4(0));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from average texture
|
||||
ivec2 dst_pos = ivec2(pos.x, pos.y * SH_SIZE + i);
|
||||
imageStore(lightprobe_average_scroll_texture, dst_pos, ivec4(0));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SCROLL_STORE
|
||||
|
||||
//do not update probe texture, as these will be updated later
|
||||
|
||||
for (uint j = 0; j < params.history_size; j++) {
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from history texture
|
||||
ivec3 spos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j));
|
||||
ivec4 value = imageLoad(lightprobe_history_scroll_texture, spos);
|
||||
imageStore(lightprobe_history_texture, spos, value);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SH_SIZE; i++) {
|
||||
// copy from average texture
|
||||
ivec2 spos = ivec2(pos.x, pos.y * SH_SIZE + i);
|
||||
ivec4 average = imageLoad(lightprobe_average_scroll_texture, spos);
|
||||
imageStore(lightprobe_average_texture, spos, average);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -212,10 +212,14 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p
|
|||
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags);
|
||||
}
|
||||
|
||||
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
|
||||
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
|
||||
Vector<DrawListID> splits;
|
||||
splits.resize(p_splits);
|
||||
draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region);
|
||||
Vector<RID> stextures;
|
||||
for (int i = 0; i < p_storage_textures.size(); i++) {
|
||||
stextures.push_back(p_storage_textures[i]);
|
||||
}
|
||||
draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, stextures);
|
||||
|
||||
Vector<int64_t> split_ids;
|
||||
split_ids.resize(splits.size());
|
||||
|
@ -236,6 +240,10 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons
|
|||
compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
|
||||
}
|
||||
|
||||
void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group) {
|
||||
compute_list_dispatch(p_list, (p_x_threads - 1) / p_x_local_group + 1, (p_y_threads - 1) / p_y_local_group + 1, (p_z_threads - 1) / p_z_local_group + 1);
|
||||
}
|
||||
|
||||
void RenderingDevice::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
|
||||
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
|
||||
|
@ -254,8 +262,10 @@ void RenderingDevice::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "sync_with_draw"), &RenderingDevice::texture_resolve_multisample, DEFVAL(false));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create);
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "size"), &RenderingDevice::framebuffer_format_create_empty);
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples);
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(INVALID_FORMAT_ID));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
|
||||
|
@ -292,8 +302,8 @@ void RenderingDevice::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()));
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()));
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
|
||||
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
|
||||
|
@ -625,6 +635,8 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16);
|
||||
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32);
|
||||
|
||||
BIND_ENUM_CONSTANT(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
|
||||
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type)
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE); //only texture); (textureXX GLSL type)
|
||||
|
|
|
@ -467,9 +467,11 @@ public:
|
|||
|
||||
// This ID is warranted to be unique for the same formats, does not need to be freed
|
||||
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format) = 0;
|
||||
virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size) = 0;
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
|
||||
|
||||
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0;
|
||||
virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID) = 0;
|
||||
|
||||
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
|
||||
|
||||
|
@ -618,8 +620,12 @@ public:
|
|||
UNIFORM_TYPE_MAX
|
||||
};
|
||||
|
||||
enum StorageBufferUsage {
|
||||
STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1
|
||||
};
|
||||
|
||||
virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0;
|
||||
virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0;
|
||||
virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0) = 0;
|
||||
virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0;
|
||||
|
||||
struct Uniform {
|
||||
|
@ -940,8 +946,8 @@ public:
|
|||
typedef int64_t DrawListID;
|
||||
|
||||
virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()) = 0;
|
||||
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0;
|
||||
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0;
|
||||
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
|
||||
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
|
||||
|
||||
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
|
||||
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
|
||||
|
@ -968,10 +974,14 @@ public:
|
|||
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
|
||||
virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) = 0;
|
||||
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0;
|
||||
virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group);
|
||||
virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) = 0;
|
||||
virtual void compute_list_add_barrier(ComputeListID p_list) = 0;
|
||||
|
||||
virtual void compute_list_end() = 0;
|
||||
|
||||
virtual void full_barrier() = 0;
|
||||
|
||||
/***************/
|
||||
/**** FREE! ****/
|
||||
/***************/
|
||||
|
@ -1070,7 +1080,7 @@ protected:
|
|||
|
||||
RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
|
||||
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
|
||||
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
|
||||
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
||||
void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
||||
};
|
||||
|
@ -1089,6 +1099,7 @@ VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode)
|
|||
VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::StorageBufferUsage)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::UniformType)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode)
|
||||
|
|
|
@ -222,6 +222,10 @@ bool RenderingServerRaster::has_feature(Features p_feature) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void RenderingServerRaster::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
|
||||
RSG::scene_render->sdfgi_set_debug_probe_select(p_position, p_dir);
|
||||
}
|
||||
|
||||
RID RenderingServerRaster::get_test_cube() {
|
||||
if (!test_cube.is_valid()) {
|
||||
test_cube = _make_test_cube();
|
||||
|
|
|
@ -322,7 +322,8 @@ public:
|
|||
BIND2(light_set_negative, RID, bool)
|
||||
BIND2(light_set_cull_mask, RID, uint32_t)
|
||||
BIND2(light_set_reverse_cull_face_mode, RID, bool)
|
||||
BIND2(light_set_use_gi, RID, bool)
|
||||
BIND2(light_set_bake_mode, RID, LightBakeMode)
|
||||
BIND2(light_set_max_sdfgi_cascade, RID, uint32_t)
|
||||
|
||||
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
|
||||
|
||||
|
@ -336,9 +337,9 @@ public:
|
|||
|
||||
BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
|
||||
BIND2(reflection_probe_set_intensity, RID, float)
|
||||
BIND2(reflection_probe_set_interior_ambient, RID, const Color &)
|
||||
BIND2(reflection_probe_set_interior_ambient_energy, RID, float)
|
||||
BIND2(reflection_probe_set_interior_ambient_probe_contribution, RID, float)
|
||||
BIND2(reflection_probe_set_ambient_color, RID, const Color &)
|
||||
BIND2(reflection_probe_set_ambient_energy, RID, float)
|
||||
BIND2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
|
||||
BIND2(reflection_probe_set_max_distance, RID, float)
|
||||
BIND2(reflection_probe_set_extents, RID, const Vector3 &)
|
||||
BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &)
|
||||
|
@ -523,6 +524,7 @@ public:
|
|||
#define BINDBASE RSG::scene_render
|
||||
|
||||
BIND1(directional_shadow_atlas_set_size, int)
|
||||
BIND1(gi_probe_set_quality, GIProbeQuality)
|
||||
|
||||
/* SKY API */
|
||||
|
||||
|
@ -564,9 +566,13 @@ public:
|
|||
BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
|
||||
BIND5(environment_set_fog_height, RID, bool, float, float, float)
|
||||
|
||||
BIND12(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, bool, float, float, float)
|
||||
BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
|
||||
BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
|
||||
|
||||
BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
|
||||
|
||||
BIND2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
BIND3(screen_space_roughness_limiter_set_active, bool, float, float)
|
||||
BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
|
||||
BIND2(sub_surface_scattering_set_scale, float, float)
|
||||
|
||||
|
@ -793,6 +799,8 @@ public:
|
|||
|
||||
virtual bool is_low_end() const;
|
||||
|
||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
|
||||
|
||||
RenderingServerRaster();
|
||||
~RenderingServerRaster();
|
||||
|
||||
|
|
|
@ -369,6 +369,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
|
|||
switch (instance->base_type) {
|
||||
case RS::INSTANCE_LIGHT: {
|
||||
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
|
||||
|
||||
if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
|
||||
instance->scenario->dynamic_lights.erase(light->instance);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (light->geometries.size()) {
|
||||
ERR_PRINT("BUG, indexing did not unpair geometries from light.");
|
||||
|
@ -976,7 +981,26 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
|||
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
|
||||
|
||||
RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform);
|
||||
RSG::scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
|
||||
light->shadow_dirty = true;
|
||||
|
||||
RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
|
||||
if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
|
||||
if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
|
||||
p_instance->scenario->dynamic_lights.erase(light->instance);
|
||||
}
|
||||
|
||||
light->bake_mode = bake_mode;
|
||||
|
||||
if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
|
||||
p_instance->scenario->dynamic_lights.push_back(light->instance);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
|
||||
if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
|
||||
light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
|
||||
}
|
||||
}
|
||||
|
||||
if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
|
||||
|
@ -1788,8 +1812,10 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
|
|||
} break;
|
||||
}
|
||||
|
||||
_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
RID environment = _render_get_environment(p_camera, p_scenario);
|
||||
|
||||
_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1808,6 +1834,8 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface>
|
|||
Transform world_origin = XRServer::get_singleton()->get_world_origin();
|
||||
Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
|
||||
|
||||
RID environment = _render_get_environment(p_camera, p_scenario);
|
||||
|
||||
// For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
|
||||
if (p_eye == XRInterface::EYE_LEFT) {
|
||||
// Center our transform, we assume basis is equal.
|
||||
|
@ -1865,17 +1893,17 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface>
|
|||
mono_transform *= apply_z_shift;
|
||||
|
||||
// now prepare our scene with our adjusted transform projection matrix
|
||||
_prepare_scene(mono_transform, combined_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
} else if (p_eye == XRInterface::EYE_MONO) {
|
||||
// For mono render, prepare as per usual
|
||||
_prepare_scene(cam_transform, camera_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
}
|
||||
|
||||
// And render our scene...
|
||||
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
};
|
||||
|
||||
void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
|
||||
void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
|
||||
// Note, in stereo rendering:
|
||||
// - p_cam_transform will be a transform in the middle of our two eyes
|
||||
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
||||
|
@ -1887,6 +1915,10 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||
|
||||
RSG::scene_render->set_scene_pass(render_pass);
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
RSG::scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Frustum Culling");
|
||||
|
||||
//rasterizer->set_camera(camera->transform, camera_matrix,ortho);
|
||||
|
@ -2224,22 +2256,97 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* UPDATE SDFGI */
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
uint32_t cascade_index[8];
|
||||
uint32_t cascade_sizes[8];
|
||||
const RID *cascade_ptrs[8];
|
||||
uint32_t cascade_count = 0;
|
||||
uint32_t sdfgi_light_cull_count = 0;
|
||||
|
||||
uint32_t prev_cascade = 0xFFFFFFFF;
|
||||
for (int i = 0; i < RSG::scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) {
|
||||
AABB region = RSG::scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i);
|
||||
uint32_t region_cascade = RSG::scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);
|
||||
|
||||
if (region_cascade != prev_cascade) {
|
||||
cascade_sizes[cascade_count] = 0;
|
||||
cascade_index[cascade_count] = region_cascade;
|
||||
cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count];
|
||||
cascade_count++;
|
||||
sdfgi_light_cull_pass++;
|
||||
prev_cascade = region_cascade;
|
||||
}
|
||||
uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL);
|
||||
|
||||
for (uint32_t j = 0; j < sdfgi_cull_count; j++) {
|
||||
Instance *ins = instance_shadow_cull_result[j];
|
||||
|
||||
bool keep = false;
|
||||
|
||||
if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
|
||||
InstanceLightData *instance_light = (InstanceLightData *)ins->base_data;
|
||||
if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) {
|
||||
instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass;
|
||||
sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance;
|
||||
cascade_sizes[cascade_count - 1]++;
|
||||
}
|
||||
} else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
|
||||
if (ins->baked_light) {
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!keep) {
|
||||
// remove, no reason to keep
|
||||
sdfgi_cull_count--;
|
||||
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
RSG::scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count);
|
||||
//have to save updated cascades, then update static lights.
|
||||
}
|
||||
|
||||
if (sdfgi_light_cull_count) {
|
||||
RSG::scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes);
|
||||
}
|
||||
|
||||
RSG::scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
||||
|
||||
/* ENVIRONMENT */
|
||||
|
||||
RID environment;
|
||||
if (p_force_environment.is_valid()) { //camera has more environment priority
|
||||
environment = p_force_environment;
|
||||
} else if (scenario->environment.is_valid()) {
|
||||
environment = scenario->environment;
|
||||
} else {
|
||||
environment = scenario->fallback_environment;
|
||||
RID RenderingServerScene::_render_get_environment(RID p_camera, RID p_scenario) {
|
||||
Camera *camera = camera_owner.getornull(p_camera);
|
||||
if (camera && RSG::scene_render->is_environment(camera->env)) {
|
||||
return camera->env;
|
||||
}
|
||||
|
||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
||||
if (!scenario) {
|
||||
return RID();
|
||||
}
|
||||
if (RSG::scene_render->is_environment(scenario->environment)) {
|
||||
return scenario->environment;
|
||||
}
|
||||
|
||||
if (RSG::scene_render->is_environment(scenario->fallback_environment)) {
|
||||
return scenario->fallback_environment;
|
||||
}
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
||||
|
||||
RID camera_effects;
|
||||
if (p_force_camera_effects.is_valid()) {
|
||||
camera_effects = p_force_camera_effects;
|
||||
|
@ -2249,7 +2356,7 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p
|
|||
/* PROCESS GEOMETRY AND DRAW SCENE */
|
||||
|
||||
RENDER_TIMESTAMP("Render Scene ");
|
||||
RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
}
|
||||
|
||||
void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
|
||||
#include "core/local_vector.h"
|
||||
#include "core/math/geometry_3d.h"
|
||||
#include "core/math/octree.h"
|
||||
#include "core/os/semaphore.h"
|
||||
#include "core/os/thread.h"
|
||||
|
@ -121,6 +123,8 @@ public:
|
|||
|
||||
SelfList<Instance>::List instances;
|
||||
|
||||
LocalVector<RID> dynamic_lights;
|
||||
|
||||
Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
|
||||
};
|
||||
|
||||
|
@ -309,7 +313,13 @@ public:
|
|||
|
||||
Instance *baked_light;
|
||||
|
||||
RS::LightBakeMode bake_mode;
|
||||
uint32_t max_sdfgi_cascade = 2;
|
||||
|
||||
uint64_t sdfgi_cascade_light_pass = 0;
|
||||
|
||||
InstanceLightData() {
|
||||
bake_mode = RS::LIGHT_BAKE_DISABLED;
|
||||
shadow_dirty = true;
|
||||
D = nullptr;
|
||||
last_version = 0;
|
||||
|
@ -379,7 +389,9 @@ public:
|
|||
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
||||
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
|
||||
Instance *light_cull_result[MAX_LIGHTS_CULLED];
|
||||
RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED];
|
||||
RID light_instance_cull_result[MAX_LIGHTS_CULLED];
|
||||
uint64_t sdfgi_light_cull_pass = 0;
|
||||
int light_cull_count;
|
||||
int directional_light_count;
|
||||
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
|
||||
|
@ -438,9 +450,11 @@ public:
|
|||
|
||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
|
||||
|
||||
RID _render_get_environment(RID p_camera, RID p_scenario);
|
||||
|
||||
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
|
||||
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
||||
|
|
|
@ -237,7 +237,8 @@ public:
|
|||
FUNC2(light_set_negative, RID, bool)
|
||||
FUNC2(light_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
|
||||
FUNC2(light_set_use_gi, RID, bool)
|
||||
FUNC2(light_set_bake_mode, RID, LightBakeMode)
|
||||
FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
|
||||
|
||||
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
|
||||
|
||||
|
@ -251,9 +252,9 @@ public:
|
|||
|
||||
FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
|
||||
FUNC2(reflection_probe_set_intensity, RID, float)
|
||||
FUNC2(reflection_probe_set_interior_ambient, RID, const Color &)
|
||||
FUNC2(reflection_probe_set_interior_ambient_energy, RID, float)
|
||||
FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float)
|
||||
FUNC2(reflection_probe_set_ambient_color, RID, const Color &)
|
||||
FUNC2(reflection_probe_set_ambient_energy, RID, float)
|
||||
FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
|
||||
FUNC2(reflection_probe_set_max_distance, RID, float)
|
||||
FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
|
||||
FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
|
||||
|
@ -321,6 +322,8 @@ public:
|
|||
FUNC2(gi_probe_set_anisotropy_strength, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
|
||||
|
||||
FUNC1(gi_probe_set_quality, GIProbeQuality)
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
FUNCRID(lightmap)
|
||||
|
@ -465,6 +468,10 @@ public:
|
|||
|
||||
FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
|
||||
|
||||
FUNC12(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, bool, float, float, float)
|
||||
FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
|
||||
FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
|
||||
|
||||
FUNC11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
|
||||
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
|
||||
|
||||
|
@ -478,7 +485,7 @@ public:
|
|||
|
||||
FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
|
||||
|
||||
FUNC2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
FUNC3(screen_space_roughness_limiter_set_active, bool, float, float)
|
||||
FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
|
||||
FUNC2(sub_surface_scattering_set_scale, float, float)
|
||||
|
||||
|
@ -714,6 +721,10 @@ public:
|
|||
return rendering_server->get_frame_profile();
|
||||
}
|
||||
|
||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
|
||||
rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir);
|
||||
}
|
||||
|
||||
RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread);
|
||||
~RenderingServerWrapMT();
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ ShaderTypes::ShaderTypes() {
|
|||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
|
||||
|
|
|
@ -1608,7 +1608,7 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &RenderingServer::light_set_negative);
|
||||
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
|
||||
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
|
||||
ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &RenderingServer::light_set_use_gi);
|
||||
ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &RenderingServer::light_omni_set_shadow_mode);
|
||||
|
||||
|
@ -1619,9 +1619,9 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("reflection_probe_create"), &RenderingServer::reflection_probe_create);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_update_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_update_mode);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_intensity", "probe", "intensity"), &RenderingServer::reflection_probe_set_intensity);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient", "probe", "color"), &RenderingServer::reflection_probe_set_interior_ambient);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_interior_ambient_energy);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_probe_contribution", "probe", "contrib"), &RenderingServer::reflection_probe_set_interior_ambient_probe_contribution);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_ambient_mode);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_color", "probe", "color"), &RenderingServer::reflection_probe_set_ambient_color);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_ambient_energy);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_max_distance", "probe", "distance"), &RenderingServer::reflection_probe_set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_extents", "probe", "extents"), &RenderingServer::reflection_probe_set_extents);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_origin_offset", "probe", "offset"), &RenderingServer::reflection_probe_set_origin_offset);
|
||||
|
@ -2060,9 +2060,11 @@ void RenderingServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_PSSM_SPLITS);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DECAL_ATLAS);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI_PROBES);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_BUFFER);
|
||||
|
||||
BIND_ENUM_CONSTANT(SKY_MODE_QUALITY);
|
||||
BIND_ENUM_CONSTANT(SKY_MODE_REALTIME);
|
||||
|
@ -2346,7 +2348,7 @@ RenderingServer::RenderingServer() {
|
|||
|
||||
GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false);
|
||||
GLOBAL_DEF("rendering/quality/gi_probes/quality", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Lowest (1 Cone - Fast),Medium (4 Cones - Average),High (6 Cones - Slow)"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
|
||||
|
||||
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
|
||||
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);
|
||||
|
@ -2372,10 +2374,11 @@ RenderingServer::RenderingServer() {
|
|||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Low (Fast),Medium (Average),High (Slow),Ultra (Slower)"));
|
||||
GLOBAL_DEF("rendering/quality/ssao/half_size", false);
|
||||
|
||||
GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/screen_space_roughness_limiter", PROPERTY_HINT_ENUM, "Disabled (Fast),Enabled (Average)"));
|
||||
GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_curve", 1.0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_curve", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_curve", PROPERTY_HINT_EXP_EASING, "0.01,8,0.01"));
|
||||
GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_enable", true);
|
||||
GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", 0.25);
|
||||
GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", 0.18);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
|
||||
|
||||
GLOBAL_DEF("rendering/quality/glow/upscale_mode", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/glow/upscale_mode", PropertyInfo(Variant::INT, "rendering/quality/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)"));
|
||||
|
@ -2395,6 +2398,11 @@ RenderingServer::RenderingServer() {
|
|||
|
||||
GLOBAL_DEF("rendering/lightmapper/probe_capture_update_speed", 15);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lightmapper/probe_capture_update_speed", PropertyInfo(Variant::FLOAT, "rendering/lightmapper/probe_capture_update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"));
|
||||
|
||||
GLOBAL_DEF("rendering/sdfgi/probe_ray_count", 2);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/probe_ray_count", PropertyInfo(Variant::INT, "rendering/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)"));
|
||||
GLOBAL_DEF("rendering/sdfgi/frames_to_converge", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/frames_to_converge", PropertyInfo(Variant::INT, "rendering/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)"));
|
||||
}
|
||||
|
||||
RenderingServer::~RenderingServer() {
|
||||
|
|
|
@ -406,7 +406,15 @@ public:
|
|||
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
|
||||
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
|
||||
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
|
||||
virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
|
||||
|
||||
enum LightBakeMode {
|
||||
LIGHT_BAKE_DISABLED,
|
||||
LIGHT_BAKE_DYNAMIC,
|
||||
LIGHT_BAKE_STATIC,
|
||||
};
|
||||
|
||||
virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0;
|
||||
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
|
||||
|
||||
// omni light
|
||||
enum LightOmniShadowMode {
|
||||
|
@ -445,9 +453,16 @@ public:
|
|||
|
||||
virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode) = 0;
|
||||
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_color) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0;
|
||||
|
||||
enum ReflectionProbeAmbientMode {
|
||||
REFLECTION_PROBE_AMBIENT_DISABLED,
|
||||
REFLECTION_PROBE_AMBIENT_ENVIRONMENT,
|
||||
REFLECTION_PROBE_AMBIENT_COLOR
|
||||
};
|
||||
|
||||
virtual void reflection_probe_set_ambient_mode(RID p_probe, ReflectionProbeAmbientMode p_mode) = 0;
|
||||
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
|
||||
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
|
||||
virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
|
||||
virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
|
||||
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
|
||||
|
@ -522,6 +537,13 @@ public:
|
|||
virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0;
|
||||
virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0;
|
||||
|
||||
enum GIProbeQuality {
|
||||
GI_PROBE_QUALITY_LOW,
|
||||
GI_PROBE_QUALITY_HIGH,
|
||||
};
|
||||
|
||||
virtual void gi_probe_set_quality(GIProbeQuality) = 0;
|
||||
|
||||
/* LIGHTMAP */
|
||||
|
||||
virtual RID lightmap_create() = 0;
|
||||
|
@ -690,9 +712,12 @@ public:
|
|||
VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
|
||||
VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE,
|
||||
VIEWPORT_DEBUG_DRAW_SSAO,
|
||||
VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||
VIEWPORT_DEBUG_DRAW_PSSM_SPLITS,
|
||||
VIEWPORT_DEBUG_DRAW_DECAL_ATLAS,
|
||||
VIEWPORT_DEBUG_DRAW_SDFGI,
|
||||
VIEWPORT_DEBUG_DRAW_SDFGI_PROBES,
|
||||
VIEWPORT_DEBUG_DRAW_GI_BUFFER,
|
||||
|
||||
};
|
||||
|
||||
virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
|
||||
|
@ -807,13 +832,51 @@ public:
|
|||
|
||||
virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size) = 0;
|
||||
|
||||
enum EnvironmentSDFGICascades {
|
||||
ENV_SDFGI_CASCADES_4,
|
||||
ENV_SDFGI_CASCADES_6,
|
||||
ENV_SDFGI_CASCADES_8,
|
||||
};
|
||||
|
||||
enum EnvironmentSDFGIYScale {
|
||||
ENV_SDFGI_Y_SCALE_DISABLED,
|
||||
ENV_SDFGI_Y_SCALE_75_PERCENT,
|
||||
ENV_SDFGI_Y_SCALE_50_PERCENT
|
||||
};
|
||||
|
||||
virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, bool p_enhance_ssr, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
|
||||
|
||||
enum EnvironmentSDFGIRayCount {
|
||||
ENV_SDFGI_RAY_COUNT_8,
|
||||
ENV_SDFGI_RAY_COUNT_16,
|
||||
ENV_SDFGI_RAY_COUNT_32,
|
||||
ENV_SDFGI_RAY_COUNT_64,
|
||||
ENV_SDFGI_RAY_COUNT_96,
|
||||
ENV_SDFGI_RAY_COUNT_128,
|
||||
ENV_SDFGI_RAY_COUNT_MAX,
|
||||
};
|
||||
|
||||
virtual void environment_set_sdfgi_ray_count(EnvironmentSDFGIRayCount p_ray_count) = 0;
|
||||
|
||||
enum EnvironmentSDFGIFramesToConverge {
|
||||
ENV_SDFGI_CONVERGE_IN_5_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_IN_10_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_IN_15_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_IN_20_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_IN_25_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_IN_30_FRAMES,
|
||||
ENV_SDFGI_CONVERGE_MAX
|
||||
};
|
||||
|
||||
virtual void environment_set_sdfgi_frames_to_converge(EnvironmentSDFGIFramesToConverge p_frames) = 0;
|
||||
|
||||
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
|
||||
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 Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
|
||||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0;
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
|
||||
|
||||
enum SubSurfaceScatteringQuality {
|
||||
SUB_SURFACE_SCATTERING_QUALITY_DISABLED,
|
||||
|
@ -1207,6 +1270,8 @@ public:
|
|||
virtual RID get_test_texture();
|
||||
virtual RID get_white_texture();
|
||||
|
||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
|
||||
|
||||
virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius);
|
||||
|
||||
virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data);
|
||||
|
@ -1248,10 +1313,12 @@ VARIANT_ENUM_CAST(RenderingServer::BlendShapeMode);
|
|||
VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightType);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightParam);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightBakeMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::DecalTexture);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
|
||||
|
|
Loading…
Reference in New Issue