Rewrote large part of rendering, omni and spot shadows now work.

This commit is contained in:
Juan Linietsky 2019-09-06 22:51:27 -03:00
parent 1d871f6226
commit 920db604d2
35 changed files with 3641 additions and 738 deletions

View file

@ -512,6 +512,28 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
return new_matrix;
}
void CameraMatrix::set_depth_correction() {
real_t *m = &matrix[0][0];
m[0] = 1;
m[1] = 0.0;
m[2] = 0.0;
m[3] = 0.0;
m[4] = 0.0;
m[5] = -1;
m[6] = 0.0;
m[7] = 0.0;
m[8] = 0.0;
m[9] = 0.0;
m[10] = 0.5;
m[11] = 0.0;
m[12] = 0.0;
m[13] = 0.0;
m[14] = 0.5;
m[15] = 1.0;
}
void CameraMatrix::set_light_bias() {
real_t *m = &matrix[0][0];

View file

@ -50,6 +50,7 @@ struct CameraMatrix {
void set_identity();
void set_zero();
void set_light_bias();
void set_depth_correction();
void set_light_atlas_rect(const Rect2 &p_rect);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);

View file

@ -216,7 +216,7 @@ public:
/* SHADOW ATLAS API */
struct ShadowAtlas {
struct ShadowAtlas {
enum {
QUADRANT_SHIFT = 27,
@ -288,7 +288,7 @@ public:
/* REFLECTION PROBE ATLAS API */
struct ReflectionAtlas {
struct ReflectionAtlas {
int subdiv;
int size;
@ -307,8 +307,7 @@ public:
mutable RID_PtrOwner<ReflectionAtlas> reflection_atlas_owner;
virtual RID reflection_atlas_create();
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size);
virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv);
virtual void reflection_atlas_configure(RID p_ref_atlas, int p_size, int p_count);
/* REFLECTION CUBEMAPS */
@ -324,7 +323,7 @@ public:
/* REFLECTION PROBE INSTANCE */
struct ReflectionProbeInstance {
struct ReflectionProbeInstance {
RasterizerStorageGLES3::ReflectionProbe *probe_ptr;
RID probe;
@ -364,7 +363,7 @@ public:
/* ENVIRONMENT API */
struct Environment {
struct Environment {
VS::EnvironmentBG bg_mode;
@ -590,7 +589,7 @@ public:
float shadow_split_offsets[4];
};
struct LightInstance {
struct LightInstance {
struct ShadowTransform {
@ -639,7 +638,7 @@ public:
/* REFLECTION INSTANCE */
struct GIProbeInstance {
struct GIProbeInstance {
RID data;
RasterizerStorageGLES3::GIProbe *probe;
GLuint tex_cache;

View file

@ -1497,6 +1497,23 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, NULL, 0, NULL);
}
void RenderingDeviceVulkan::_buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) {
VkBufferMemoryBarrier buffer_mem_barrier;
buffer_mem_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
buffer_mem_barrier.pNext = NULL;
buffer_mem_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_mem_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_mem_barrier.srcAccessMask = p_src_access;
buffer_mem_barrier.dstAccessMask = p_dst_sccess;
buffer_mem_barrier.buffer = buffer;
buffer_mem_barrier.offset = p_from;
buffer_mem_barrier.size = p_size;
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 0, NULL, 1, &buffer_mem_barrier, 0, NULL);
}
/*****************/
/**** TEXTURE ****/
/*****************/
@ -1715,7 +1732,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
}
if (p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT) {
texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
texture.unbound_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
} else {
texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
@ -2526,6 +2543,9 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
ERR_FAIL_COND_V(p_dst_mipmap >= dst_tex->mipmaps, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_dst_layer >= dst_layer_count, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_mask != dst_tex->read_aspect_mask, ERR_INVALID_PARAMETER,
"Source and destination texture must be of the same type (color or depth).");
VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
{
@ -2586,7 +2606,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
image_copy_region.srcOffset.y = p_from.y;
image_copy_region.srcOffset.z = p_from.z;
image_copy_region.dstSubresource.aspectMask = src_tex->barrier_aspect_mask;
image_copy_region.dstSubresource.aspectMask = dst_tex->read_aspect_mask;
image_copy_region.dstSubresource.baseArrayLayer = p_dst_layer;
image_copy_region.dstSubresource.layerCount = 1;
image_copy_region.dstSubresource.mipLevel = p_dst_mipmap;
@ -2712,6 +2732,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_COND_V_MSG(!(p_format[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)), VK_NULL_HANDLE,
"Texture format for index (" + itos(i) + ") requires an attachment (depth, stencil or resolve) bit set.");
bool can_be_sampled = p_format[i].usage_flags & TEXTURE_USAGE_SAMPLING_BIT;
switch (p_initial_action) {
case INITIAL_ACTION_CLEAR: {
@ -2722,7 +2744,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
case INITIAL_ACTION_KEEP_COLOR: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@ -2738,10 +2760,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@ -2772,15 +2794,16 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
switch (p_final_action) {
case FINAL_ACTION_READ_COLOR_AND_DEPTH: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@ -2791,12 +2814,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@ -2807,12 +2830,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@ -3062,7 +3085,7 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Poo
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
_buffer_update(&buffer, 0, r.ptr(), data_size);
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
}
return vertex_buffer_owner.make_rid(buffer);
@ -3223,7 +3246,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
_buffer_update(&index_buffer, 0, r.ptr(), data_size);
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
_buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
}
return index_buffer_owner.make_rid(index_buffer);
}
@ -3934,7 +3957,7 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Po
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
_buffer_update(&buffer, 0, r.ptr(), data_size);
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
}
return uniform_buffer_owner.make_rid(buffer);
}
@ -3953,7 +3976,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
_buffer_update(&buffer, 0, r.ptr(), data_size);
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, false);
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, false);
}
return storage_buffer_owner.make_rid(buffer);
}
@ -3976,7 +3999,7 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
_buffer_update(&texture_buffer.buffer, 0, r.ptr(), data_size);
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, false);
_buffer_memory_barrier(texture_buffer.buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, false);
}
VkBufferViewCreateInfo view_create_info;
@ -4400,7 +4423,8 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
Buffer *buffer = storage_buffer_owner.getornull(uniform.ids[0]);
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
//if 0, then its sized on link time
ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(),
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
write.dstArrayElement = 0;
@ -4523,8 +4547,47 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
return err;
}
_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw);
_buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw);
#if 0
if (p_sync_with_draw) {
VkMemoryBarrier memoryBarrier;
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.pNext = NULL;
memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
VK_ACCESS_INDEX_READ_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
VK_ACCESS_UNIFORM_READ_BIT |
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT |
VK_ACCESS_HOST_READ_BIT |
VK_ACCESS_HOST_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
VK_ACCESS_INDEX_READ_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
VK_ACCESS_UNIFORM_READ_BIT |
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT |
VK_ACCESS_HOST_READ_BIT |
VK_ACCESS_HOST_WRITE_BIT;
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, NULL, 0, NULL);
}
#endif
return err;
}
@ -5145,6 +5208,47 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
return OK;
}
void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector<Color> &p_clear_colors) {
Vector<VkClearAttachment> clear_attachments;
int color_index = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.getornull(framebuffer->texture_ids[i]);
VkClearAttachment clear_at;
if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
ERR_FAIL_INDEX(color_index, p_clear_colors.size()); //a bug
Color clear_color = p_clear_colors[color_index];
clear_at.clearValue.color.float32[0] = clear_color.r;
clear_at.clearValue.color.float32[1] = clear_color.g;
clear_at.clearValue.color.float32[2] = clear_color.b;
clear_at.clearValue.color.float32[3] = clear_color.a;
clear_at.colorAttachment = color_index++;
clear_at.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
} else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
clear_at.clearValue.depthStencil.depth = 1.0;
clear_at.clearValue.depthStencil.stencil = 0;
clear_at.colorAttachment = 0;
clear_at.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (format_has_stencil(texture->format)) {
clear_at.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
} else {
ERR_CONTINUE(true);
}
clear_attachments.push_back(clear_at);
}
VkClearRect cr;
cr.baseArrayLayer = 0;
cr.layerCount = 1;
cr.rect.offset.x = viewport_offset.x;
cr.rect.offset.y = viewport_offset.y;
cr.rect.extent.width = viewport_size.width;
cr.rect.extent.height = viewport_size.height;
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_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, const Rect2 &p_region) {
_THREAD_SAFE_METHOD_
@ -5154,8 +5258,9 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
bool needs_clear_region = false;
if (p_region != Rect2()) { //check custom region
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
Rect2i viewport(viewport_offset, viewport_size);
Rect2i regioni = p_region;
if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@ -5166,6 +5271,11 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
viewport_offset = regioni.position;
viewport_size = regioni.size;
if (p_initial_action == INITIAL_ACTION_CLEAR) {
p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH;
needs_clear_region = true;
}
}
if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
@ -5196,6 +5306,10 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
draw_list_count = 0;
draw_list_split = false;
if (needs_clear_region) {
_draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, p_clear_colors);
}
VkViewport viewport;
viewport.x = viewport_offset.x;
viewport.y = viewport_offset.y;
@ -5230,7 +5344,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
if (p_region != Rect2()) { //check custom region
bool needs_clear_region = false;
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
Rect2i viewport(viewport_offset, viewport_size);
Rect2i regioni = p_region;
if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@ -5241,6 +5357,11 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
viewport_offset = regioni.position;
viewport_size = regioni.size;
if (p_initial_action == INITIAL_ACTION_CLEAR) {
p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH;
needs_clear_region = true;
}
}
if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
@ -5340,6 +5461,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
#ifdef DEBUG_ENABLED
draw_list[i].validation.framebuffer_format = framebuffer->format_id;
#endif
if (i == 0 && needs_clear_region) {
_draw_list_insert_clear_region(&draw_list[i], framebuffer, viewport_offset, viewport_size, p_clear_colors);
}
VkViewport viewport;
viewport.x = viewport_offset.x;
@ -5754,6 +5878,11 @@ void RenderingDeviceVulkan::draw_list_end() {
}
}
draw_list_bound_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
_memory_barrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, 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) {

View file

@ -216,6 +216,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Error _buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer = false, uint32_t p_required_align = 32);
void _memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
void _buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
/*********************/
/**** FRAMEBUFFER ****/
@ -790,6 +791,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Vector<RID> draw_list_bound_textures;
bool draw_list_unbind_textures;
void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector<Color> &p_clear_colors);
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);

View file

@ -1753,6 +1753,12 @@ bool Main::start() {
}
#endif
{
int directional_atlas_size = GLOBAL_GET("rendering/quality/directional_shadow/size");
VisualServer::get_singleton()->directional_shadow_atlas_set_size(directional_atlas_size);
}
if (!editor && !project_manager) {
//standard helpers that can be changed from main config

View file

@ -431,42 +431,24 @@ OmniLight::ShadowMode OmniLight::get_shadow_mode() const {
return shadow_mode;
}
void OmniLight::set_shadow_detail(ShadowDetail p_detail) {
shadow_detail = p_detail;
VS::get_singleton()->light_omni_set_shadow_detail(light, VS::LightOmniShadowDetail(p_detail));
}
OmniLight::ShadowDetail OmniLight::get_shadow_detail() const {
return shadow_detail;
}
void OmniLight::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight::get_shadow_mode);
ClassDB::bind_method(D_METHOD("set_shadow_detail", "detail"), &OmniLight::set_shadow_detail);
ClassDB::bind_method(D_METHOD("get_shadow_detail"), &OmniLight::get_shadow_detail);
ADD_GROUP("Omni", "omni_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_detail", PROPERTY_HINT_ENUM, "Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail");
BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID);
BIND_ENUM_CONSTANT(SHADOW_CUBE);
BIND_ENUM_CONSTANT(SHADOW_DETAIL_VERTICAL);
BIND_ENUM_CONSTANT(SHADOW_DETAIL_HORIZONTAL);
}
OmniLight::OmniLight() :
Light(VisualServer::LIGHT_OMNI) {
set_shadow_mode(SHADOW_CUBE);
set_shadow_detail(SHADOW_DETAIL_HORIZONTAL);
}
String SpotLight::get_configuration_warning() const {

View file

@ -183,15 +183,8 @@ public:
SHADOW_CUBE,
};
// omni light
enum ShadowDetail {
SHADOW_DETAIL_VERTICAL,
SHADOW_DETAIL_HORIZONTAL
};
private:
ShadowMode shadow_mode;
ShadowDetail shadow_detail;
protected:
static void _bind_methods();
@ -200,14 +193,10 @@ public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
void set_shadow_detail(ShadowDetail p_detail);
ShadowDetail get_shadow_detail() const;
OmniLight();
};
VARIANT_ENUM_CAST(OmniLight::ShadowMode)
VARIANT_ENUM_CAST(OmniLight::ShadowDetail)
class SpotLight : public Light {

View file

@ -2075,14 +2075,10 @@ SceneTree::SceneTree() {
int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_size", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_size", PROPERTY_HINT_RANGE, "0,8192,or_greater")); //next_power_of_2 will return a 0 as min value
int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,or_greater")); //next_power_of_2 will return a 0 as min value
int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"));
root->set_msaa(Viewport::MSAA(msaa_mode));
VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
{ //load default fallback environment
//get possible extensions
List<String> exts;

View file

@ -47,6 +47,8 @@ void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted)
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
instances.clear();
}
RasterizerScene::InstanceDependency::~InstanceDependency() {

View file

@ -46,6 +46,7 @@ public:
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
virtual void directional_shadow_atlas_set_size(int p_size) = 0;
virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
virtual void set_directional_shadow_count(int p_count) = 0;
@ -107,18 +108,11 @@ public:
Map<InstanceBase *, uint32_t> instances;
};
struct InstanceCustomData {
virtual ~InstanceCustomData() {}
};
struct InstanceBase {
VS::InstanceType base_type;
RID base;
InstanceCustomData *custom_data;
RID skeleton;
RID material_override;
@ -201,7 +195,6 @@ public:
InstanceBase() :
dependency_item(this) {
custom_data = nullptr;
base_type = VS::INSTANCE_NONE;
cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
receive_shadows = true;
@ -215,9 +208,6 @@ public:
}
virtual ~InstanceBase() {
if (custom_data) {
memdelete(custom_data);
}
clear_dependencies();
}
};
@ -228,16 +218,10 @@ public:
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const { return true; }
virtual RID reflection_atlas_create() = 0;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size) = 0;
virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) = 0;
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
virtual void reflection_probe_instance_begin_render(RID p_instance) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
virtual RID gi_probe_instance_create() = 0;
@ -245,21 +229,13 @@ public:
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 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_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 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_environment, RID p_shadow_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 set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time) = 0;
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) = 0;
virtual void instance_create_custom_data(InstanceBase *p_instance) = 0;
virtual void instance_free_custom_data(InstanceBase *p_instance) = 0;
virtual void instance_custom_data_update_lights(InstanceBase *p_instance) = 0;
virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance) = 0;
virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance) = 0;
virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance) = 0;
virtual void instance_custom_data_update_transform(InstanceBase *p_instance) = 0;
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, VS::ViewportMSAA p_msaa) = 0;
@ -442,7 +418,6 @@ public:
virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0;
virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0;
virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;

View file

@ -2375,7 +2375,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
attachments.push_back(af_color);
RD::AttachmentFormat af_depth;
af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
attachments.push_back(af_depth);

View file

@ -39,7 +39,23 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
return uniform_set;
}
void RasterizerEffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
if (p_flip_y) {
blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_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);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@ -164,6 +180,23 @@ void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_frameb
RD::get_singleton()->draw_list_end();
}
void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
push_constant.bias = p_bias;
push_constant.z_far = p_z_far;
push_constant.z_near = p_z_near;
push_constant.z_flip = p_dp_flip;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant));
@ -277,6 +310,20 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
}
}
{
// Initialize copier
Vector<String> copy_modes;
copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n");
copy.shader.initialize(copy_modes);
copy.shader_version = copy.shader.version_create();
for (int i = 0; i < COPY_MODE_MAX; i++) {
copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
}
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;

View file

@ -4,6 +4,7 @@
#include "core/math/camera_matrix.h"
#include "render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/tonemap.glsl.gen.h"
@ -36,7 +37,8 @@ class RasterizerEffectsRD {
BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4)
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
BLUR_FLAG_FLIP_Y = (1 << 5)
};
struct BlurPushConstant {
@ -146,6 +148,25 @@ class RasterizerEffectsRD {
RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX];
} tonemap;
struct CopyToDPPushConstant {
float bias;
float z_far;
float z_near;
uint32_t z_flip;
};
enum CopyMode {
COPY_MODE_CUBE_TO_DP,
COPY_MODE_MAX
};
struct Copy {
CopyShaderRD shader;
RID shader_version;
RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
} copy;
RID default_sampler;
RID index_buffer;
RID index_array;
@ -155,11 +176,13 @@ class RasterizerEffectsRD {
RID _get_uniform_set_from_texture(RID p_texture);
public:
void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false);
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness);
void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
struct TonemapSettings {

View file

@ -67,6 +67,18 @@ static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_3x3_430(const Transform &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.elements[0][0];
p_array[1] = p_mtx.basis.elements[1][0];
p_array[2] = p_mtx.basis.elements[2][0];
p_array[3] = p_mtx.basis.elements[0][1];
p_array[4] = p_mtx.basis.elements[1][1];
p_array[5] = p_mtx.basis.elements[2][1];
p_array[6] = p_mtx.basis.elements[0][2];
p_array[7] = p_mtx.basis.elements[1][2];
p_array[8] = p_mtx.basis.elements[2][2];
}
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
@ -296,8 +308,8 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
if (depth_draw == DEPTH_DRAW_OPAQUE) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
} else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
if (k == SHADER_VERSION_DEPTH_PASS) {
} else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
if (k == SHADER_VERSION_DEPTH_PASS || k == k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, blend state contains nothing
} else {
blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@ -310,7 +322,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
blend_state = blend_state_opaque;
} else if (k == SHADER_VERSION_DEPTH_PASS) {
} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@ -583,60 +595,62 @@ bool RasterizerSceneForwardRD::free(RID p_rid) {
}
return false;
}
/// INSTANCE DATA ///
void RasterizerSceneForwardRD::instance_create_custom_data(InstanceBase *p_instance) {
InstanceGeometryData *geom_data = memnew(InstanceGeometryData);
geom_data->ubo = RD::get_singleton()->uniform_buffer_create(sizeof(InstanceGeometryData::UBO));
geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
p_instance->custom_data = geom_data;
}
void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, int p_element_count) {
void RasterizerSceneForwardRD::instance_free_custom_data(InstanceBase *p_instance) {
InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
ERR_FAIL_COND(!geom_data);
RD::get_singleton()->free(geom_data->ubo);
//uniform sets are freed as dependencies
memdelete(geom_data);
p_instance->custom_data = nullptr;
}
for (int i = 0; i < p_element_count; i++) {
void RasterizerSceneForwardRD::instance_custom_data_update_lights(InstanceBase *p_instance) {
//unused
}
const RenderList::Element *e = p_elements[i];
InstanceData &id = scene_state.instances[i];
store_transform(e->instance->transform, id.transform);
store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
id.flags = 0;
id.mask = e->instance->layer_mask;
void RasterizerSceneForwardRD::instance_custom_data_update_reflection_probes(InstanceBase *p_instance) {
//unused
}
void RasterizerSceneForwardRD::instance_custom_data_update_lightmap(InstanceBase *p_instance) {
InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
ERR_FAIL_COND(!geom_data);
//forward
geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
uint32_t reflection_count = 0;
uint32_t omni_count = 0;
uint32_t spot_count = 0;
uint32_t decal_count = 0;
if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
RD::get_singleton()->free(geom_data->uniform_set_gi);
if (!e->instance->light_instances.empty()) {
uint32_t light_count = e->instance->light_instances.size();
const RID *light_ptrs = e->instance->light_instances.ptr();
for (uint32_t j = 0; j < light_count; j++) {
if (render_pass != light_instance_get_render_pass(light_ptrs[j])) {
continue; //not rendered this frame
}
RID base = light_instance_get_base_light(light_ptrs[j]);
uint32_t mask = storage->light_get_cull_mask(base);
if (!(mask & id.mask)) {
continue; //masked
}
if (storage->light_get_type(base) == VS::LIGHT_OMNI) {
if (omni_count < 8) {
id.omni_light_indices[omni_count] = light_instance_get_index(light_ptrs[j]);
omni_count++;
}
} else {
if (spot_count < 8) {
id.omni_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
spot_count++;
}
}
}
}
id.flags |= reflection_count;
id.flags |= omni_count << 3;
id.flags |= spot_count << 6;
id.flags |= decal_count << 9;
}
geom_data->uniform_set_gi = RID();
}
void RasterizerSceneForwardRD::instance_custom_data_update_gi_probes(InstanceBase *p_instance) {
InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
ERR_FAIL_COND(!geom_data);
geom_data->using_vct_gi = p_instance->gi_probe_instances.size();
if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
RD::get_singleton()->free(geom_data->uniform_set_gi);
}
geom_data->uniform_set_gi = RID();
}
void RasterizerSceneForwardRD::instance_custom_data_update_transform(InstanceBase *p_instance) {
InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
ERR_FAIL_COND(!geom_data);
geom_data->ubo_dirty = true;
RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
}
/// RENDERING ///
@ -669,7 +683,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
//find cull variant
ShaderData::CullVariant cull_variant;
if (p_pass_mode == PASS_MODE_SHADOW && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
bool mirror = e->instance->mirror;
@ -700,59 +714,42 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
InstanceGeometryData *geom_data = (InstanceGeometryData *)e->instance->custom_data;
ShaderVersion shader_version;
RID instance_uniform_set;
switch (p_pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
if (p_no_gi) {
instance_uniform_set = geom_data->uniform_set_base;
shader_version = SHADER_VERSION_COLOR_PASS;
} else if (geom_data->using_lightmap_gi) {
instance_uniform_set = geom_data->uniform_set_gi;
if (e->uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
} else if (geom_data->using_vct_gi) {
instance_uniform_set = geom_data->uniform_set_gi;
} else if (e->uses_vct) {
shader_version = SHADER_VERSION_VCT_COLOR_PASS;
} else {
instance_uniform_set = geom_data->uniform_set_gi;
shader_version = SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
if (p_no_gi) {
instance_uniform_set = geom_data->uniform_set_base;
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else if (geom_data->using_lightmap_gi) {
instance_uniform_set = geom_data->uniform_set_gi;
if (e->uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else if (geom_data->using_vct_gi) {
instance_uniform_set = geom_data->uniform_set_gi;
} else if (e->uses_vct) {
shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else {
instance_uniform_set = geom_data->uniform_set_gi;
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
}
} break;
case PASS_MODE_SHADOW: {
shader_version = SHADER_VERSION_DEPTH_PASS;
instance_uniform_set = geom_data->uniform_set_base;
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
shader_version = SHADER_VERSION_DEPTH_PASS;
instance_uniform_set = geom_data->uniform_set_base;
} break;
case PASS_MODE_SHADOW_DP: {
shader_version = SHADER_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL: {
shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL;
instance_uniform_set = geom_data->uniform_set_base;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
instance_uniform_set = geom_data->uniform_set_base;
} break;
}
@ -812,8 +809,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
prev_material = material;
}
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, instance_uniform_set, 3);
push_constant.index = i;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant));
switch (e->instance->base_type) {
@ -836,10 +832,13 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) {
void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
CameraMatrix projection = p_cam_projection;
projection.flip_y(); // Vulkan and modern APIs use Y-Down
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
correction.set_depth_correction();
CameraMatrix projection = correction * p_cam_projection;
//store camera into ubo
store_camera(projection, scene_state.ubo.projection_matrix);
@ -847,6 +846,19 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
if (p_shadow_atlas.is_valid()) {
Vector2 sas = shadow_atlas_get_size(p_shadow_atlas);
scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x;
scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y;
}
{
Vector2 dss = directional_shadow_get_size();
scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x;
scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y;
}
//time global variables
scene_state.ubo.time = time;
@ -863,7 +875,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
//ambient
if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) {
Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? storage->render_target_get_clear_request_color(p_render_target) : environment_get_bg_color(p_environment);
Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? (p_render_target.is_valid() ? storage->render_target_get_clear_request_color(p_render_target) : Color(0, 0, 0)) : environment_get_bg_color(p_environment);
color = color.to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
@ -1024,7 +1036,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
}
void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode) {
void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
@ -1047,18 +1059,18 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t
ERR_FAIL_COND(!material);
_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
while (material->next_pass.is_valid()) {
material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid)
break;
_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
}
}
void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode) {
void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
@ -1120,8 +1132,11 @@ void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_insta
e->material->shader_data->index = scene_state.current_shader_index++;
}
}
e->geometry_index = p_geometry_index;
e->material_index = e->material->index;
e->uses_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH;
e->uses_lightmap = e->instance->lightmap.is_valid();
e->uses_vct = e->instance->gi_probe_instances.size();
e->shader_index = e->shader_index;
e->depth_layer = e->instance->depth_layer;
e->priority = p_material->priority;
@ -1140,89 +1155,14 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
scene_state.used_normal_texture = false;
scene_state.used_depth_texture = false;
uint32_t geometry_index = 0;
//fill list
for (int i = 0; i < p_cull_count; i++) {
InstanceBase *inst = p_cull_result[i];
InstanceGeometryData *geom_data = (InstanceGeometryData *)inst->custom_data;
ERR_CONTINUE(!geom_data);
if (geom_data->ubo_dirty) {
//ubo marked dirty, must be updated
InstanceGeometryData::UBO ubo;
store_transform(inst->transform, ubo.transform);
store_transform_3x3(inst->transform.basis.inverse().transposed(), ubo.normal_transform);
ubo.flags = 0;
ubo.pad[0] = 0;
ubo.pad[1] = 0;
ubo.pad[2] = 0;
RD::get_singleton()->buffer_update(geom_data->ubo, 0, sizeof(InstanceGeometryData::UBO), &ubo, true);
}
if (p_no_gi) {
if (geom_data->uniform_set_base.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_base)) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
u.ids.push_back(geom_data->ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
uniforms.push_back(u);
}
geom_data->uniform_set_base = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
}
} else {
if (geom_data->uniform_set_gi.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
u.ids.push_back(geom_data->ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
uniforms.push_back(u);
}
if (geom_data->using_lightmap_gi) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
#ifndef _MSC_VER
#warning Need to put actual lightmap or lightmap capture texture if exists
#endif
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
} else if (geom_data->using_vct_gi) {
#ifndef _MSC_VER
#warning Need to put actual vct textures here
#endif
}
geom_data->uniform_set_gi = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
}
}
//add geometry for drawing
switch (inst->base_type) {
@ -1242,7 +1182,8 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
_add_geometry(inst, j, material, p_pass_mode);
uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index);
_add_geometry(inst, j, material, p_pass_mode, surface_index);
}
//mesh->last_pass=frame;
@ -1341,12 +1282,208 @@ void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu
storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
}
void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
for (uint32_t i = 0; i < p_reflection_probe_cull_count; i++) {
RID rpi = p_reflection_probe_cull_result[i];
if (i >= scene_state.max_reflections) {
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
continue;
}
reflection_probe_instance_set_render_index(rpi, i);
RID base_probe = reflection_probe_instance_get_probe(rpi);
ReflectionData &reflection_ubo = scene_state.reflections[i];
Vector3 extents = storage->reflection_probe_get_extents(base_probe);
reflection_ubo.box_extents[0] = extents.x;
reflection_ubo.box_extents[1] = extents.y;
reflection_ubo.box_extents[2] = extents.z;
reflection_ubo.box_extents[3] = 0;
Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
reflection_ubo.box_offset[0] = origin_offset.x;
reflection_ubo.box_offset[1] = origin_offset.y;
reflection_ubo.box_offset[2] = origin_offset.z;
reflection_ubo.box_offset[3] = 0;
float intensity = storage->reflection_probe_get_intensity(base_probe);
bool interior = storage->reflection_probe_is_interior(base_probe);
bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
reflection_ubo.params[0] = intensity;
reflection_ubo.params[1] = 0;
reflection_ubo.params[2] = interior ? 1.0 : 0.0;
reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
if (interior) {
Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe);
float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe);
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
reflection_ubo.ambient[3] = interior_ambient_probe_contrib;
} else {
Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
if (is_environment(p_environment)) {
Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear();
float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment);
ambient_linear = env_ambient_color;
ambient_linear.r *= env_ambient_energy;
ambient_linear.g *= env_ambient_energy;
ambient_linear.b *= env_ambient_energy;
}
reflection_ubo.ambient[0] = ambient_linear.r;
reflection_ubo.ambient[1] = ambient_linear.g;
reflection_ubo.ambient[2] = ambient_linear.b;
reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
}
Transform transform = reflection_probe_instance_get_transform(rpi);
Transform proj = (p_camera_inverse_transform * transform).inverse();
store_transform(proj, reflection_ubo.local_matrix);
}
if (p_reflection_probe_cull_count) {
RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true);
}
}
void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas) {
uint32_t light_count = 0;
scene_state.ubo.directional_light_count = 0;
for (int i = 0; i < p_light_cull_count; i++) {
RID li = p_light_cull_result[i];
RID base = light_instance_get_base_light(li);
ERR_CONTINUE(base.is_null());
VS::LightType type = storage->light_get_type(base);
switch (type) {
case VS::LIGHT_DIRECTIONAL: {
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
continue;
}
} break;
case VS::LIGHT_SPOT:
case VS::LIGHT_OMNI: {
if (light_count >= scene_state.max_lights) {
continue;
}
Transform light_transform = light_instance_get_base_transform(li);
LightData &light_data = scene_state.lights[light_count];
float sign = storage->light_is_negative(base) ? -1 : 1;
Color linear_col = storage->light_get_color(base).to_linear();
light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_ATTENUATION));
light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI);
light_data.color_specular[0] = CLAMP(uint32_t(linear_col.r * 255), 0, 255);
light_data.color_specular[1] = CLAMP(uint32_t(linear_col.g * 255), 0, 255);
light_data.color_specular[2] = CLAMP(uint32_t(linear_col.b * 255), 0, 255);
light_data.color_specular[3] = CLAMP(uint32_t(storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR) * 255), 0, 255);
light_data.inv_radius = 1.0 / MAX(0.001, storage->light_get_param(base, VS::LIGHT_PARAM_RANGE));
Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
light_data.position[0] = pos.x;
light_data.position[1] = pos.y;
light_data.position[2] = pos.z;
Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
light_data.direction[0] = direction.x;
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ATTENUATION));
light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ANGLE))));
light_data.mask = storage->light_get_cull_mask(base);
Color shadow_color = storage->light_get_shadow_color(base);
bool has_shadow = storage->light_has_shadow(base);
light_data.shadow_color_enabled[0] = CLAMP(uint32_t(shadow_color.r * 255), 0, 255);
light_data.shadow_color_enabled[1] = CLAMP(uint32_t(shadow_color.g * 255), 0, 255);
light_data.shadow_color_enabled[2] = CLAMP(uint32_t(shadow_color.b * 255), 0, 255);
light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
light_data.atlas_rect[0] = 0;
light_data.atlas_rect[1] = 0;
light_data.atlas_rect[2] = 0;
light_data.atlas_rect[3] = 0;
if (storage->light_has_shadow(base) && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
// fill in the shadow information
Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
if (type == VS::LIGHT_OMNI) {
light_data.atlas_rect[0] = rect.position.x;
light_data.atlas_rect[1] = rect.position.y;
light_data.atlas_rect[2] = rect.size.width;
light_data.atlas_rect[3] = rect.size.height * 0.5;
Transform proj = (p_camera_inverse_transform * light_transform).inverse();
store_transform(proj, light_data.shadow_matrix);
} else if (type == VS::LIGHT_SPOT) {
Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
CameraMatrix bias;
bias.set_light_bias();
CameraMatrix rectm;
rectm.set_light_atlas_rect(rect);
CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
store_camera(shadow_mtx, light_data.shadow_matrix);
}
}
light_instance_set_index(li, light_count);
light_count++;
} break;
}
light_instance_set_render_pass(li, render_pass);
//update UBO for forward rendering, blit to texture for clustered
}
if (light_count) {
RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true);
}
if (scene_state.ubo.directional_light_count) {
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
}
}
void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
ERR_FAIL_COND(!render_buffer); //bug out for now
//first of all, make a new render pass
render_pass++;
@ -1388,14 +1525,34 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
scene_state.ubo.viewport_size[1] = vp_he.y;
RID render_target;
Size2 screen_pixel_size;
RID opaque_framebuffer;
RID alpha_framebuffer;
if (render_buffer) {
scene_state.ubo.screen_pixel_size[0] = 1.0 / render_buffer->width;
scene_state.ubo.screen_pixel_size[1] = 1.0 / render_buffer->height;
screen_pixel_size.width = 1.0 / render_buffer->width;
screen_pixel_size.height = 1.0 / render_buffer->height;
render_target = render_buffer->render_target;
opaque_framebuffer = render_buffer->color_fb;
alpha_framebuffer = opaque_framebuffer;
} else if (p_reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
screen_pixel_size.width = 1.0 / resolution;
screen_pixel_size.height = 1.0 / resolution;
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
alpha_framebuffer = opaque_framebuffer;
} else {
ERR_FAIL(); //bug?
}
_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid());
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas);
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
#if 0
for (int i = 0; i < p_light_cull_count; i++) {
@ -1771,10 +1928,12 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
}
}
_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap);
_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, RID());
render_list.sort_by_key(false);
_fill_instances(render_list.elements, render_list.element_count);
bool can_continue = true; //unless the middle buffers are needed
bool using_separate_specular = false;
@ -1782,14 +1941,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
//regular forward for now
Vector<Color> c;
c.push_back(clear_color.to_linear());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::get_singleton()->draw_list_end();
}
if (draw_sky) {
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
_draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), p_environment, p_cam_projection, p_cam_transform, 1.0);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
_draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, p_cam_projection, p_cam_transform, 1.0);
RD::get_singleton()->draw_list_end();
if (using_separate_specular && !can_continue) {
@ -1887,9 +2046,11 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
#endif
render_list.sort_by_reverse_depth_and_priority(true);
_fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count);
{
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::get_singleton()->draw_list_end();
}
@ -1907,7 +2068,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
}
#endif
if (p_reflection_probe.is_valid()) {
//rendering a probe, do no more!
//was rendering a probe, so do no more
return;
}
@ -1931,6 +2092,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
storage->render_target_disable_clear_request(render_buffer->render_target);
if (true) {
if (p_shadow_atlas.is_valid()) {
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
}
}
#if 0
_post_process(env, p_cam_projection);
// Needed only for debugging
@ -1988,8 +2158,38 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
//disable all stuff
#endif
}
void RasterizerSceneForwardRD::_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) {
void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap) {
render_pass++;
scene_state.ubo.shadow_z_offset = p_bias;
scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
scene_state.ubo.z_far = p_zfar;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
_setup_environment(RID(), RID(), p_projection, p_transform, true, Vector2(1, 1), RID());
render_list.clear();
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
_fill_render_list(p_cull_result, p_cull_count, pass_mode, true);
_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), RID(), RID(), RID());
render_list.sort_by_key(false);
_fill_instances(render_list.elements, render_list.element_count);
{
//regular forward for now
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true);
RD::get_singleton()->draw_list_end();
}
}
void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas) {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
@ -2065,20 +2265,79 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
{
RD::Uniform u;
u.binding = 7;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.ids.push_back(shadow_sampler);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.uniform_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 9;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.instance_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 10;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.reflection_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.light_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 12;
u.type = RD::UNIFORM_TYPE_TEXTURE;
if (p_shadow_atlas.is_valid()) {
u.ids.push_back(shadow_atlas_get_texture(p_shadow_atlas));
} else {
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
}
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 13;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.directional_light_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 14;
u.type = RD::UNIFORM_TYPE_TEXTURE;
if (directional_shadow_get_texture().is_valid()) {
u.ids.push_back(directional_shadow_get_texture());
} else {
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
}
uniforms.push_back(u);
}
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
}
RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL;
void RasterizerSceneForwardRD::set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
}
void RasterizerSceneForwardRD::set_time(double p_time) {
time = p_time;
}
@ -2097,8 +2356,53 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
}
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
if (textures_per_stage <= 16) {
//ARM pretty much, and very old Intel GPUs under Linux
scene_state.max_reflection_probes_per_instance = 4; //sad
} else {
//maximum 8
scene_state.max_reflection_probes_per_instance = 8;
}
defines += "\n#define MAX_REFLECTION_PROBES " + itos(scene_state.max_reflection_probes_per_instance) + "\n";
uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
{ //reflections
uint32_t reflection_buffer_size;
if (uniform_max_size < 65536) {
//Yes, you guessed right, ARM again
reflection_buffer_size = uniform_max_size;
} else {
reflection_buffer_size = 65536;
}
scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData);
scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections);
scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size);
defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n";
}
{ //lights
scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
print_line("ID: " + itos(sizeof(InstanceData)));
scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
scene_state.max_directional_lights = 4;
uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights);
scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n";
}
Vector<String> shader_versions;
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_BUFFER\n");
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_ROUGHNESS_BUFFER\n");
shader_versions.push_back("");
@ -2198,7 +2502,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
@ -2249,11 +2553,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
}
//render list
render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)256000);
render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);
render_list.init();
scene_pass = 0;
render_pass = 0;
{
scene_state.max_instances = render_list.max_elements;
scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances);
scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances);
}
scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
{
@ -2266,6 +2576,16 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
}
{
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.enable_compare = true;
sampler.compare_op = RD::COMPARE_OP_LESS;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
}
RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
@ -2273,4 +2593,9 @@ RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
{
RD::get_singleton()->free(scene_state.reflection_buffer);
memdelete_arr(scene_state.reflections);
}
}

View file

@ -42,6 +42,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
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_COLOR_PASS,
@ -174,37 +175,11 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
/* Instance Custom Data */
struct InstanceGeometryData : public InstanceCustomData {
struct UBO {
float transform[16];
float normal_transform[12];
uint32_t flags;
uint32_t pad[3];
};
RID ubo;
RID uniform_set_base;
RID uniform_set_gi;
bool ubo_dirty = true;
bool using_lightmap_gi = false;
bool using_vct_gi = false;
};
/* Push Constant */
struct PushConstant {
uint32_t reflection_probe_count;
uint32_t omni_light_count;
uint32_t spot_light_count;
uint32_t decal_count;
float reflection_probe_indices[4];
float omni_light_indices[4];
float spot_light_indices[4];
float decal_indices[4];
uint32_t index;
uint32_t pad[3];
};
/* Framebuffer */
@ -227,11 +202,65 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
virtual RenderBufferData *_create_render_buffer_data();
RID shadow_sampler;
RID render_base_uniform_set;
void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap);
void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas);
/* Scene State UBO */
struct ReflectionData { //should always be 128 bytes
float box_extents[4];
float box_offset[4];
float params[4]; // intensity, 0, interior , boxproject
float ambient[4]; // ambient color, energy
float local_matrix[16]; // up to here for spot and omni, rest is for directional
};
struct LightData {
float position[3];
float inv_radius;
float direction[3];
uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
uint32_t mask;
uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
};
struct DirectionalLightData {
float direction[3];
float energy;
float color[3];
float specular;
uint32_t mask;
uint32_t pad[3];
float shadow_color[3];
uint32_t shadow_enabled;
float shadow_atlas_rect[4];
float shadow_split_offsets[4];
float shadow_matrix1[16];
float shadow_matrix2[16];
float shadow_matrix3[16];
float shadow_matrix4[16];
};
struct InstanceData {
float transform[16];
float normal_transform[16];
uint32_t flags;
uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
uint32_t mask;
uint16_t reflection_probe_indices[8];
uint16_t omni_light_indices[8];
uint16_t spot_light_indices[8];
uint16_t decal_indices[8];
};
struct SceneState {
struct UBO {
float projection_matrix[16];
@ -257,12 +286,37 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
uint32_t use_reflection_cubemap;
float radiance_inverse_xform[12];
float shadow_atlas_pixel_size[2];
float directional_shadow_pixel_size[2];
uint32_t directional_light_count;
float dual_paraboloid_side;
float z_far;
uint32_t pad[1];
};
UBO ubo;
RID uniform_buffer;
ReflectionData *reflections;
uint32_t max_reflections;
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
LightData *lights;
uint32_t max_lights;
RID light_buffer;
DirectionalLightData *directional_lights;
uint32_t max_directional_lights;
RID directional_light_buffer;
RID instance_buffer;
InstanceData *instances;
uint32_t max_instances;
bool used_screen_texture = false;
bool used_normal_texture = false;
bool used_depth_texture = false;
@ -283,10 +337,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
union {
struct {
//from least significant to most significant in sort, TODO: should be endian swapped on big endian
uint64_t material_index : 20;
uint64_t shader_index : 20;
uint64_t priority : 16;
uint64_t depth_layer : 8;
uint64_t geometry_index : 20;
uint64_t material_index : 15;
uint64_t shader_index : 12;
uint64_t uses_instancing : 1;
uint64_t uses_vct : 1;
uint64_t uses_lightmap : 1;
uint64_t depth_layer : 4;
uint64_t priority : 8;
};
uint64_t sort_key;
@ -407,7 +465,6 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
RenderList render_list;
static RasterizerSceneForwardRD *singleton;
uint64_t scene_pass;
uint64_t render_pass;
double time;
RID default_shader;
@ -419,39 +476,33 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
PASS_MODE_COLOR_SPECULAR,
PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
PASS_MODE_DEPTH_NORMAL,
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
};
void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog);
void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas);
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 _fill_instances(RenderList::Element **p_elements, int p_element_count);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi);
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode);
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode);
_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, PassMode p_pass_mode, uint32_t p_geometry_index);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
protected:
virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
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);
public:
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
virtual void set_scene_pass(uint64_t p_pass);
virtual void set_time(double p_time);
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
virtual void instance_create_custom_data(InstanceBase *p_instance);
virtual void instance_free_custom_data(InstanceBase *p_instance);
virtual void instance_custom_data_update_lights(InstanceBase *p_instance);
virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance);
virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance);
virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance);
virtual void instance_custom_data_update_transform(InstanceBase *p_instance);
virtual bool free(RID p_rid);
RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);

File diff suppressed because it is too large Load diff

View file

@ -15,20 +15,17 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
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) = 0;
private:
int roughness_layers;
RasterizerStorageRD *storage;
struct Sky {
int radiance_size = 256;
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
RID panorama;
struct ReflectionData {
RID radiance;
bool dirty = false;
Sky *dirty_list = nullptr;
struct Layer {
struct Mipmap {
RID framebuffers[6];
@ -38,9 +35,26 @@ private:
Vector<Mipmap> mipmaps;
};
RID radiance_base_cubemap; //cubemap for first layer, first cubemap
Vector<Layer> layers;
};
void _clear_reflection_data(ReflectionData &rd);
void _update_reflection_data(ReflectionData &rd, int p_size, bool p_quality);
void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side);
void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
/* SKY */
struct Sky {
int radiance_size = 256;
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
RID panorama;
ReflectionData reflection;
bool dirty = false;
Sky *dirty_list = nullptr;
};
Sky *dirty_sky_list = nullptr;
void _sky_invalidate(Sky *p_sky);
@ -52,6 +66,156 @@ private:
mutable RID_Owner<Sky> sky_owner;
/* REFLECTION PROBE INSTANCE */
struct ReflectionProbeInstance {
RID probe;
ReflectionData reflection;
RID depth_buffer;
RID render_fb[6];
int current_resolution = 0;
bool dirty = true;
bool rendering = false;
int processing_side = 0;
uint32_t render_index = 0;
Transform transform;
};
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
/* SHADOW ATLAS */
struct ShadowAtlas {
enum {
QUADRANT_SHIFT = 27,
SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
SHADOW_INVALID = 0xFFFFFFFF
};
struct Quadrant {
uint32_t subdivision;
struct Shadow {
RID owner;
uint64_t version;
uint64_t alloc_tick;
Shadow() {
version = 0;
alloc_tick = 0;
}
};
Vector<Shadow> shadows;
Quadrant() {
subdivision = 0; //not in use
}
} quadrants[4];
int size_order[4] = { 0, 1, 2, 3 };
uint32_t smallest_subdiv = 0;
int size = 0;
RID depth;
RID fb; //for copying
Map<RID, uint32_t> shadow_owners;
};
RID_Owner<ShadowAtlas> shadow_atlas_owner;
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
/* DIRECTIONAL SHADOW */
struct DirectionalShadow {
RID depth;
RID fb; //for copying
int light_count = 0;
int size = 0;
int current_light = 0;
} directional_shadow;
/* SHADOW CUBEMAPS */
struct ShadowCubemap {
RID cubemap;
RID side_fb[6];
};
Map<int, ShadowCubemap> shadow_cubemaps;
ShadowCubemap *_get_shadow_cubemap(int p_size);
struct ShadowMap {
RID depth;
RID fb;
};
Map<Vector2i, ShadowMap> shadow_maps;
ShadowMap *_get_shadow_map(const Size2i &p_size);
void _create_shadow_cubemaps();
/* LIGHT INSTANCE */
struct LightInstance {
struct ShadowTransform {
CameraMatrix camera;
Transform transform;
float farplane;
float split;
float bias_scale;
};
VS::LightType light_type;
ShadowTransform shadow_transform[4];
RID self;
RID light;
Transform transform;
Vector3 light_vector;
Vector3 spot_vector;
float linear_att;
uint64_t shadow_pass = 0;
uint64_t last_scene_pass = 0;
uint64_t last_scene_shadow_pass = 0;
uint64_t last_pass = 0;
uint32_t light_index = 0;
uint32_t light_directional_index = 0;
uint32_t current_shadow_atlas_key;
Vector2 dp;
Rect2 directional_rect;
Set<RID> shadow_atlases; //shadow atlases where this light is registered
LightInstance() {}
};
mutable RID_Owner<LightInstance> light_instance_owner;
/* ENVIRONMENT */
struct Environent {
// BG
@ -82,6 +246,8 @@ private:
mutable RID_Owner<Environent> environment_owner;
/* RENDER BUFFERS */
struct RenderBuffers {
RenderBufferData *data = nullptr;
@ -92,16 +258,45 @@ private:
mutable RID_Owner<RenderBuffers> render_buffers_owner;
uint64_t scene_pass = 0;
uint64_t shadow_atlas_realloc_tolerance_msec = 500;
public:
/* SHADOW ATLAS API */
RID shadow_atlas_create() { return RID(); }
void shadow_atlas_set_size(RID p_atlas, int p_size) {}
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }
RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas, int p_size);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!atlas, false);
return atlas->shadow_owners.has(p_light_intance);
}
int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
void set_directional_shadow_count(int p_count) {}
_FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->depth;
}
_FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) {
ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!atlas, Size2i());
return Size2(atlas->size, atlas->size);
}
void directional_shadow_atlas_set_size(int p_size);
int get_directional_light_shadow_size(RID p_light_intance);
void set_directional_shadow_count(int p_count);
_FORCE_INLINE_ RID directional_shadow_get_texture() {
return directional_shadow.depth;
}
_FORCE_INLINE_ Size2i directional_shadow_get_size() {
return Size2i(directional_shadow.size, directional_shadow.size);
}
/* SKY API */
@ -166,22 +361,121 @@ public:
void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
RID light_instance_create(RID p_light) { return RID(); }
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
void light_instance_mark_visible(RID p_light_instance) {}
RID light_instance_create(RID p_light);
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
void light_instance_mark_visible(RID p_light_instance);
RID reflection_atlas_create() { return RID(); }
void reflection_atlas_set_size(RID p_ref_atlas, int p_size) {}
void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {}
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->light;
}
RID reflection_probe_instance_create(RID p_probe) { return RID(); }
void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {}
void reflection_probe_release_atlas_index(RID p_instance) {}
bool reflection_probe_instance_needs_redraw(RID p_instance) { return false; }
bool reflection_probe_instance_has_reflection(RID p_instance) { return false; }
bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
_FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->transform;
}
_FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
LightInstance *li = light_instance_owner.getornull(p_light_instance);
uint32_t key = shadow_atlas->shadow_owners[li->self];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2());
uint32_t atlas_size = shadow_atlas->size;
uint32_t quadrant_size = atlas_size >> 1;
uint32_t x = (quadrant & 1) * quadrant_size;
uint32_t y = (quadrant >> 1) * quadrant_size;
uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
uint32_t width = shadow_size;
uint32_t height = shadow_size;
return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
}
_FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].camera;
}
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
li->last_pass = p_pass;
}
_FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->last_pass;
}
_FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
li->light_index = p_index;
}
_FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->light_index;
}
_FORCE_INLINE_ VS::LightType light_instance_get_type(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->light_type;
}
virtual RID reflection_probe_instance_create(RID p_probe);
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
virtual void reflection_probe_instance_begin_render(RID p_instance);
virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
_FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
return rpi->probe;
}
_FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND(!rpi);
rpi->render_index = p_render_index;
}
_FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
return rpi->render_index;
}
_FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, Transform());
return rpi->transform;
}
_FORCE_INLINE_ RID reflection_probe_instance_get_texture(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
return rpi->reflection.radiance;
}
RID gi_probe_instance_create() { return RID(); }
void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
@ -191,7 +485,12 @@ public:
RID render_buffers_create();
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
_FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
@ -201,6 +500,7 @@ public:
virtual void update();
RasterizerSceneRD(RasterizerStorageRD *p_storage);
~RasterizerSceneRD();
};
#endif // RASTERIZER_SCENE_RD_H

View file

@ -2087,6 +2087,462 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
}
/* LIGHT */
RID RasterizerStorageRD::light_create(VS::LightType p_type) {
Light light;
light.type = p_type;
light.param[VS::LIGHT_PARAM_ENERGY] = 1.0;
light.param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
light.param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
light.param[VS::LIGHT_PARAM_RANGE] = 1.0;
light.param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
light.param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
light.param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
return light_owner.make_rid(light);
}
void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->color = p_color;
}
void RasterizerStorageRD::light_set_param(RID p_light, VS::LightParam p_param, float p_value) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX);
switch (p_param) {
case VS::LIGHT_PARAM_RANGE:
case VS::LIGHT_PARAM_SPOT_ANGLE:
case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
case VS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
} break;
default: {
}
}
light->param[p_param] = p_value;
}
void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow = p_enabled;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow_color = p_color;
}
void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->projector = p_texture;
}
void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->negative = p_enable;
}
void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->cull_mask = p_mask;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->reverse_cull = p_enabled;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->use_gi = p_enabled;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->omni_shadow_mode = p_mode;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
VS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE);
return light->omni_shadow_mode;
}
void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_shadow_mode = p_mode;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_blend_splits = p_enable;
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, false);
return light->directional_blend_splits;
}
VS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
return light->directional_shadow_mode;
}
void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_range_mode = p_range_mode;
}
VS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
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);
return light->use_gi;
}
uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->version;
}
AABB RasterizerStorageRD::light_get_aabb(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, AABB());
switch (light->type) {
case VS::LIGHT_SPOT: {
float len = light->param[VS::LIGHT_PARAM_RANGE];
float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case VS::LIGHT_OMNI: {
float r = light->param[VS::LIGHT_PARAM_RANGE];
return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
};
case VS::LIGHT_DIRECTIONAL: {
return AABB();
};
}
ERR_FAIL_V(AABB());
}
/* REFLECTION PROBE */
RID RasterizerStorageRD::reflection_probe_create() {
return reflection_probe_owner.make_rid(ReflectionProbe());
}
void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->intensity = p_intensity;
}
void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior_ambient = p_ambient;
}
void RasterizerStorageRD::reflection_probe_set_interior_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_energy = p_energy;
}
void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior_ambient_probe_contrib = p_contrib;
}
void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->max_distance = p_distance;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->extents = p_extents;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->box_projection = p_enable;
}
void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
ERR_FAIL_COND(p_resolution < 32);
reflection_probe->resolution = p_resolution;
}
AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, AABB());
AABB aabb;
aabb.position = -reflection_probe->extents;
aabb.size = reflection_probe->extents * 2.0;
return aabb;
}
VS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
return reflection_probe->update_mode;
}
uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->cull_mask;
}
Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
return reflection_probe->extents;
}
Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
return reflection_probe->origin_offset;
}
bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->enable_shadows;
}
float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->max_distance;
}
int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->resolution;
}
float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->intensity;
}
bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->interior;
}
bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->box_projection;
}
Color RasterizerStorageRD::reflection_probe_get_interior_ambient(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;
}
float RasterizerStorageRD::reflection_probe_get_interior_ambient_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;
}
/* RENDER TARGET API */
void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
@ -2432,6 +2888,12 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base);
p_instance->update_dependency(&mesh->instance_dependency);
} else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
p_instance->update_dependency(&rp->instance_dependency);
} else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base);
p_instance->update_dependency(&l->instance_dependency);
}
}
@ -2440,6 +2902,13 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return VS::INSTANCE_MESH;
}
if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE;
}
if (light_owner.owns(p_rid)) {
return VS::INSTANCE_LIGHT;
}
return VS::INSTANCE_NONE;
}
void RasterizerStorageRD::update_dirty_resources() {
@ -2461,6 +2930,13 @@ bool RasterizerStorageRD::free(RID p_rid) {
RD::get_singleton()->free(t->rd_texture);
}
if (t->is_proxy && t->proxy_to.is_valid()) {
Texture *proxy_to = texture_owner.getornull(t->proxy_to);
if (proxy_to) {
proxy_to->proxies.erase(p_rid);
}
}
for (int i = 0; i < t->proxies.size(); i++) {
Texture *p = texture_owner.getornull(t->proxies[i]);
ERR_CONTINUE(!p);
@ -2495,6 +2971,18 @@ bool RasterizerStorageRD::free(RID p_rid) {
Mesh *mesh = mesh_owner.getornull(p_rid);
mesh->instance_dependency.instance_notify_deleted(p_rid);
mesh_owner.free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
reflection_probe_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {
// delete the texture
Light *light = light_owner.getornull(p_rid);
light->instance_dependency.instance_notify_deleted(p_rid);
light_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.getornull(p_rid);
@ -2606,7 +3094,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
tformat.height = 4;
tformat.array_layers = 6;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
tformat.type = RD::TEXTURE_TYPE_CUBE;
tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
@ -2634,7 +3122,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
tformat.height = 4;
tformat.array_layers = 6;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
tformat.type = RD::TEXTURE_TYPE_CUBE;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
@ -2680,34 +3168,6 @@ RasterizerStorageRD::RasterizerStorageRD() {
}
}
{ //create default cubemap array
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tformat.width = 4;
tformat.height = 4;
tformat.array_layers = 6;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
pv.set(i * 4 + 3, 0);
}
{
Vector<PoolVector<uint8_t> > vpv;
for (int i = 0; i < 6; i++) {
vpv.push_back(pv);
}
default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
}
//default samplers
for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {

View file

@ -251,6 +251,12 @@ private:
RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
RID material;
uint32_t render_index = 0;
uint64_t render_pass = 0;
uint32_t multimesh_render_index = 0;
uint64_t multimesh_render_pass = 0;
};
uint32_t blend_shape_count = 0;
@ -275,6 +281,54 @@ private:
RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
/* LIGHT */
struct Light {
VS::LightType type;
float param[VS::LIGHT_PARAM_MAX];
Color color = Color(1, 1, 1, 1);
Color shadow_color;
RID projector;
bool shadow = false;
bool negative = false;
bool reverse_cull = false;
bool use_gi = true;
uint32_t cull_mask = 0xFFFFFFFF;
VS::LightOmniShadowMode omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
VS::LightDirectionalShadowMode directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
VS::LightDirectionalShadowDepthRangeMode directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
bool directional_blend_splits = false;
uint64_t version = 0;
RasterizerScene::InstanceDependency instance_dependency;
};
mutable RID_Owner<Light> light_owner;
/* REFLECTION PROBE */
struct ReflectionProbe {
VS::ReflectionProbeUpdateMode update_mode = VS::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;
float max_distance = 0;
Vector3 extents = Vector3(1, 1, 1);
Vector3 origin_offset;
bool interior = false;
bool box_projection = false;
bool enable_shadows = false;
uint32_t cull_mask = (1 << 20) - 1;
RasterizerScene::InstanceDependency instance_dependency;
};
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
/* RENDER TARGET */
struct RenderTarget {
@ -530,6 +584,32 @@ public:
return mesh_default_rd_buffers[p_buffer];
}
_FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->render_pass != p_render_pass) {
(*r_index)++;
s->render_pass = p_render_pass;
s->render_index = *r_index;
}
return s->render_index;
}
_FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->multimesh_render_pass != p_render_pass) {
(*r_index)++;
s->multimesh_render_pass = p_render_pass;
s->multimesh_render_index = *r_index;
}
return s->multimesh_render_index;
}
/* MULTIMESH API */
virtual RID multimesh_create() { return RID(); }
@ -587,68 +667,125 @@ public:
/* Light API */
RID light_create(VS::LightType p_type) { return RID(); }
RID light_create(VS::LightType p_type);
RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); }
RID omni_light_create() { return light_create(VS::LIGHT_OMNI); }
RID spot_light_create() { return light_create(VS::LIGHT_SPOT); }
void light_set_color(RID p_light, const Color &p_color) {}
void light_set_param(RID p_light, VS::LightParam p_param, float p_value) {}
void light_set_shadow(RID p_light, bool p_enabled) {}
void light_set_shadow_color(RID p_light, const Color &p_color) {}
void light_set_projector(RID p_light, RID p_texture) {}
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_color(RID p_light, const Color &p_color);
void light_set_param(RID p_light, VS::LightParam p_param, float p_value);
void light_set_shadow(RID p_light, bool p_enabled);
void light_set_shadow_color(RID p_light, const Color &p_color);
void light_set_projector(RID p_light, RID p_texture);
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_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {}
void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) {}
void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode);
void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {}
void light_directional_set_blend_splits(RID p_light, bool p_enable) {}
bool light_directional_get_blend_splits(RID p_light) const { return false; }
void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {}
VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode);
void light_directional_set_blend_splits(RID p_light, bool p_enable);
bool light_directional_get_blend_splits(RID p_light) const;
void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
bool light_has_shadow(RID p_light) const { return false; }
_FORCE_INLINE_ VS::LightType light_get_type(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
VS::LightType light_get_type(RID p_light) const { return VS::LIGHT_OMNI; }
AABB light_get_aabb(RID p_light) const { return AABB(); }
float light_get_param(RID p_light, VS::LightParam p_param) { return 0.0; }
Color light_get_color(RID p_light) { return Color(); }
bool light_get_use_gi(RID p_light) { return false; }
uint64_t light_get_version(RID p_light) const { return 0; }
return light->type;
}
AABB light_get_aabb(RID p_light) const;
_FORCE_INLINE_ float light_get_param(RID p_light, VS::LightParam p_param) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->param[p_param];
}
_FORCE_INLINE_ Color light_get_color(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, Color());
return light->color;
}
_FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, Color());
return light->shadow_color;
}
_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->cull_mask;
}
_FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
return light->shadow;
}
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
return light->negative;
}
bool light_get_use_gi(RID p_light);
uint64_t light_get_version(RID p_light) const;
/* PROBE API */
RID reflection_probe_create() { return RID(); }
RID reflection_probe_create();
void reflection_probe_set_update_mode(RID p_probe, VS::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_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) {}
void reflection_probe_set_as_interior(RID p_probe, bool p_enable) {}
void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {}
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {}
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {}
void reflection_probe_set_resolution(RID p_probe, int p_resolution) {}
void reflection_probe_set_update_mode(RID p_probe, VS::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_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);
void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
void reflection_probe_set_resolution(RID p_probe, int p_resolution);
AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); }
VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; }
uint32_t reflection_probe_get_cull_mask(RID p_probe) const { return 0; }
Vector3 reflection_probe_get_extents(RID p_probe) const { return Vector3(); }
Vector3 reflection_probe_get_origin_offset(RID p_probe) const { return Vector3(); }
float reflection_probe_get_origin_max_distance(RID p_probe) const { return 0.0; }
bool reflection_probe_renders_shadows(RID p_probe) const { return false; }
AABB reflection_probe_get_aabb(RID p_probe) const;
VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
Vector3 reflection_probe_get_extents(RID p_probe) const;
Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
float reflection_probe_get_origin_max_distance(RID p_probe) const;
int reflection_probe_get_resolution(RID p_probe) const;
bool reflection_probe_renders_shadows(RID p_probe) const;
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;
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}

View file

@ -31,10 +31,13 @@
#ifndef RENDER_PIPELINE_CACHE_RD_H
#define RENDER_PIPELINE_CACHE_RD_H
#include "core/spin_lock.h"
#include "servers/visual/rendering_device.h"
class RenderPipelineVertexFormatCacheRD {
SpinLock spin_lock;
RID shader;
uint32_t input_mask;
@ -68,12 +71,19 @@ public:
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
"Attempted to use an unused shader variant (shader is null),");
#endif
spin_lock.lock();
RID result;
for (uint32_t i = 0; i < version_count; i++) {
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
return versions[i].pipeline;
result = versions[i].pipeline;
spin_lock.unlock();
return result;
}
}
return _generate_version(p_vertex_format_id, p_framebuffer_format_id);
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id);
spin_lock.unlock();
return result;
}
_FORCE_INLINE_ uint32_t get_vertex_input_mask() const {

View file

@ -10,4 +10,5 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('scene_forward.glsl');
env.RD_GLSL('sky.glsl');
env.RD_GLSL('tonemap.glsl');
env.RD_GLSL('copy.glsl');

View file

@ -23,6 +23,10 @@ void main() {
gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
if (bool(blur.flags&FLAG_FLIP_Y)) {
uv_interp.y = 1.0 - uv_interp.y;
}
}
/* clang-format off */

View file

@ -3,6 +3,7 @@
#define FLAG_USE_ORTHOGONAL_PROJECTION (1<<2)
#define FLAG_DOF_NEAR_FIRST_TAP (1<<3)
#define FLAG_GLOW_FIRST_PASS (1<<4)
#define FLAG_FLIP_Y (1<<5)
layout(push_constant, binding = 1, std430) uniform Blur {
vec4 section;

View file

@ -0,0 +1,93 @@
/* clang-format off */
[vertex]
/* clang-format on */
#version 450
/* clang-format off */
VERSION_DEFINES
/* clang-format on */
layout(location =0) out vec2 uv_interp;
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
}
/* clang-format off */
[fragment]
/* clang-format on */
#version 450
/* clang-format off */
VERSION_DEFINES
/* clang-format on */
layout(location =0) in vec2 uv_interp;
#ifdef MODE_CUBE_TO_DP
layout( set=0, binding=0 ) uniform samplerCube source_cube;
layout(push_constant, binding = 0, std430) uniform Params {
float bias;
float z_far;
float z_near;
bool z_flip;
} params;
layout(location=0) out float depth_buffer;
#endif
void main() {
#ifdef MODE_CUBE_TO_DP
vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
normal = normalize(normal);
normal.y = -normal.y; //needs to be flipped to match projection matrix
if (!params.z_flip) {
normal.z = -normal.z;
}
float depth = texture(source_cube, normal).r;
// absolute values for direction cosines, bigger value equals closer to basis axis
vec3 unorm = abs(normal);
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
// x code
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
// y code
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
// z code
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
} else {
// oh-no we messed up code
// has to be
unorm = vec3(1.0, 0.0, 0.0);
}
float depth_fix = 1.0 / dot(normal, unorm);
depth = 2.0 * depth - 1.0;
float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
#endif
}

View file

@ -75,12 +75,26 @@ VERTEX_SHADER_GLOBALS
// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
//invariant gl_Position;
layout(location =7) flat out uint instance_index;
#ifdef MODE_DUAL_PARABOLOID
layout(location =8) out float dp_clip;
#endif
void main() {
instance_index = draw_call.instance_index;
/*if (draw_call.instance_increment) {
instance_index += gl_InstanceIndex;
}*/
vec3 vertex = vertex_attrib;
mat4 world_matrix = instance_data.transform;
mat3 world_normal_matrix= instance_data.normal_transform;
mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform);
vec3 normal = normal_attrib;
@ -131,8 +145,8 @@ void main() {
float roughness = 1.0;
mat4 modelview = scene_data.inv_camera_matrix * instance_data.transform;
mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * instance_data.normal_transform;
mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
{
/* clang-format off */
@ -179,14 +193,35 @@ VERTEX_SHADER_CODE
#ifdef MODE_RENDER_DEPTH
#ifdef MODE_DUAL_PARABOLOID
vertex_interp.z *= scene_data.dual_paraboloid_side;
normal_interp.z *= scene_data.dual_paraboloid_side;
dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
float distance = length(vtx);
vtx = normalize(vtx);
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
vertex_interp = vtx;
#else
float z_ofs = scene_data.z_offset;
z_ofs += (1.0 - abs(normal_interp.z)) * scene_data.z_slope_scale;
vertex_interp.z -= z_ofs;
#endif
#endif //MODE_RENDER_DEPTH
#ifdef USE_OVERRIDE_POSITION
gl_Position = position;
gl_Position = position;;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
@ -227,10 +262,19 @@ layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
layout(location =7) flat in uint instance_index;
#ifdef MODE_DUAL_PARABOLOID
layout(location =8) in float dp_clip;
#endif
//defines to keep compatibility with vertex
#define world_matrix instance_data.transform;
#define world_normal_matrix instance_data.normal_transform;
#define world_matrix instances.data[instance_index].transform;
#define world_normal_matrix instances.data[instance_index].normal_transform;
#define projection_matrix scene_data.projection_matrix;
#ifdef USE_MATERIAL_UNIFORMS
@ -253,10 +297,14 @@ layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
#ifndef MODE_RENDER_DEPTH
layout(location = 0) out vec4 frag_color;
#endif
#endif
// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
// We're dividing this factor off because the overall term we'll end up looks like
// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
@ -329,7 +377,24 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color,float roughness, float metallic, float specular,float specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T,float anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
inout float alpha,
#endif
inout vec3 diffuse_light, inout vec3 specular_light
) {
#if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader
@ -419,11 +484,11 @@ LIGHT_SHADER_CODE
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
#if defined(TRANSMISSION_USED)
#if defined(LIGHT_TRANSMISSION_USED)
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
#endif
#if defined(RIM_LIGHT_USED)
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
#endif
@ -517,9 +582,209 @@ LIGHT_SHADER_CODE
#endif //defined(USE_LIGHT_SHADER_CODE)
}
#ifndef USE_NO_SHADOWS
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
#ifdef SHADOW_MODE_PCF_13
float avg = textureProj(shadow, vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
return avg * (1.0 / 13.0);
#endif
#ifdef SHADOW_MODE_PCF_5
float avg = textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
return avg * (1.0 / 5.0);
#endif
#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
return textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
#endif
}
#endif //USE_NO_SHADOWS
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
inout float alpha,
#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float normalized_distance = light_length * lights.data[idx].inv_radius;
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
vec3 light_attenuation = vec3(omni_attenuation);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb*=attenuation_energy.y;
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
// there is a shadowmap
vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
float shadow_len = length(splane);
splane = normalize(splane);
vec4 clamp_rect = lights.data[idx].atlas_rect;
if (splane.z >= 0.0) {
splane.z += 1.0;
clamp_rect.y += clamp_rect.w;
} else {
splane.z = 1.0 - splane.z;
}
splane.xy /= splane.z;
splane.xy = splane.xy * 0.5 + 0.5;
splane.z = shadow_len * lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
}
#endif //USE_NO_SHADOWS
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha
#endif
diffuse_light, specular_light);
}
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
inout float alpha
#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
float normalized_distance = light_length * lights.data[idx].inv_radius;
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
vec3 spot_dir = lights.data[idx].direction;
vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
vec3 light_attenuation = vec3(spot_attenuation);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb*=attenuation_energy.y;
/*
if (lights.data[idx].atlas_rect!=vec4(0.0)) {
//use projector texture
}
*/
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
//there is a shadowmap
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
splane.xyz /= splane.w;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
}
#endif //USE_NO_SHADOWS
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
diffuse_light, specular_light);
}
void main() {
#ifdef MODE_DUAL_PARABOLOID
if (dp_clip > 0.0)
discard;
#endif
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
@ -701,14 +966,149 @@ FRAGMENT_SHADER_CODE
specular_blob_intensity *= specular * 2.0;
#endif
#ifndef MODE_RENDER_DEPTH
//gi probes
//lightmap
//lightmap capture
//process reflections
#if 0
{ // process reflections
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
for (uint i = 0; i < MAX_REFLECTION_PROBES; i++) {
if (i >= draw_data.reflection_probe_count) {
break;
}
uint ref_index;
if (i<4) {
if (i<2) {
ref_index=draw_data.reflection_probe_indices[0];
} else {
ref_index=draw_data.reflection_probe_indices[1];
}
} else {
if (i<6) {
ref_index=draw_data.reflection_probe_indices[2];
} else {
ref_index=draw_data.reflection_probe_indices[3];
}
}
ref_index>>=(i&1)*16;
ref_index&=0xFFFF;
vec3 box_extents = reflections.data[ref_index].box_extents.xyz;
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
continue;
}
vec3 ref_vec = normalize(reflect(vertex, normal));
vec3 inner_pos = abs(local_pos / box_extents);
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
//make blend more rounded
blend = mix(length(inner_pos), blend, blend);
blend *= blend;
blend = max(0.0, 1.0 - blend);
if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
if (reflections.data[ref_index].params.w > 0.5) { //box project
vec3 nrdir = normalize(local_ref_vec);
vec3 rbmax = (box_extents - local_pos) / nrdir;
vec3 rbmin = (-box_extents - local_pos) / nrdir;
vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
vec3 posonbox = local_pos + nrdir * fa;
local_ref_vec = posonbox - reflections.data[ref_index].box_offset.xyz;
}
vec4 reflection;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod,layer_blend;
layer_blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
reflection.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod)).rgb;
reflection.rgb = mix(reflection.rgb,texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod+1)).rgb,layer_blend);
#else
reflection.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif
if (reflections.data[ref_index].params.z < 0.5) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
}
reflection.rgb *= reflections.data[ref_index].params.x;
reflection.a = blend;
reflection.rgb *= reflection.a;
reflection_accum += reflection;
}
#ifndef USE_LIGHTMAP
if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
vec4 ambient_out;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
ambient_out.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, MAX_ROUGHNESS_LOD)).rgb;
#else
ambient_out.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_amb_vec, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
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;
}
#endif //USE_LIGHTMAP
}
if (reflection_accum.a > 0.0) {
specular_light = reflection_accum.rgb / reflection_accum.a;
}
#if !defined(USE_LIGHTMAP)
if (ambient_accum.a > 0.0) {
ambient_light = ambient_accum.rgb / ambient_accum.a;
}
#endif
}
#endif //0
{
#if defined(DIFFUSE_TOON)
@ -734,8 +1134,86 @@ FRAGMENT_SHADER_CODE
//directional light
{ //omni lights
uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
for (uint i = 0; i < omni_light_count; i++) {
//process omni and spots
uint light_index = instances.data[instance_index].omni_light_indices[i>>1];
if (bool(i&1)) {
light_index>>=16;
} else {
light_index&=0xFFFF;
}
//this is done on CPU, so no need to do it here
//if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
// continue; //not masked
//}
light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
diffuse_light, specular_light);
}
}
{ //spot lights
uint spot_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
for (uint i = 0; i < spot_light_count; i++) {
uint light_index = instances.data[instance_index].spot_light_indices[i>>1];
if (bool(i&1)) {
light_index>>=16;
} else {
light_index&=0xFFFF;
}
//this is done on CPU, so no need to do it here
//if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
// continue; //not masked
//}
light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
diffuse_light, specular_light);
}
}
#endif //!MODE_RENDER_DEPTH
#ifdef USE_SHADOW_TO_OPACITY
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@ -757,6 +1235,7 @@ FRAGMENT_SHADER_CODE
#endif // USE_SHADOW_TO_OPACITY
#ifdef MODE_RENDER_DEPTH
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else

View file

@ -2,6 +2,13 @@
#define M_PI 3.14159265359
#define ROUGHNESS_MAX_LOD 5
layout(push_constant, binding = 0, std430) uniform DrawCall {
uint instance_index;
uint pad[3]; //16 bits minimum size
} draw_call;
/* Set 0 Scene data, screen and sources (changes the least) */
layout(set=0,binding=1) uniform texture2D depth_buffer;
@ -35,7 +42,9 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
layout(set = 0, binding = 6) uniform sampler material_samplers[12];
layout(set=0,binding=7,std140) uniform SceneData {
layout(set = 0, binding = 7) uniform sampler shadow_sampler;
layout(set=0,binding=8,std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
@ -63,6 +72,14 @@ layout(set=0,binding=7,std140) uniform SceneData {
mat3 radiance_inverse_xform;
vec2 shadow_atlas_pixel_size;
vec2 directional_shadow_pixel_size;
uint directional_light_count;
float dual_paraboloid_side;
float z_far;
uint pad0;
#if 0
vec4 ambient_light_color;
vec4 bg_color;
@ -101,80 +118,125 @@ layout(set=0,binding=7,std140) uniform SceneData {
#endif
} scene_data;
#define INSTANCE_FLAGS_FORWARD_MASK 3
#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
struct InstanceData {
mat4 transform;
mat4 normal_transform;
uint flags;
uint instance_ofs; //instance_offset in instancing/skeleton buffer
uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
uint layer_mask;
uint reflection_probe_indices[4];
uint omni_light_indices[4];
uint spot_light_indices[4];
uint decal_indices[4];
};
layout(set=0,binding=9,std430) buffer Instances {
InstanceData data[];
} instances;
struct ReflectionData {
vec4 box_extents;
vec4 box_offset;
vec4 params; // intensity, 0, interior , boxproject
vec4 ambient; // ambient color, energy
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
};
layout(set=0,binding=10,std140) uniform ReflectionProbeData {
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
} reflections;
struct LightData { //this structure needs to be 128 bits
vec3 position;
float inv_radius;
vec3 direction;
uint attenuation_energy; //attenuation
uint color_specular; //rgb color, a specular (8 bit unorm)
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
uint mask;
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
mat4 shadow_matrix;
};
layout(set=0,binding=11,std140) uniform Lights {
LightData data[MAX_LIGHT_DATA_STRUCTS];
} lights;
layout(set=0,binding=12) uniform texture2D shadow_atlas;
#if 0
struct DirectionalLightData {
vec4 light_pos_inv_radius;
vec4 light_direction_attenuation;
vec4 light_color_energy;
vec4 light_params; // cone attenuation, angle, specular, shadow enabled,
vec4 light_clamp;
vec4 shadow_color_contact;
vec3 direction;
float energy;
vec3 color;
float specular;
uint mask;
uint pad0,pad1,pad2;
vec3 shadow_color;
bool shadow_enabled;
vec4 shadow_atlas_rect;
vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
vec4 shadow_split_offsets;
};
#endif
/* Set 1 Skeleton Data (most objects lack it, so it changes little */
};
layout(set=0,binding=13,std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
} directional_lights;
layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
/*
layout(set=0,binding=15,std430) buffer Skeletons {
vec4 data[];
} skeletons;
*/
/* Set 1 Instancing (Multimesh) */
//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
/* Set 2 Instancing (Multimesh) data */
#if 0
layout(set = 1 binding = 0, std140) uniform SkeletonData {
mat4 transform;
bool use_skeleton;
bool use_world_coords;
bool pad1;
bool pad2;
} skeleton;
layout(set = 1, binding = 1) uniform textureBuffer skeleton_bones;
#endif
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
/* Set 2 Custom Material Data (changess less than instance) */
layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
#else
/* Set 3 Instance Data (Set on every draw call) */
layout(push_constant, binding = 0, std430) uniform DrawData {
//used in forward rendering, 16 bits indices, max 8
uint reflection_probe_count;
uint omni_light_count;
uint spot_light_count;
uint decal_count;
uvec4 reflection_probe_indices;
uvec4 omni_light_indices;
uvec4 spot_light_indices;
uvec4 decal_indices;
} draw_data;
layout(set = 3, binding = 0, std140) uniform InstanceData {
mat4 transform;
mat3 normal_transform;
uint flags;
uint pad0;
uint pad1;
uint pad2;
} instance_data;
layout(set = 3, binding = 1) uniform textureBuffer multimesh_transforms;
#ifdef USE_LIGHTMAP
layout(set = 3, binding = 2) uniform texture2D lightmap;
layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
#endif
#ifdef USE_VOXEL_CONE_TRACING
layout(set = 3, binding = 3) uniform texture3D gi_probe[2];
layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
layout(set = 3, binding = 4) uniform texture3D gi_probe_aniso_pos[2];
layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_neg[2];
layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_pos[2];
layout(set = 3, binding = 6) uniform texture3D gi_probe_aniso_neg[2];
#endif
#endif
#endif

View file

@ -166,7 +166,9 @@ vec3 tonemap_reinhard(vec3 color, float white) {
return (white * color + color) / (color * white + white);
}
vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1]
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)));
}
@ -233,15 +235,9 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
return color + glow;
} else if (params.glow_mode==GLOW_MODE_SCREEN) {
//need color clamping
color = clamp(color,0.0,1.0);
glow = clamp(glow,0.0,1.0);
return max((color + glow) - (color * glow), vec3(0.0));
} else if ( params.glow_mode==GLOW_MODE_SOFTLIGHT) {
//need color clamping
color = clamp(color,0.0,1.0);
glow = clamp(glow,0.0,1.0);
glow = glow * vec3(0.5f) + vec3(0.5f);
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));

View file

@ -103,9 +103,9 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
VSG::rasterizer->begin_frame(frame_step);
VSG::scene->update_dirty_instances(); //update scene stuff
VSG::scene_render->update(); //update scenes stuff before updating instances
VSG::scene_render->update();
VSG::scene->update_dirty_instances(); //update scene stuff
VSG::viewport->draw_viewports();
VSG::scene->render_probes();

View file

@ -313,7 +313,6 @@ public:
BIND2(light_set_use_gi, RID, bool)
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
BIND2(light_directional_set_blend_splits, RID, bool)
@ -489,6 +488,8 @@ public:
//from now on, calls forwarded to this singleton
#define BINDBASE VSG::scene_render
BIND1(directional_shadow_atlas_set_size, int)
/* SKY API */
BIND0R(RID, sky_create)
@ -535,7 +536,6 @@ public:
BIND2(scenario_set_debug, RID, ScenarioDebugMode)
BIND2(scenario_set_environment, RID, RID)
BIND3(scenario_set_reflection_atlas_size, RID, int, int)
BIND2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */

View file

@ -268,7 +268,6 @@ RID VisualServerScene::scenario_create() {
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
scenario->reflection_atlas = VSG::scene_render->reflection_atlas_create();
return scenario_rid;
}
@ -294,14 +293,6 @@ void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_
scenario->fallback_environment = p_environment;
}
void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) {
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_size);
VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas, p_subdiv);
}
/* INSTANCING API */
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@ -360,11 +351,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
instance->octree_id = 0;
}
if (instance->custom_data) {
VSG::scene_render->instance_free_custom_data(instance);
instance->custom_data = nullptr;
}
switch (instance->base_type) {
case VS::INSTANCE_LIGHT: {
@ -494,8 +480,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
VSG::storage->base_update_dependency(p_base, instance);
VSG::scene_render->instance_create_custom_data(instance);
}
_instance_queue_update(instance, true, true);
@ -527,8 +511,6 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
} break;
case VS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
} break;
case VS::INSTANCE_GI_PROBE: {
@ -710,10 +692,6 @@ void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap
lightmap_capture->users.insert(instance);
instance->lightmap = p_lightmap;
}
if (instance->custom_data) {
VSG::scene_render->instance_custom_data_update_lightmap(instance);
}
}
void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@ -943,10 +921,6 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
if (p_instance->custom_data) {
VSG::scene_render->instance_custom_data_update_transform(p_instance);
}
if (!p_instance->scenario) {
return;
@ -1614,12 +1588,12 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
//using this one ensures that raster deferred will have it
static const Vector3 view_normals[6] = {
Vector3(-1, 0, 0),
Vector3(+1, 0, 0),
Vector3(-1, 0, 0),
Vector3(0, -1, 0),
Vector3(0, +1, 0),
Vector3(0, 0, -1),
Vector3(0, 0, +1)
Vector3(0, 0, +1),
Vector3(0, 0, -1)
};
static const Vector3 view_up[6] = {
Vector3(0, -1, 0),
@ -1920,10 +1894,8 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
reflection_probe->reflection_dirty = false;
}
if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
reflection_probe_cull_count++;
}
reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
reflection_probe_cull_count++;
}
}
}
@ -1970,10 +1942,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->lighting_dirty = false;
if (ins->custom_data) {
VSG::scene_render->instance_custom_data_update_lights(ins);
}
}
if (geom->reflection_dirty) {
@ -1989,10 +1957,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->reflection_dirty = false;
if (ins->custom_data) {
VSG::scene_render->instance_custom_data_update_reflection_probes(ins);
}
}
if (geom->gi_probes_dirty) {
@ -2008,10 +1972,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->gi_probes_dirty = false;
if (ins->custom_data) {
VSG::scene_render->instance_custom_data_update_gi_probes(ins);
}
}
ins->depth = near_plane.distance_to(ins->transform.origin);
@ -2188,7 +2148,7 @@ void VisualServerScene::_render_scene(RID p_render_buffers, const Transform p_ca
/* PROCESS GEOMETRY AND DRAW SCENE */
VSG::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, environment, p_shadow_atlas, scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
VSG::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, environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@ -2202,7 +2162,7 @@ void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->environment;
else
environment = scenario->fallback_environment;
VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, RID(), 0);
#endif
}
@ -2216,9 +2176,7 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
if (p_step == 0) {
if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
return true; //sorry, all full :(
}
VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance);
}
if (p_step >= 0 && p_step < 6) {
@ -3507,7 +3465,6 @@ bool VisualServerScene::free(RID p_rid) {
instance_set_scenario(scenario->instances.first()->self()->self, RID());
}
VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
VSG::scene_render->free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
memdelete(scenario);

View file

@ -115,7 +115,6 @@ public:
RID environment;
RID fallback_environment;
RID reflection_probe_shadow_atlas;
RID reflection_atlas;
SelfList<Instance>::List instances;
@ -132,7 +131,6 @@ public:
virtual void scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv);
/* INSTANCING API */

View file

@ -240,7 +240,6 @@ public:
FUNC2(light_set_use_gi, RID, bool)
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
@ -404,6 +403,8 @@ public:
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
FUNC1(directional_shadow_atlas_set_size, int)
/* SKY API */
FUNCRID(sky)
@ -447,7 +448,6 @@ public:
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
FUNC2(scenario_set_environment, RID, RID)
FUNC3(scenario_set_reflection_atlas_size, RID, int, int)
FUNC2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */

View file

@ -1694,7 +1694,6 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &VisualServer::light_set_use_gi);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &VisualServer::light_omni_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_detail", "light", "detail"), &VisualServer::light_omni_set_shadow_detail);
ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &VisualServer::light_directional_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &VisualServer::light_directional_set_blend_splits);
@ -1836,7 +1835,6 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("scenario_create"), &VisualServer::scenario_create);
ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &VisualServer::scenario_set_debug);
ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &VisualServer::scenario_set_environment);
ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "size", "subdiv"), &VisualServer::scenario_set_reflection_atlas_size);
ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &VisualServer::scenario_set_fallback_environment);
#ifndef _3D_DISABLED
@ -2056,8 +2054,6 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_VERTICAL);
BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);

View file

@ -432,14 +432,6 @@ public:
virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0;
// omni light
enum LightOmniShadowDetail {
LIGHT_OMNI_SHADOW_DETAIL_VERTICAL,
LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL
};
virtual void light_omni_set_shadow_detail(RID p_light, LightOmniShadowDetail p_detail) = 0;
// directional light
enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
@ -667,12 +659,17 @@ public:
enum ViewportDebugDraw {
VIEWPORT_DEBUG_DRAW_DISABLED,
VIEWPORT_DEBUG_DRAW_UNSHADED,
VIEWPORT_DEBUG_DRAW_LIGHTING,
VIEWPORT_DEBUG_DRAW_OVERDRAW,
VIEWPORT_DEBUG_DRAW_WIREFRAME,
VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS
};
virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
virtual void directional_shadow_atlas_set_size(int p_size) = 0;
/* SKY API */
enum SkyMode {
@ -792,7 +789,6 @@ public:
virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
/* INSTANCING API */
@ -1106,7 +1102,6 @@ VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat);
VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat);
VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat);
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowDetail);
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode);
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode);
VARIANT_ENUM_CAST(VisualServer::ReflectionProbeUpdateMode);