GIProbes working.

This commit is contained in:
Juan Linietsky 2019-10-03 17:39:08 -03:00
parent 52f96abd8b
commit acf0f6c8a7
51 changed files with 5085 additions and 5109 deletions

View file

@ -335,6 +335,19 @@ StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
return ti->inherits;
}
StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) {
if (classes.has(p_class)) {
return p_class;
}
if (compat_classes.has(p_class)) {
return compat_classes[p_class];
}
return p_class;
}
StringName ClassDB::get_parent_class(const StringName &p_class) {
OBJTYPE_RLOCK;

View file

@ -218,6 +218,7 @@ public:
static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static StringName get_parent_class_nocheck(const StringName &p_class);
static StringName get_parent_class(const StringName &p_class);
static StringName get_compatibility_remapped_class(const StringName &p_class);
static bool class_exists(const StringName &p_class);
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instance(const StringName &p_class);

View file

@ -1255,7 +1255,7 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
ria->res_path = ria->local_path;
//ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
String r = ria->recognize(f);
return r;
return ClassDB::get_compatibility_remapped_class(r);
}
///////////////////////////////////////////////////////////

View file

@ -729,8 +729,9 @@ String ResourceLoader::get_resource_type(const String &p_path) {
for (int i = 0; i < loader_count; i++) {
String result = loader[i]->get_resource_type(local_path);
if (result != "")
if (result != "") {
return result;
}
}
return "";

View file

@ -32,6 +32,7 @@
#define VECTOR3_H
#include "core/math/math_funcs.h"
#include "core/math/vector3i.h"
#include "core/ustring.h"
class Basis;
@ -147,6 +148,15 @@ struct Vector3 {
_FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const;
operator String() const;
_FORCE_INLINE_ operator Vector3i() const {
return Vector3i(x, y, z);
}
_FORCE_INLINE_ Vector3(const Vector3i &p_ivec) {
x = p_ivec.x;
y = p_ivec.y;
z = p_ivec.z;
}
_FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) {
x = p_x;

25
core/math/vector3i.cpp Normal file
View file

@ -0,0 +1,25 @@
#include "vector3i.h"
void Vector3i::set_axis(int p_axis, int32_t p_value) {
ERR_FAIL_INDEX(p_axis, 3);
coord[p_axis] = p_value;
}
int32_t Vector3i::get_axis(int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 3, 0);
return operator[](p_axis);
}
int Vector3i::min_axis() const {
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
}
int Vector3i::max_axis() const {
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
}
Vector3i::operator String() const {
return (itos(x) + ", " + itos(y) + ", " + itos(z));
}

242
core/math/vector3i.h Normal file
View file

@ -0,0 +1,242 @@
#ifndef VECTOR3I_H
#define VECTOR3I_H
#include "core/typedefs.h"
#include "core/ustring.h"
struct Vector3i {
enum Axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
union {
struct {
int32_t x;
int32_t y;
int32_t z;
};
int32_t coord[3];
};
_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
return coord[p_axis];
}
_FORCE_INLINE_ int32_t &operator[](int p_axis) {
return coord[p_axis];
}
void set_axis(int p_axis, int32_t p_value);
int32_t get_axis(int p_axis) const;
int min_axis() const;
int max_axis() const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
/* Operators */
_FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator+(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator-=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator-(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator*=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator*(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator/=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator/(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i operator-() const;
_FORCE_INLINE_ bool operator==(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator!=(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator<(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator>(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator>=(const Vector3i &p_v) const;
operator String() const;
_FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) {
x = p_x;
y = p_y;
z = p_z;
}
_FORCE_INLINE_ Vector3i() { x = y = z = 0; }
};
Vector3i Vector3i::abs() const {
return Vector3i(ABS(x), ABS(y), ABS(z));
}
Vector3i Vector3i::sign() const {
return Vector3i(SGN(x), SGN(y), SGN(z));
}
/* Operators */
Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
x += p_v.x;
y += p_v.y;
z += p_v.z;
return *this;
}
Vector3i Vector3i::operator+(const Vector3i &p_v) const {
return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z);
}
Vector3i &Vector3i::operator-=(const Vector3i &p_v) {
x -= p_v.x;
y -= p_v.y;
z -= p_v.z;
return *this;
}
Vector3i Vector3i::operator-(const Vector3i &p_v) const {
return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z);
}
Vector3i &Vector3i::operator*=(const Vector3i &p_v) {
x *= p_v.x;
y *= p_v.y;
z *= p_v.z;
return *this;
}
Vector3i Vector3i::operator*(const Vector3i &p_v) const {
return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z);
}
Vector3i &Vector3i::operator/=(const Vector3i &p_v) {
x /= p_v.x;
y /= p_v.y;
z /= p_v.z;
return *this;
}
Vector3i Vector3i::operator/(const Vector3i &p_v) const {
return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z);
}
Vector3i &Vector3i::operator*=(int32_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
return *this;
}
_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vec) {
return p_vec * p_scalar;
}
Vector3i Vector3i::operator*(int32_t p_scalar) const {
return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
}
Vector3i &Vector3i::operator/=(int32_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
return *this;
}
Vector3i Vector3i::operator/(int32_t p_scalar) const {
return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar);
}
Vector3i Vector3i::operator-() const {
return Vector3i(-x, -y, -z);
}
bool Vector3i::operator==(const Vector3i &p_v) const {
return (x == p_v.x && y == p_v.y && z == p_v.z);
}
bool Vector3i::operator!=(const Vector3i &p_v) const {
return (x != p_v.x || y == p_v.y || z == p_v.z);
}
bool Vector3i::operator<(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y)
return z < p_v.z;
else
return y < p_v.y;
} else {
return x < p_v.x;
}
}
bool Vector3i::operator>(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y)
return z > p_v.z;
else
return y > p_v.y;
} else {
return x > p_v.x;
}
}
bool Vector3i::operator<=(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y)
return z <= p_v.z;
else
return y < p_v.y;
} else {
return x < p_v.x;
}
}
bool Vector3i::operator>=(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y)
return z >= p_v.z;
else
return y > p_v.y;
} else {
return x > p_v.x;
}
}
void Vector3i::zero() {
x = y = z = 0;
}
#endif // VECTOR3I_H

View file

@ -1950,6 +1950,9 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_CUBEMAP && (src_texture->type != TEXTURE_TYPE_CUBE && src_texture->type != TEXTURE_TYPE_CUBE_ARRAY), RID(),
"Can only create a cubemap slice from a cubemap or cubemap array mipmap");
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_3D && src_texture->type != TEXTURE_TYPE_3D, RID(),
"Can only create a 3D slice from a 3D texture");
//create view
ERR_FAIL_INDEX_V(p_mipmap, src_texture->mipmaps, RID());
@ -1976,7 +1979,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
VK_IMAGE_VIEW_TYPE_2D,
};
image_view_create_info.viewType = p_slice_type == TEXTURE_SLICE_CUBEMAP ? VK_IMAGE_VIEW_TYPE_CUBE : view_types[texture.type];
image_view_create_info.viewType = p_slice_type == TEXTURE_SLICE_CUBEMAP ? VK_IMAGE_VIEW_TYPE_CUBE : (p_slice_type == TEXTURE_SLICE_3D ? VK_IMAGE_VIEW_TYPE_3D : view_types[texture.type]);
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
image_view_create_info.format = vulkan_formats[texture.format];
} else {
@ -2676,6 +2679,94 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
return OK;
}
Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw) {
Texture *src_tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!src_tex, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_sync_with_draw && src_tex->bound, ERR_INVALID_PARAMETER,
"Source texture can't be cleared while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V(p_layers == 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_mipmaps == 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
"Source texture requires the TEXTURE_USAGE_CAN_COPY_TO_BIT in order to be cleared.");
uint32_t src_layer_count = src_tex->layers;
if (src_tex->type == TEXTURE_TYPE_CUBE || src_tex->type == TEXTURE_TYPE_CUBE_ARRAY) {
src_layer_count *= 6;
}
ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER);
VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
VkImageLayout layout = src_tex->layout;
if (src_tex->layout != VK_IMAGE_LAYOUT_GENERAL) { //storage may be in general state
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = 0;
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.oldLayout = src_tex->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
image_memory_barrier.subresourceRange.layerCount = p_layers;
layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
VkClearColorValue clear_color;
clear_color.float32[0] = p_color.r;
clear_color.float32[1] = p_color.g;
clear_color.float32[2] = p_color.b;
clear_color.float32[3] = p_color.a;
VkImageSubresourceRange range;
range.aspectMask = src_tex->read_aspect_mask;
range.baseArrayLayer = p_base_layer;
range.layerCount = p_layers;
range.baseMipLevel = p_base_mipmap;
range.levelCount = p_mipmaps;
vkCmdClearColorImage(command_buffer, src_tex->image, layout, &clear_color, 1, &range);
if (src_tex->layout != VK_IMAGE_LAYOUT_GENERAL) { //storage may be in general state
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.newLayout = src_tex->layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
image_memory_barrier.subresourceRange.layerCount = p_layers;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
return OK;
}
bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const {
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);
@ -2719,7 +2810,7 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
/**** ATTACHMENT ****/
/********************/
VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, int *r_color_attachment_count) {
VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, int *r_color_attachment_count) {
Vector<VkAttachmentDescription> attachments;
Vector<VkAttachmentReference> color_references;
@ -2739,17 +2830,18 @@ 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 is_depth_stencil = p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
bool is_sampled = p_format[i].usage_flags & TEXTURE_USAGE_SAMPLING_BIT;
bool is_storage = p_format[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT;
switch (p_initial_action) {
switch (is_depth_stencil ? p_initial_depth_action : p_initial_color_action) {
case INITIAL_ACTION_CLEAR: {
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
} break;
case INITIAL_ACTION_KEEP_COLOR: {
case INITIAL_ACTION_KEEP: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -2764,22 +2856,6 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
case INITIAL_ACTION_KEEP_COLOR_AND_DEPTH: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : 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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
case INITIAL_ACTION_CONTINUE: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@ -2800,8 +2876,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
}
switch (p_final_action) {
case FINAL_ACTION_READ_COLOR_AND_DEPTH: {
switch (is_depth_stencil ? p_final_depth_action : p_final_color_action) {
case FINAL_ACTION_READ: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -2817,59 +2893,42 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
break;
case FINAL_ACTION_READ_COLOR_DISCARD_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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
} break;
case FINAL_ACTION_DISCARD: {
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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : 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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
case FINAL_ACTION_DISCARD: {
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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : 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 = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
case FINAL_ACTION_CONTINUE: {
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_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_STENCIL_ATTACHMENT_OPTIMAL;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
default: {
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
case FINAL_ACTION_CONTINUE: {
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_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_STENCIL_ATTACHMENT_OPTIMAL;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
default: {
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
}
}
@ -2945,7 +3004,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
}
int color_references;
VkRenderPass render_pass = _render_pass_create(p_format, INITIAL_ACTION_CLEAR, FINAL_ACTION_DISCARD, &color_references); //actions don't matter for this use case
VkRenderPass render_pass = _render_pass_create(p_format, INITIAL_ACTION_CLEAR, FINAL_ACTION_DISCARD, INITIAL_ACTION_CLEAR, FINAL_ACTION_DISCARD, &color_references); //actions don't matter for this use case
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
return INVALID_ID;
@ -5240,17 +5299,19 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(in
return ID_TYPE_DRAW_LIST;
}
Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass) {
Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass) {
Framebuffer::VersionKey vk;
vk.initial_action = p_initial_action;
vk.final_action = p_final_action;
vk.initial_color_action = p_initial_color_action;
vk.final_color_action = p_final_color_action;
vk.initial_depth_action = p_initial_depth_action;
vk.final_depth_action = p_final_depth_action;
if (!p_framebuffer->framebuffers.has(vk)) {
//need to create this version
Framebuffer::Version version;
version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, p_initial_action, p_final_action);
version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action);
VkFramebufferCreateInfo framebuffer_create_info;
framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
@ -5283,7 +5344,7 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
return OK;
}
Error RenderingDeviceVulkan::_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) {
Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents) {
VkRenderPassBeginInfo render_pass_begin;
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@ -5297,12 +5358,15 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
render_pass_begin.renderArea.offset.y = viewport_offset.y;
Vector<VkClearValue> clear_values;
if (p_initial_action == INITIAL_ACTION_CLEAR) {
clear_values.resize(framebuffer->texture_ids.size());
{
int color_index = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.getornull(framebuffer->texture_ids[i]);
VkClearValue clear_value;
if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
if (color_index < p_clear_colors.size() && texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); //a bug
Color clear_color = p_clear_colors[color_index];
clear_value.color.float32[0] = clear_color.r;
@ -5311,15 +5375,15 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
clear_value.color.float32[3] = clear_color.a;
color_index++;
} else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
clear_value.depthStencil.depth = 1.0;
clear_value.depthStencil.stencil = 0;
clear_value.depthStencil.depth = p_clear_depth;
clear_value.depthStencil.stencil = p_clear_stencil;
} else {
clear_value.color.float32[0] = 0;
clear_value.color.float32[1] = 0;
clear_value.color.float32[2] = 0;
clear_value.color.float32[3] = 0;
}
clear_values.push_back(clear_value);
clear_values.write[i] = clear_value;
}
}
@ -5330,7 +5394,9 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
//mark textures as bound
draw_list_bound_textures.clear();
draw_list_unbind_textures = p_final_action != FINAL_ACTION_CONTINUE;
draw_list_unbind_color_textures = p_final_color_action != FINAL_ACTION_CONTINUE;
draw_list_unbind_depth_textures = p_final_depth_action != FINAL_ACTION_CONTINUE;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.getornull(framebuffer->texture_ids[i]);
texture->bound = true;
@ -5340,13 +5406,13 @@ 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) {
void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) {
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) {
if (p_clear_color && 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;
@ -5355,10 +5421,10 @@ void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list,
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) {
} else if (p_clear_depth && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
clear_at.clearValue.depthStencil.depth = 1.0;
clear_at.clearValue.depthStencil.stencil = 0;
clear_at.clearValue.depthStencil.depth = p_depth;
clear_at.clearValue.depthStencil.stencil = p_stencil;
clear_at.colorAttachment = 0;
clear_at.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (format_has_stencil(texture->format)) {
@ -5381,7 +5447,7 @@ void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list,
vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr);
}
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, const Rect2 &p_region) {
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
_THREAD_SAFE_METHOD_
@ -5393,7 +5459,8 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
bool needs_clear_region = false;
bool needs_clear_color = false;
bool needs_clear_depth = false;
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
Rect2i viewport(viewport_offset, viewport_size);
@ -5407,27 +5474,31 @@ 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_color_action == INITIAL_ACTION_CLEAR) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
}
if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values
int color_attachments = framebuffer_formats[framebuffer->format_id].color_attachments;
ERR_FAIL_COND_V_MSG(p_clear_colors.size() != color_attachments, INVALID_ID,
"Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer (" + itos(color_attachments) + ").");
ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_attachments, INVALID_ID,
"Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer (" + itos(color_attachments) + ").");
}
VkFramebuffer vkframebuffer;
VkRenderPass render_pass;
Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_action, p_final_action, &vkframebuffer, &render_pass);
Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, &vkframebuffer, &render_pass);
ERR_FAIL_COND_V(err != OK, INVALID_ID);
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
err = _draw_list_render_pass_begin(framebuffer, p_initial_action, p_final_action, p_clear_colors, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE);
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE);
if (err != OK) {
return INVALID_ID;
@ -5441,8 +5512,8 @@ 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);
if (needs_clear_color || needs_clear_depth) {
_draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil);
}
VkViewport viewport;
@ -5467,7 +5538,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
return ID_TYPE_DRAW_LIST;
}
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, const Rect2 &p_region) {
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
_THREAD_SAFE_METHOD_
@ -5479,7 +5550,8 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
bool needs_clear_region = false;
bool needs_clear_color = false;
bool needs_clear_depth = false;
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
Rect2i viewport(viewport_offset, viewport_size);
@ -5493,17 +5565,21 @@ 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_color_action == INITIAL_ACTION_CLEAR) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
}
if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values
int color_attachments = framebuffer_formats[framebuffer->format_id].color_attachments;
ERR_FAIL_COND_V_MSG(p_clear_colors.size() != color_attachments, ERR_INVALID_PARAMETER,
"Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer (" + itos(color_attachments) + ").");
ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_attachments, ERR_INVALID_PARAMETER,
"Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer (" + itos(color_attachments) + ").");
}
if (p_splits > (uint32_t)split_draw_list_allocators.size()) {
@ -5543,11 +5619,11 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
VkFramebuffer vkframebuffer;
VkRenderPass render_pass;
Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_action, p_final_action, &vkframebuffer, &render_pass);
Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, &vkframebuffer, &render_pass);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
VkCommandBuffer frame_command_buffer = frames[frame].draw_command_buffer;
err = _draw_list_render_pass_begin(framebuffer, p_initial_action, p_final_action, p_clear_colors, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
if (err != OK) {
return ERR_CANT_CREATE;
@ -5596,8 +5672,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);
if (i == 0 && (needs_clear_color || needs_clear_depth)) {
_draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil);
}
VkViewport viewport;
@ -5626,6 +5703,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
}
RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawListID p_id) {
if (p_id < 0) {
return NULL;
}
@ -5841,7 +5919,7 @@ void RenderingDeviceVulkan::draw_list_set_push_constant(DrawListID p_list, void
#endif
}
void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances) {
void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances, uint32_t p_procedural_vertices) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
@ -5902,8 +5980,12 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
if (p_use_indices) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(p_procedural_vertices > 0,
"Procedural vertices can't be used together with indices.");
ERR_FAIL_COND_MSG(!dl->validation.index_array_size,
"Draw command requested indices, but no index buffer was set.");
if (dl->validation.pipeline_vertex_format != INVALID_ID) {
//uses vertices, do some vertex validations
ERR_FAIL_COND_MSG(dl->validation.vertex_array_size < dl->validation.index_array_max_index,
@ -5924,11 +6006,23 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
#endif
vkCmdDrawIndexed(dl->command_buffer, to_draw, p_instances, dl->validation.index_array_offset, 0, 0);
} else {
uint32_t to_draw;
if (p_procedural_vertices > 0) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format == INVALID_ID,
"Draw command lacks indices, but pipeline format does not use vertices.");
"Procedural vertices requested, but pipeline expects a vertex array.");
#endif
uint32_t to_draw = dl->validation.vertex_array_size;
to_draw = p_procedural_vertices;
} else {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format == INVALID_ID,
"Draw command lacks indices, but pipeline format does not use vertices.");
#endif
to_draw = dl->validation.vertex_array_size;
}
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum,
@ -5937,6 +6031,7 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0,
"Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ").");
#endif
vkCmdDraw(dl->command_buffer, to_draw, p_instances, 0, 0);
}
}
@ -6005,13 +6100,17 @@ void RenderingDeviceVulkan::draw_list_end() {
draw_list = NULL;
}
if (draw_list_unbind_textures) {
for (int i = 0; i < draw_list_bound_textures.size(); i++) {
Texture *texture = texture_owner.getornull(draw_list_bound_textures[i]);
ERR_CONTINUE(!texture); //wtf
for (int i = 0; i < draw_list_bound_textures.size(); i++) {
Texture *texture = texture_owner.getornull(draw_list_bound_textures[i]);
ERR_CONTINUE(!texture); //wtf
if (draw_list_unbind_color_textures && (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {
texture->bound = false;
}
if (draw_list_unbind_depth_textures && (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
texture->bound = false;
}
}
draw_list_bound_textures.clear();
// To ensure proper synchronization, we must make sure rendering is done before:
@ -6168,7 +6267,7 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = textures_to_storage[i]->image;
image_memory_barrier.subresourceRange.aspectMask = textures_to_sampled[i]->read_aspect_mask;
image_memory_barrier.subresourceRange.aspectMask = textures_to_storage[i]->read_aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = textures_to_storage[i]->mipmaps;
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
@ -6197,6 +6296,7 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
}
#endif
}
void RenderingDeviceVulkan::compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size) {
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
ERR_FAIL_COND(!compute_list);
@ -6223,6 +6323,10 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
ComputeList *cl = compute_list;
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(p_x_groups > limits.maxComputeWorkGroupCount[0]);
ERR_FAIL_COND(p_y_groups > limits.maxComputeWorkGroupCount[1]);
ERR_FAIL_COND(p_z_groups > limits.maxComputeWorkGroupCount[2]);
ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified.");
#endif
@ -6267,6 +6371,11 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
vkCmdDispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups);
}
void RenderingDeviceVulkan::compute_list_add_barrier(ComputeListID p_list) {
_memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, true);
}
void RenderingDeviceVulkan::compute_list_end() {
ERR_FAIL_COND(!compute_list);
@ -6295,6 +6404,9 @@ void RenderingDeviceVulkan::compute_list_end() {
}
memdelete(compute_list);
compute_list = NULL;
_memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, true);
}
#if 0

View file

@ -259,7 +259,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
};
VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, int *r_color_attachment_count = NULL);
VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depthcolor_action, int *r_color_attachment_count = NULL);
// This is a cache and it's never freed, it ensures
// IDs for a given format are always unique.
@ -276,13 +276,23 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct Framebuffer {
FramebufferFormatID format_id;
struct VersionKey {
InitialAction initial_action;
FinalAction final_action;
InitialAction initial_color_action;
FinalAction final_color_action;
InitialAction initial_depth_action;
FinalAction final_depth_action;
bool operator<(const VersionKey &p_key) const {
if (initial_action == p_key.initial_action) {
return final_action < p_key.final_action;
if (initial_color_action == p_key.initial_color_action) {
if (final_color_action == p_key.final_color_action) {
if (initial_depth_action == p_key.initial_depth_action) {
return final_depth_action < p_key.final_depth_action;
} else {
return initial_depth_action < p_key.initial_depth_action;
}
} else {
return final_color_action < p_key.final_color_action;
}
} else {
return initial_action < p_key.initial_action;
return initial_color_action < p_key.initial_color_action;
}
}
};
@ -806,11 +816,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t draw_list_count;
bool draw_list_split;
Vector<RID> draw_list_bound_textures;
bool draw_list_unbind_textures;
bool draw_list_unbind_color_textures;
bool draw_list_unbind_depth_textures;
void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, 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);
void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
/**********************/
@ -966,6 +977,7 @@ public:
virtual bool texture_is_valid(RID p_texture);
virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false);
virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false);
/*********************/
/**** FRAMEBUFFER ****/
@ -1046,8 +1058,9 @@ public:
/********************/
virtual DrawListID draw_list_begin_for_screen(int p_screen = 0, const Color &p_clear_color = Color());
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors = Vector<Color>(), const Rect2 &p_region = Rect2());
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors = Vector<Color>(), const Rect2 &p_region = Rect2());
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline);
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index);
@ -1056,7 +1069,7 @@ public:
virtual void draw_list_set_line_width(DrawListID p_list, float p_width);
virtual void draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size);
virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1);
virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0);
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);
virtual void draw_list_disable_scissor(DrawListID p_list);
@ -1071,6 +1084,8 @@ public:
virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline);
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index);
virtual void compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size);
virtual void compute_list_add_barrier(ComputeListID p_list);
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);
virtual void compute_list_end();

View file

@ -53,6 +53,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(VkDebugU
strstr(pCallbackData->pMessage, "can result in undefined behavior if this memory is used by the device") != NULL) {
return VK_FALSE;
}
// This needs to be ignored because Validator is wrong here
if (strstr(pCallbackData->pMessage, "SPIR-V module not valid: Pointer operand") != NULL &&
strstr(pCallbackData->pMessage, "must be a memory object") != NULL) {
return VK_FALSE;
}
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
strcat(prefix, "VERBOSE : ");

View file

@ -6682,7 +6682,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(TextureRegionEditorPlugin(this)));
add_editor_plugin(memnew(Particles2DEditorPlugin(this)));
add_editor_plugin(memnew(GIProbeEditorPlugin(this)));
add_editor_plugin(memnew(BakedLightmapEditorPlugin(this)));
// add_editor_plugin(memnew(BakedLightmapEditorPlugin(this)));
add_editor_plugin(memnew(Path2DEditorPlugin(this)));
add_editor_plugin(memnew(PathEditorPlugin(this)));
add_editor_plugin(memnew(Line2DEditorPlugin(this)));

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#if 0
#include "baked_lightmap_editor_plugin.h"
void BakedLightmapEditorPlugin::_bake() {
@ -124,3 +125,4 @@ BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) {
BakedLightmapEditorPlugin::~BakedLightmapEditorPlugin() {
}
#endif

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#if 0
#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H
#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H
@ -67,3 +68,4 @@ public:
};
#endif // BAKED_LIGHTMAP_EDITOR_PLUGIN_H
#endif

View file

@ -2759,43 +2759,60 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(idx, !current);
} break;
case VIEW_DISPLAY_NORMAL: {
case VIEW_DISPLAY_NORMAL:
case VIEW_DISPLAY_WIREFRAME:
case VIEW_DISPLAY_OVERDRAW:
case VIEW_DISPLAY_SHADELESS:
case VIEW_DISPLAY_LIGHTING:
case VIEW_DISPLAY_DEBUG_SHADOW_ATLAS:
case VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS:
case VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO:
case VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING: {
viewport->set_debug_draw(Viewport::DEBUG_DRAW_DISABLED);
static const int display_options[] = {
VIEW_DISPLAY_NORMAL,
VIEW_DISPLAY_WIREFRAME,
VIEW_DISPLAY_OVERDRAW,
VIEW_DISPLAY_SHADELESS,
VIEW_DISPLAY_LIGHTING,
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO,
VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING,
VIEW_MAX
};
static const Viewport::DebugDraw debug_draw_modes[] = {
Viewport::DEBUG_DRAW_DISABLED,
Viewport::DEBUG_DRAW_WIREFRAME,
Viewport::DEBUG_DRAW_OVERDRAW,
Viewport::DEBUG_DRAW_UNSHADED,
Viewport::DEBUG_DRAW_LIGHTING,
Viewport::DEBUG_DRAW_WIREFRAME,
Viewport::DEBUG_DRAW_SHADOW_ATLAS,
Viewport::DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
Viewport::DEBUG_DRAW_GI_PROBE_LIGHTING,
Viewport::DEBUG_DRAW_GI_PROBE_ALBEDO
};
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS), false);
} break;
case VIEW_DISPLAY_WIREFRAME: {
int idx = 0;
viewport->set_debug_draw(Viewport::DEBUG_DRAW_WIREFRAME);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME), true);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS), false);
while (display_options[idx] != VIEW_MAX) {
} break;
case VIEW_DISPLAY_OVERDRAW: {
viewport->set_debug_draw(Viewport::DEBUG_DRAW_OVERDRAW);
VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW), true);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS), false);
} break;
case VIEW_DISPLAY_SHADELESS: {
viewport->set_debug_draw(Viewport::DEBUG_DRAW_UNSHADED);
VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS), true);
int id = display_options[idx];
int item_idx = view_menu->get_popup()->get_item_index(id);
if (item_idx != -1) {
view_menu->get_popup()->set_item_checked(item_idx, id == p_option);
}
item_idx = display_submenu->get_item_index(id);
if (item_idx != -1) {
display_submenu->set_item_checked(item_idx, id == p_option);
}
if (id == p_option) {
viewport->set_debug_draw(debug_draw_modes[idx]);
}
idx++;
}
} break;
}
}
@ -3590,6 +3607,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
vbox->add_child(view_menu);
view_menu->set_h_size_flags(0);
display_submenu = memnew(PopupMenu);
view_menu->get_popup()->add_child(display_submenu);
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP);
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM);
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT);
@ -3608,6 +3628,13 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW);
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
display_submenu->add_radio_check_item(TTR("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS);
display_submenu->add_radio_check_item(TTR("Directional Shadow"), VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS);
display_submenu->add_separator();
display_submenu->add_radio_check_item(TTR("GIProbe Lighting"), VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING);
display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO);
display_submenu->set_name("display_advanced");
view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced");
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("View Environment")), VIEW_ENVIRONMENT);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("View Gizmos")), VIEW_GIZMOS);
@ -3630,7 +3657,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_transform_with_view"), VIEW_ALIGN_TRANSFORM_WITH_VIEW);
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_rotation_with_view"), VIEW_ALIGN_ROTATION_WITH_VIEW);
view_menu->get_popup()->connect("id_pressed", this, "_menu_option");
display_submenu->connect("id_pressed", this, "_menu_option");
view_menu->set_disable_shortcuts(true);
if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
@ -5587,7 +5614,7 @@ void SpatialEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<CPUParticlesGizmoPlugin>(memnew(CPUParticlesGizmoPlugin)));
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
add_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin)));
// add_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionShapeSpatialGizmoPlugin>(memnew(CollisionShapeSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionPolygonSpatialGizmoPlugin>(memnew(CollisionPolygonSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<NavigationMeshSpatialGizmoPlugin>(memnew(NavigationMeshSpatialGizmoPlugin)));

View file

@ -167,8 +167,14 @@ class SpatialEditorViewport : public Control {
VIEW_DISPLAY_WIREFRAME,
VIEW_DISPLAY_OVERDRAW,
VIEW_DISPLAY_SHADELESS,
VIEW_DISPLAY_LIGHTING,
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO,
VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING,
VIEW_LOCK_ROTATION,
VIEW_CINEMATIC_PREVIEW
VIEW_CINEMATIC_PREVIEW,
VIEW_MAX
};
public:
@ -205,6 +211,7 @@ private:
ViewportContainer *viewport_container;
MenuButton *view_menu;
PopupMenu *display_submenu;
Control *surface;
Viewport *viewport;

View file

@ -2904,7 +2904,7 @@ void GIProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
}
////
#if 0
BakedIndirectLightGizmoPlugin::BakedIndirectLightGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/baked_indirect_light", Color(0.5, 0.6, 1));
@ -3033,7 +3033,7 @@ void BakedIndirectLightGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
p_gizmo->add_unscaled_billboard(icon, 0.05);
p_gizmo->add_handles(handles, get_material("handles"));
}
#endif
////
CollisionShapeSpatialGizmoPlugin::CollisionShapeSpatialGizmoPlugin() {

View file

@ -303,6 +303,7 @@ public:
GIProbeGizmoPlugin();
};
#if 0
class BakedIndirectLightGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(BakedIndirectLightGizmoPlugin, EditorSpatialGizmoPlugin);
@ -320,7 +321,7 @@ public:
BakedIndirectLightGizmoPlugin();
};
#endif
class CollisionShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(CollisionShapeSpatialGizmoPlugin, EditorSpatialGizmoPlugin);

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#if 0
#include "baked_lightmap.h"
#include "core/io/config_file.h"
#include "core/io/resource_saver.h"
@ -368,7 +369,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
Ref<BakedLightmapData> new_light_data;
new_light_data.instance();
VoxelLightBaker baker;
Voxelizer baker;
int bake_subdiv;
int capture_subdiv;
@ -413,7 +414,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
}
pmc = 0;
baker.begin_bake_light(VoxelLightBaker::BakeQuality(bake_quality), VoxelLightBaker::BakeMode(bake_mode), propagation, energy);
baker.begin_bake_light(Voxelizer::BakeQuality(bake_quality), Voxelizer::BakeMode(bake_mode), propagation, energy);
for (List<PlotLight>::Element *E = light_list.front(); E; E = E->next()) {
@ -465,7 +466,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
used_mesh_names.insert(mesh_name);
pmc++;
VoxelLightBaker::LightMapData lm;
Voxelizer::LightMapData lm;
Error err;
if (bake_step_function) {
@ -626,7 +627,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
if (p_create_visual_debug) {
MultiMeshInstance *mmi = memnew(MultiMeshInstance);
mmi->set_multimesh(baker.create_debug_multimesh(VoxelLightBaker::DEBUG_LIGHT));
mmi->set_multimesh(baker.create_debug_multimesh(Voxelizer::DEBUG_LIGHT));
add_child(mmi);
#ifdef TOOLS_ENABLED
if (get_tree()->get_edited_scene_root() == this) {
@ -860,3 +861,4 @@ BakedLightmap::BakedLightmap() {
image_path = ".";
set_disable_scale(true);
}
#endif

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#if 0
#ifndef BAKED_INDIRECT_LIGHT_H
#define BAKED_INDIRECT_LIGHT_H
@ -211,4 +212,5 @@ VARIANT_ENUM_CAST(BakedLightmap::BakeQuality);
VARIANT_ENUM_CAST(BakedLightmap::BakeMode);
VARIANT_ENUM_CAST(BakedLightmap::BakeError);
#endif
#endif // BAKED_INDIRECT_LIGHT_H

View file

@ -32,116 +32,135 @@
#include "core/os/os.h"
#include "core/method_bind_ext.gen.inc"
#include "mesh_instance.h"
#include "voxel_light_baker.h"
#include "voxelizer.h"
void GIProbeData::set_bounds(const AABB &p_bounds) {
void GIProbeData::_set_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bounds"));
ERR_FAIL_COND(!p_data.has("octree_size"));
ERR_FAIL_COND(!p_data.has("octree_cells"));
ERR_FAIL_COND(!p_data.has("octree_data"));
ERR_FAIL_COND(!p_data.has("level_counts"));
ERR_FAIL_COND(!p_data.has("to_cell_xform"));
VS::get_singleton()->gi_probe_set_bounds(probe, p_bounds);
AABB bounds = p_data["bounds"];
Vector3 octree_size = p_data["octree_size"];
PoolVector<uint8_t> octree_cells = p_data["octree_cells"];
PoolVector<uint8_t> octree_data = p_data["octree_data"];
PoolVector<int> octree_levels = p_data["level_counts"];
Transform to_cell_xform = p_data["to_cell_xform"];
allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_levels);
}
Dictionary GIProbeData::_get_data() const {
Dictionary d;
d["bounds"] = get_bounds();
d["octree_size"] = get_octree_size();
d["octree_cells"] = get_octree_cells();
d["octree_data"] = get_data_cells();
d["level_counts"] = get_level_counts();
d["to_cell_xform"] = get_to_cell_xform();
return d;
}
void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) {
VS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_level_counts);
bounds = p_aabb;
to_cell_xform = p_to_cell_xform;
octree_size = p_octree_size;
}
AABB GIProbeData::get_bounds() const {
return VS::get_singleton()->gi_probe_get_bounds(probe);
return bounds;
}
void GIProbeData::set_cell_size(float p_size) {
VS::get_singleton()->gi_probe_set_cell_size(probe, p_size);
Vector3 GIProbeData::get_octree_size() const {
return octree_size;
}
float GIProbeData::get_cell_size() const {
return VS::get_singleton()->gi_probe_get_cell_size(probe);
PoolVector<uint8_t> GIProbeData::get_octree_cells() const {
return VS::get_singleton()->gi_probe_get_octree_cells(probe);
}
void GIProbeData::set_to_cell_xform(const Transform &p_xform) {
VS::get_singleton()->gi_probe_set_to_cell_xform(probe, p_xform);
PoolVector<uint8_t> GIProbeData::get_data_cells() const {
return VS::get_singleton()->gi_probe_get_data_cells(probe);
}
PoolVector<int> GIProbeData::get_level_counts() const {
return VS::get_singleton()->gi_probe_get_level_counts(probe);
}
Transform GIProbeData::get_to_cell_xform() const {
return VS::get_singleton()->gi_probe_get_to_cell_xform(probe);
return to_cell_xform;
}
void GIProbeData::set_dynamic_data(const PoolVector<int> &p_data) {
VS::get_singleton()->gi_probe_set_dynamic_data(probe, p_data);
}
PoolVector<int> GIProbeData::get_dynamic_data() const {
return VS::get_singleton()->gi_probe_get_dynamic_data(probe);
}
void GIProbeData::set_dynamic_range(int p_range) {
void GIProbeData::set_dynamic_range(float p_range) {
VS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range);
dynamic_range = p_range;
}
void GIProbeData::set_energy(float p_range) {
VS::get_singleton()->gi_probe_set_energy(probe, p_range);
float GIProbeData::get_dynamic_range() const {
return dynamic_range;
}
float GIProbeData::get_energy() const {
return VS::get_singleton()->gi_probe_get_energy(probe);
}
void GIProbeData::set_bias(float p_range) {
VS::get_singleton()->gi_probe_set_bias(probe, p_range);
}
float GIProbeData::get_bias() const {
return VS::get_singleton()->gi_probe_get_bias(probe);
}
void GIProbeData::set_normal_bias(float p_range) {
VS::get_singleton()->gi_probe_set_normal_bias(probe, p_range);
}
float GIProbeData::get_normal_bias() const {
return VS::get_singleton()->gi_probe_get_normal_bias(probe);
}
void GIProbeData::set_propagation(float p_range) {
VS::get_singleton()->gi_probe_set_propagation(probe, p_range);
void GIProbeData::set_propagation(float p_propagation) {
VS::get_singleton()->gi_probe_set_propagation(probe, p_propagation);
propagation = p_propagation;
}
float GIProbeData::get_propagation() const {
return propagation;
}
return VS::get_singleton()->gi_probe_get_propagation(probe);
void GIProbeData::set_anisotropy_strength(float p_anisotropy_strength) {
VS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength);
anisotropy_strength = p_anisotropy_strength;
}
float GIProbeData::get_anisotropy_strength() const {
return anisotropy_strength;
}
void GIProbeData::set_energy(float p_energy) {
VS::get_singleton()->gi_probe_set_energy(probe, p_energy);
energy = p_energy;
}
float GIProbeData::get_energy() const {
return energy;
}
void GIProbeData::set_bias(float p_bias) {
VS::get_singleton()->gi_probe_set_bias(probe, p_bias);
bias = p_bias;
}
float GIProbeData::get_bias() const {
return bias;
}
void GIProbeData::set_normal_bias(float p_normal_bias) {
VS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias);
normal_bias = p_normal_bias;
}
float GIProbeData::get_normal_bias() const {
return normal_bias;
}
void GIProbeData::set_interior(bool p_enable) {
VS::get_singleton()->gi_probe_set_interior(probe, p_enable);
interior = p_enable;
}
bool GIProbeData::is_interior() const {
return VS::get_singleton()->gi_probe_is_interior(probe);
return interior;
}
bool GIProbeData::is_compressed() const {
return VS::get_singleton()->gi_probe_is_compressed(probe);
void GIProbeData::set_use_two_bounces(bool p_enable) {
VS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable);
use_two_bounces = p_enable;
}
void GIProbeData::set_compress(bool p_enable) {
VS::get_singleton()->gi_probe_set_compress(probe, p_enable);
}
int GIProbeData::get_dynamic_range() const {
return VS::get_singleton()->gi_probe_get_dynamic_range(probe);
bool GIProbeData::is_using_two_bounces() const {
return use_two_bounces;
}
RID GIProbeData::get_rid() const {
@ -149,19 +168,25 @@ RID GIProbeData::get_rid() const {
return probe;
}
void GIProbeData::_validate_property(PropertyInfo &property) const {
if (property.name == "anisotropy_strength") {
bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/quality/gi_probes/anisotropic");
if (!anisotropy_enabled) {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
}
void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &GIProbeData::set_bounds);
ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "octree_data", "octree_level_count"), &GIProbeData::allocate);
ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds);
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &GIProbeData::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &GIProbeData::get_cell_size);
ClassDB::bind_method(D_METHOD("set_to_cell_xform", "to_cell_xform"), &GIProbeData::set_to_cell_xform);
ClassDB::bind_method(D_METHOD("get_octree_size"), &GIProbeData::get_octree_size);
ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform);
ClassDB::bind_method(D_METHOD("set_dynamic_data", "dynamic_data"), &GIProbeData::set_dynamic_data);
ClassDB::bind_method(D_METHOD("get_dynamic_data"), &GIProbeData::get_dynamic_data);
ClassDB::bind_method(D_METHOD("get_octree_cells"), &GIProbeData::get_octree_cells);
ClassDB::bind_method(D_METHOD("get_data_cells"), &GIProbeData::get_data_cells);
ClassDB::bind_method(D_METHOD("get_level_counts"), &GIProbeData::get_level_counts);
ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range);
ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range);
@ -178,28 +203,40 @@ void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation);
ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &GIProbeData::set_anisotropy_strength);
ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &GIProbeData::get_anisotropy_strength);
ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior);
ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress);
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed);
ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &GIProbeData::set_use_two_bounces);
ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &GIProbeData::is_using_two_bounces);
ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform");
ClassDB::bind_method(D_METHOD("_set_data", "data"), &GIProbeData::_set_data);
ClassDB::bind_method(D_METHOD("_get_data"), &GIProbeData::_get_data);
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "dynamic_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_data", "get_dynamic_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed");
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
}
GIProbeData::GIProbeData() {
dynamic_range = 4;
energy = 1.0;
bias = 1.5;
normal_bias = 0.0;
propagation = 0.7;
anisotropy_strength = 0.5;
interior = false;
probe = VS::get_singleton()->gi_probe_create();
}
@ -251,89 +288,6 @@ Vector3 GIProbe::get_extents() const {
return extents;
}
void GIProbe::set_dynamic_range(int p_dynamic_range) {
dynamic_range = p_dynamic_range;
}
int GIProbe::get_dynamic_range() const {
return dynamic_range;
}
void GIProbe::set_energy(float p_energy) {
energy = p_energy;
if (probe_data.is_valid()) {
probe_data->set_energy(energy);
}
}
float GIProbe::get_energy() const {
return energy;
}
void GIProbe::set_bias(float p_bias) {
bias = p_bias;
if (probe_data.is_valid()) {
probe_data->set_bias(bias);
}
}
float GIProbe::get_bias() const {
return bias;
}
void GIProbe::set_normal_bias(float p_normal_bias) {
normal_bias = p_normal_bias;
if (probe_data.is_valid()) {
probe_data->set_normal_bias(normal_bias);
}
}
float GIProbe::get_normal_bias() const {
return normal_bias;
}
void GIProbe::set_propagation(float p_propagation) {
propagation = p_propagation;
if (probe_data.is_valid()) {
probe_data->set_propagation(propagation);
}
}
float GIProbe::get_propagation() const {
return propagation;
}
void GIProbe::set_interior(bool p_enable) {
interior = p_enable;
if (probe_data.is_valid()) {
probe_data->set_interior(p_enable);
}
}
bool GIProbe::is_interior() const {
return interior;
}
void GIProbe::set_compress(bool p_enable) {
compress = p_enable;
if (probe_data.is_valid()) {
probe_data->set_compress(p_enable);
}
}
bool GIProbe::is_compressed() const {
return compress;
}
void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
@ -397,9 +351,9 @@ GIProbe::BakeEndFunc GIProbe::bake_end_function = NULL;
void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
static const int subdiv_value[SUBDIV_MAX] = { 7, 8, 9, 10 };
static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
VoxelLightBaker baker;
Voxelizer baker;
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
@ -431,8 +385,6 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
//create the data for visual server
PoolVector<int> data = baker.create_gi_probe_data();
if (p_create_visual_debug) {
MultiMeshInstance *mmi = memnew(MultiMeshInstance);
mmi->set_multimesh(baker.create_debug_multimesh());
@ -454,17 +406,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
if (probe_data.is_null())
probe_data.instance();
probe_data->set_bounds(AABB(-extents, extents * 2.0));
probe_data->set_cell_size(baker.get_cell_size());
probe_data->set_dynamic_data(data);
probe_data->set_dynamic_range(dynamic_range);
probe_data->set_energy(energy);
probe_data->set_bias(bias);
probe_data->set_normal_bias(normal_bias);
probe_data->set_propagation(propagation);
probe_data->set_interior(interior);
probe_data->set_compress(compress);
probe_data->set_to_cell_xform(baker.get_to_cell_space_xform());
probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), baker.get_giprobe_level_cell_count());
set_probe_data(probe_data);
}
@ -508,40 +450,12 @@ void GIProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents);
ClassDB::bind_method(D_METHOD("set_dynamic_range", "max"), &GIProbe::set_dynamic_range);
ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbe::get_dynamic_range);
ClassDB::bind_method(D_METHOD("set_energy", "max"), &GIProbe::set_energy);
ClassDB::bind_method(D_METHOD("get_energy"), &GIProbe::get_energy);
ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias);
ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias);
ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias);
ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias);
ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation);
ClassDB::bind_method(D_METHOD("set_interior", "enable"), &GIProbe::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbe::is_interior);
ClassDB::bind_method(D_METHOD("set_compress", "enable"), &GIProbe::set_compress);
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbe::is_compressed);
ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "1,16,1"), "set_dynamic_range", "get_dynamic_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);
@ -554,14 +468,7 @@ void GIProbe::_bind_methods() {
GIProbe::GIProbe() {
subdiv = SUBDIV_128;
dynamic_range = 4;
energy = 1.0;
bias = 1.5;
normal_bias = 0.0;
propagation = 0.7;
extents = Vector3(10, 10, 10);
interior = false;
compress = false;
gi_probe = VS::get_singleton()->gi_probe_create();
set_disable_scale(true);

View file

@ -40,42 +40,58 @@ class GIProbeData : public Resource {
RID probe;
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
Transform to_cell_xform;
AABB bounds;
Vector3 octree_size;
float dynamic_range;
float energy;
float bias;
float normal_bias;
float propagation;
float anisotropy_strength;
bool interior;
bool use_two_bounces;
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
public:
void set_bounds(const AABB &p_bounds);
void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts);
AABB get_bounds() const;
void set_cell_size(float p_size);
float get_cell_size() const;
void set_to_cell_xform(const Transform &p_xform);
Vector3 get_octree_size() const;
PoolVector<uint8_t> get_octree_cells() const;
PoolVector<uint8_t> get_data_cells() const;
PoolVector<int> get_level_counts() const;
Transform get_to_cell_xform() const;
void set_dynamic_data(const PoolVector<int> &p_data);
PoolVector<int> get_dynamic_data() const;
void set_dynamic_range(float p_range);
float get_dynamic_range() const;
void set_dynamic_range(int p_range);
int get_dynamic_range() const;
void set_propagation(float p_range);
void set_propagation(float p_propagation);
float get_propagation() const;
void set_energy(float p_range);
void set_anisotropy_strength(float p_anisotropy_strength);
float get_anisotropy_strength() const;
void set_energy(float p_energy);
float get_energy() const;
void set_bias(float p_range);
void set_bias(float p_bias);
float get_bias() const;
void set_normal_bias(float p_range);
void set_normal_bias(float p_normal_bias);
float get_normal_bias() const;
void set_interior(bool p_enable);
bool is_interior() const;
void set_compress(bool p_enable);
bool is_compressed() const;
void set_use_two_bounces(bool p_enable);
bool is_using_two_bounces() const;
virtual RID get_rid() const;
@ -107,13 +123,6 @@ private:
Subdiv subdiv;
Vector3 extents;
int dynamic_range;
float energy;
float bias;
float normal_bias;
float propagation;
bool interior;
bool compress;
struct PlotMesh {
Ref<Material> override_material;
@ -142,27 +151,6 @@ public:
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
void set_dynamic_range(int p_dynamic_range);
int get_dynamic_range() const;
void set_energy(float p_energy);
float get_energy() const;
void set_bias(float p_bias);
float get_bias() const;
void set_normal_bias(float p_normal_bias);
float get_normal_bias() const;
void set_propagation(float p_propagation);
float get_propagation() const;
void set_interior(bool p_enable);
bool is_interior() const;
void set_compress(bool p_enable);
bool is_compressed() const;
void bake(Node *p_from_node = NULL, bool p_create_visual_debug = false);
virtual AABB get_aabb() const;

File diff suppressed because it is too large Load diff

1108
scene/3d/voxelizer.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*************************************************************************/
/* voxel_light_baker.h */
/* voxelizer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -31,27 +31,11 @@
#ifndef VOXEL_LIGHT_BAKER_H
#define VOXEL_LIGHT_BAKER_H
#include "core/math/vector3i.h"
#include "scene/3d/mesh_instance.h"
#include "scene/resources/multimesh.h"
class VoxelLightBaker {
public:
enum DebugMode {
DEBUG_ALBEDO,
DEBUG_LIGHT
};
enum BakeQuality {
BAKE_QUALITY_LOW,
BAKE_QUALITY_MEDIUM,
BAKE_QUALITY_HIGH
};
enum BakeMode {
BAKE_MODE_CONE_TRACE,
BAKE_MODE_RAY_TRACE,
};
class Voxelizer {
private:
enum {
CHILD_EMPTY = 0xFFFFFFFF
@ -66,7 +50,10 @@ private:
float normal[3];
uint32_t used_sides;
float alpha; //used for upsampling
int level;
uint16_t x;
uint16_t y;
uint16_t z;
uint16_t level;
Cell() {
for (int i = 0; i < 8; i++) {
@ -80,6 +67,7 @@ private:
}
alpha = 0;
used_sides = 0;
x = y = z = 0;
level = 0;
}
};
@ -87,27 +75,24 @@ private:
Vector<Cell> bake_cells;
int cell_subdiv;
struct Light {
int x, y, z;
float accum[6][3]; //rgb anisotropic
float direct_accum[6][3]; //for direct bake
int next_leaf;
Light() {
x = y = z = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 3; j++) {
accum[i][j] = 0;
direct_accum[i][j] = 0;
}
}
next_leaf = 0;
struct CellSort {
union {
struct {
uint64_t z : 16;
uint64_t y : 16;
uint64_t x : 16;
uint64_t level : 16;
};
uint64_t key;
};
int32_t index;
_FORCE_INLINE_ bool operator<(const CellSort &p_cell_sort) const {
return key < p_cell_sort.key;
}
};
int first_leaf;
Vector<Light> bake_light;
struct MaterialCache {
//128x128 textures
Vector<Color> albedo;
@ -115,9 +100,6 @@ private:
};
Map<Ref<Material>, MaterialCache> material_cache;
int leaf_voxel_count;
bool direct_lights_baked;
AABB original_bounds;
AABB po2_bounds;
int axis_cell_size[3];
@ -128,64 +110,36 @@ private:
int bake_texture_size;
float cell_size;
float propagation;
float energy;
BakeQuality bake_quality;
BakeMode bake_mode;
int max_original_cells;
void _init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent);
int leaf_voxel_count;
Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add);
MaterialCache _get_material_cache(Ref<Material> p_material);
void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb);
void _fixup_plot(int p_idx, int p_level);
void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, DebugMode p_mode);
void _check_init_light();
void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx);
uint32_t _find_cell_at_pos(const Cell *cells, int x, int y, int z);
struct LightMap {
Vector3 light;
Vector3 pos;
Vector3 normal;
};
void _plot_triangle(Vector2 *vertices, Vector3 *positions, Vector3 *normals, LightMap *pixels, int width, int height);
_FORCE_INLINE_ void _sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha);
_FORCE_INLINE_ Vector3 _voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture);
_FORCE_INLINE_ Vector3 _compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
_FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
void _lightmap_bake_point(uint32_t p_x, LightMap *p_line);
bool sorted;
void _sort();
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
void plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
void begin_bake_light(BakeQuality p_quality = BAKE_QUALITY_MEDIUM, BakeMode p_bake_mode = BAKE_MODE_CONE_TRACE, float p_propagation = 0.85, float p_energy = 1);
void plot_light_directional(const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, bool p_direct);
void plot_light_omni(const Vector3 &p_pos, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, bool p_direct);
void plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axis, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, float p_spot_angle, float p_spot_attenuation, bool p_direct);
void end_bake();
struct LightMapData {
int width;
int height;
PoolVector<float> light;
};
int get_gi_probe_octree_depth() const;
Vector3i get_giprobe_octree_size() const;
int get_giprobe_cell_count() const;
PoolVector<uint8_t> get_giprobe_octree_cells() const;
PoolVector<uint8_t> get_giprobe_data_cells() const;
PoolVector<int> get_giprobe_level_cell_count() const;
Error make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, float default_texels_per_unit, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float) = NULL, void *p_bake_time_ud = NULL);
Ref<MultiMesh> create_debug_multimesh();
PoolVector<int> create_gi_probe_data();
Ref<MultiMesh> create_debug_multimesh(DebugMode p_mode = DEBUG_ALBEDO);
PoolVector<uint8_t> create_capture_octree(int p_subdiv);
float get_cell_size() const;
Transform get_to_cell_space_xform() const;
VoxelLightBaker();
Voxelizer();
};
#endif // VOXEL_LIGHT_BAKER_H

View file

@ -129,8 +129,14 @@ public:
enum DebugDraw {
DEBUG_DRAW_DISABLED,
DEBUG_DRAW_UNSHADED,
DEBUG_DRAW_LIGHTING,
DEBUG_DRAW_OVERDRAW,
DEBUG_DRAW_WIREFRAME,
DEBUG_DRAW_GI_PROBE_ALBEDO,
DEBUG_DRAW_GI_PROBE_LIGHTING,
DEBUG_DRAW_SHADOW_ATLAS,
DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
};
enum ClearMode {

View file

@ -419,8 +419,8 @@ void register_scene_types() {
ClassDB::register_class<ReflectionProbe>();
ClassDB::register_class<GIProbe>();
ClassDB::register_class<GIProbeData>();
ClassDB::register_class<BakedLightmap>();
ClassDB::register_class<BakedLightmapData>();
//ClassDB::register_class<BakedLightmap>();
//ClassDB::register_class<BakedLightmapData>();
ClassDB::register_class<Particles>();
ClassDB::register_class<CPUParticles>();
ClassDB::register_class<Position3D>();

View file

@ -904,6 +904,8 @@ Array ArrayMesh::_get_surfaces() const {
ret.push_back(data);
}
print_line("Saving surfaces: " + itos(ret.size()));
return ret;
}
@ -983,7 +985,15 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
if (d.has("2d")) {
_2d = d["2d"];
}
/*
print_line("format: " + itos(surface.format));
print_line("aabb: " + surface.aabb);
print_line("array size: " + itos(surface.vertex_data.size()));
print_line("vertex count: " + itos(surface.vertex_count));
print_line("index size: " + itos(surface.index_data.size()));
print_line("index count: " + itos(surface.index_count));
print_line("primitive: " + itos(surface.primitive));
*/
surface_data.push_back(surface);
surface_materials.push_back(material);
surface_names.push_back(name);
@ -999,6 +1009,7 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
} else {
// if mesh does not exist (first time this is loaded, most likely),
// we can create it with a single call, which is a lot more efficient and thread friendly
print_line("create mesh from surfaces: " + itos(surface_data.size()));
mesh = VS::get_singleton()->mesh_create_from_surfaces(surface_data);
VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)blend_shape_mode);
}
@ -1144,6 +1155,14 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &
Error err = VS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags);
ERR_FAIL_COND(err != OK);
/* print_line("format: " + itos(surface.format));
print_line("aabb: " + surface.aabb);
print_line("array size: " + itos(surface.vertex_data.size()));
print_line("vertex count: " + itos(surface.vertex_count));
print_line("index size: " + itos(surface.index_data.size()));
print_line("index count: " + itos(surface.index_count));
print_line("primitive: " + itos(surface.primitive));
*/
add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shapes, surface.bone_aabbs, surface.lods);
}
@ -1570,8 +1589,8 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_surfaces", "surfaces"), &ArrayMesh::_set_surfaces);
ClassDB::bind_method(D_METHOD("_get_surfaces"), &ArrayMesh::_get_surfaces);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative", PROPERTY_USAGE_NOEDITOR), "set_blend_shape_mode", "get_blend_shape_mode");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_surfaces", "_get_surfaces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
BIND_CONSTANT(NO_INDEX_ARRAY);

View file

@ -1281,7 +1281,7 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
ria->res_path = ria->local_path;
//ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
String r = ria->recognize(f);
return r;
return ClassDB::get_compatibility_remapped_class(r);
}
void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {

View file

@ -230,12 +230,13 @@ public:
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
virtual RID gi_probe_instance_create() = 0;
virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) = 0;
virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
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 bool gi_probe_needs_update(RID p_probe) const = 0;
virtual void gi_probe_update(RID p_probe, const Vector<RID> &p_light_instances) = 0;
virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_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_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;
@ -481,51 +482,41 @@ public:
virtual RID gi_probe_create() = 0;
virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) = 0;
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
virtual PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0;
virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0;
virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) = 0;
virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const = 0;
virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0;
virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0;
virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0;
virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_energy(RID p_probe) const = 0;
virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;
virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_bias(RID p_probe) const = 0;
virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0;
virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_normal_bias(RID p_probe) const = 0;
virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0;
virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0;
virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_propagation(RID p_probe) const = 0;
virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0;
virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0;
virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0;
virtual bool gi_probe_is_interior(RID p_probe) const = 0;
virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0;
virtual bool gi_probe_is_compressed(RID p_probe) const = 0;
virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0;
virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0;
virtual uint32_t gi_probe_get_version(RID p_probe) = 0;
enum GIProbeCompression {
GI_PROBE_UNCOMPRESSED,
GI_PROBE_S3TC,
GI_PROBE_ETC2
};
virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const = 0;
virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) = 0;
virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) = 0;
/* LIGHTMAP CAPTURE */
struct LightmapCaptureOctree {

View file

@ -1331,7 +1331,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
if (p_screen_uniform_set.is_valid()) {
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 3);
@ -1637,7 +1637,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
Vector<Color> cc;
cc.push_back(Color(p_far, p_far, p_far, 1.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 1));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 1));
CameraMatrix projection;
{

View file

@ -46,7 +46,7 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_frame
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::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, 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);
@ -67,7 +67,7 @@ void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_frameb
blur.push_constant.section[3] = p_region.size.height;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
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);
@ -93,7 +93,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuff
blur.push_constant.pixel_size[1] = p_pixel_size.y;
//HORIZONTAL
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
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);
@ -105,7 +105,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuff
RD::get_singleton()->draw_list_end();
//VERTICAL
draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].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_rd_texture_half), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@ -127,7 +127,7 @@ void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_sour
roughness.push_constant.use_direct_write = p_roughness == 0.0;
//RUN
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.pipelines[p_source_is_panorama ? CUBEMAP_ROUGHNESS_SOURCE_PANORAMA : CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
@ -171,7 +171,7 @@ void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_frameb
blur.push_constant.pixel_size[0] = p_pixel_size.x;
blur.push_constant.pixel_size[1] = p_pixel_size.y;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@ -188,7 +188,7 @@ void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest
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::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.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);
@ -222,7 +222,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);

File diff suppressed because it is too large Load diff

View file

@ -188,6 +188,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
//for rendering, may be MSAAd
RID color;
RID depth;
RID depth_fb;
RID color_fb;
RID color_only_fb;
int width, height;
@ -204,7 +205,9 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
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, RID p_shadow_atlas, RID p_reflection_atlas);
RID render_pass_uniform_set;
void _update_render_base_uniform_set();
void _setup_render_pass_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 */
@ -247,6 +250,20 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
float shadow_matrices[4][16];
};
struct GIProbeData {
float xform[16];
float bounds[3];
float dynamic_range;
float bias;
float normal_bias;
uint32_t blend_ambient;
uint32_t texture_slot;
float anisotropy_strength;
uint32_t pad[3];
};
enum {
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
@ -315,6 +332,11 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
GIProbeData *gi_probes;
uint32_t max_gi_probes;
RID gi_probe_buffer;
uint32_t max_gi_probe_probes_per_instance;
LightData *lights;
uint32_t max_lights;
RID light_buffer;
@ -498,6 +520,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
void _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);
@ -508,13 +531,15 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
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);
VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
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_gi_probe_cull_result, int p_gi_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_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 set_time(double p_time);
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw);
virtual bool free(RID p_rid);

View file

@ -619,6 +619,10 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
}
}
Vector<RID> fb;
fb.push_back(atlas->depth_buffer);
atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
}
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
@ -700,6 +704,16 @@ RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance,
return atlas->reflections[rpi->atlas_index].fbs[p_index];
}
RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
ERR_FAIL_INDEX_V(p_index, 6, RID());
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->depth_fb;
}
///////////////////////////////////////////////////////////
RID RasterizerSceneRD::shadow_atlas_create() {
@ -1192,6 +1206,454 @@ RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p
return &shadow_maps[p_size];
}
/////////////////////////////////
RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
//find a free slot
int index = -1;
for (int i = 0; i < gi_probe_slots.size(); i++) {
if (gi_probe_slots[i] == RID()) {
index = i;
break;
}
}
ERR_FAIL_COND_V(index == -1, RID());
GIProbeInstance gi_probe;
gi_probe.slot = index;
gi_probe.probe = p_base;
RID rid = gi_probe_instance_owner.make_rid(gi_probe);
gi_probe_slots.write[index] = rid;
return rid;
}
void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->transform = p_xform;
}
bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gi_probe, false);
//return true;
return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
}
void RasterizerSceneRD::gi_probe_update(RID p_probe, const Vector<RID> &p_light_instances) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe);
// (RE)CREATE IF NEEDED
if (gi_probe->last_probe_data_version != data_version) {
//need to re-create everything
if (gi_probe->texture.is_valid()) {
RD::get_singleton()->free(gi_probe->texture);
if (gi_probe_use_anisotropy) {
RD::get_singleton()->free(gi_probe->anisotropy[0]);
RD::get_singleton()->free(gi_probe->anisotropy[1]);
}
RD::get_singleton()->free(gi_probe->write_buffer);
gi_probe->mipmaps.clear();
}
Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
if (octree_size != Vector3i()) {
//can create a 3D texture
PoolVector<int> levels = storage->gi_probe_get_level_counts(gi_probe->probe);
for (int i = 0; i < levels.size(); i++) {
print_line("level " + itos(i) + ": " + itos(levels[i]));
}
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tf.width = octree_size.x;
tf.height = octree_size.y;
tf.depth = octree_size.z;
tf.type = RD::TEXTURE_TYPE_3D;
tf.mipmaps = levels.size();
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
gi_probe->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
if (gi_probe_use_anisotropy) {
tf.format = RD::DATA_FORMAT_R5G6B5_UNORM_PACK16;
tf.shareable_formats.push_back(RD::DATA_FORMAT_R5G6B5_UNORM_PACK16);
tf.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT);
gi_probe->anisotropy[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
gi_probe->anisotropy[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
}
{
int total_elements = 0;
for (int i = 0; i < levels.size(); i++) {
total_elements += levels[i];
}
if (gi_probe_use_anisotropy) {
total_elements *= 6;
}
gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16);
}
for (int i = 0; i < levels.size(); i++) {
GIProbeInstance::Mipmap mipmap;
mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D);
if (gi_probe_use_anisotropy) {
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R16_UINT;
mipmap.anisotropy[0] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[0], 0, i, RD::TEXTURE_SLICE_3D);
mipmap.anisotropy[1] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[1], 0, i, RD::TEXTURE_SLICE_3D);
}
mipmap.level = levels.size() - i - 1;
mipmap.cell_offset = 0;
for (uint32_t j = 0; j < mipmap.level; j++) {
mipmap.cell_offset += levels[j];
}
mipmap.cell_count = levels[mipmap.level];
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 4;
u.ids.push_back(gi_probe->write_buffer);
uniforms.push_back(u);
}
{
Vector<RD::Uniform> copy_uniforms = uniforms;
if (i == 0) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
u.ids.push_back(gi_probe_lights_uniform);
copy_uniforms.push_back(u);
}
mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0);
copy_uniforms = uniforms; //restore
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
u.ids.push_back(gi_probe->texture);
copy_uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 6;
u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
copy_uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 7;
u.ids.push_back(gi_probe->anisotropy[0]);
copy_uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 8;
u.ids.push_back(gi_probe->anisotropy[1]);
copy_uniforms.push_back(u);
}
}
mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
} else {
mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0);
}
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
u.ids.push_back(mipmap.texture);
uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 6;
u.ids.push_back(mipmap.anisotropy[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 7;
u.ids.push_back(mipmap.anisotropy[1]);
uniforms.push_back(u);
}
}
mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0);
gi_probe->mipmaps.push_back(mipmap);
}
}
gi_probe->last_probe_data_version = data_version;
}
// UDPDATE TIME
uint32_t light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
{
Transform to_cell = storage->gi_probe_get_to_cell_xform(gi_probe->probe);
Transform to_probe_xform = (gi_probe->transform * to_cell.affine_inverse()).affine_inverse();
//update lights
for (uint32_t i = 0; i < light_count; i++) {
GIProbeLight &l = gi_probe_lights[i];
RID light_instance = p_light_instances[i];
RID light = light_instance_get_base_light(light_instance);
l.type = storage->light_get_type(light);
l.attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_ATTENUATION);
l.energy = storage->light_get_param(light, VS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, VS::LIGHT_PARAM_INDIRECT_ENERGY);
l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, VS::LIGHT_PARAM_RANGE), 0, 0)).length();
Color color = storage->light_get_color(light).to_linear();
l.color[0] = color.r;
l.color[1] = color.g;
l.color[2] = color.b;
l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ANGLE));
l.spot_attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform xform = light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
l.position[0] = pos.x;
l.position[1] = pos.y;
l.position[2] = pos.z;
l.direction[0] = dir.x;
l.direction[1] = dir.y;
l.direction[2] = dir.z;
l.has_shadow = storage->light_has_shadow(light);
}
RD::get_singleton()->buffer_update(gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi_probe_lights, true);
}
// PROCESS MIPMAPS
if (gi_probe->mipmaps.size()) {
//can update mipmaps
Vector3i probe_size = storage->gi_probe_get_octree_size(gi_probe->probe);
GIProbePushConstant push_constant;
push_constant.limits[0] = probe_size.x;
push_constant.limits[1] = probe_size.y;
push_constant.limits[2] = probe_size.z;
push_constant.stack_size = gi_probe->mipmaps.size();
push_constant.emission_scale = 1.0;
push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe);
push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
push_constant.light_count = light_count;
push_constant.aniso_strength = storage->gi_probe_get_anisotropy_strength(gi_probe->probe);
/* print_line("probe update to version " + itos(gi_probe->last_probe_version));
print_line("propagation " + rtos(push_constant.propagation));
print_line("dynrange " + rtos(push_constant.dynamic_range));
*/
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
int passes = storage->gi_probe_is_using_two_bounces(gi_probe->probe) ? 2 : 1;
for (int pass = 0; pass < passes; pass++) {
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
if (i == 0) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
} else if (i == 1) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]);
}
if (pass == 1 || i > 0) {
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
}
if (pass == 0 || i > 0) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].uniform_set, 0);
} else {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].second_bounce_uniform_set, 0);
}
push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (gi_probe->mipmaps[i].cell_count - 1) / 64 + 1, 1, 1);
}
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0);
push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (gi_probe->mipmaps[i].cell_count - 1) / 64 + 1, 1, 1);
}
}
RD::get_singleton()->compute_list_end();
}
gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe);
print_line("update GI");
}
void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, float p_alpha) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
if (gi_probe->mipmaps.size() == 0) {
return;
}
CameraMatrix transform = (p_camera_with_transform * CameraMatrix(gi_probe->transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(gi_probe->probe).affine_inverse());
int level = 0;
GIProbeDebugPushConstant push_constant;
push_constant.alpha = p_alpha;
push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
push_constant.cell_offset = gi_probe->mipmaps[level].cell_offset;
push_constant.level = level;
int cell_count = gi_probe->mipmaps[level].cell_count;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
push_constant.projection[i * 4 + j] = transform.matrix[i][j];
}
}
if (giprobe_debug_uniform_set.is_valid()) {
RD::get_singleton()->free(giprobe_debug_uniform_set);
}
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
u.ids.push_back(gi_probe->texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 3;
u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 4;
u.ids.push_back(gi_probe->anisotropy[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
u.ids.push_back(gi_probe->anisotropy[1]);
uniforms.push_back(u);
}
}
giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_lighting ? GI_PROBE_DEBUG_LIGHT : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0);
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
}
const Vector<RID> &RasterizerSceneRD::gi_probe_get_slots() const {
return gi_probe_slots;
}
bool RasterizerSceneRD::gi_probe_slots_are_dirty() const {
return gi_probe_slots_dirty;
}
void RasterizerSceneRD::gi_probe_slots_make_not_dirty() {
gi_probe_slots_dirty = false;
}
bool RasterizerSceneRD::gi_probe_is_high_quality() const {
return gi_probe_use_6_cones;
}
////////////////////////////////
RID RasterizerSceneRD::render_buffers_create() {
@ -1218,12 +1680,12 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
return sky_use_cubemap_array;
}
void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
_render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
_render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
@ -1418,6 +1880,20 @@ bool RasterizerSceneRD::free(RID p_rid) {
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (gi_probe_instance_owner.owns(p_rid)) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
RD::get_singleton()->free(gi_probe->texture);
RD::get_singleton()->free(gi_probe->write_buffer);
}
if (gi_probe->anisotropy[0].is_valid()) {
RD::get_singleton()->free(gi_probe->anisotropy[0]);
RD::get_singleton()->free(gi_probe->anisotropy[1]);
}
gi_probe_slots.write[gi_probe->slot] = RID();
gi_probe_instance_owner.free(p_rid);
} else if (sky_owner.owns(p_rid)) {
_update_dirty_skys();
Sky *sky = sky_owner.getornull(p_rid);
@ -1470,13 +1946,83 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
// sky_use_cubemap_array = false;
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
{
String defines = "";
//kinda complicated to compute the amount of slots, we try to use as many as we can
gi_probe_max_lights = 32;
gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights);
gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight));
gi_probe_use_anisotropy = GLOBAL_GET("rendering/quality/gi_probes/anisotropic");
gi_probe_use_6_cones = GLOBAL_GET("rendering/quality/gi_probes/high_quality");
if (textures_per_stage <= 16) {
gi_probe_slots.resize(2); //thats all you can get
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 31) {
gi_probe_slots.resize(4); //thats all you can get, iOS
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 128) {
gi_probe_slots.resize(32); //old intel
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 256) {
gi_probe_slots.resize(64); //old intel too
gi_probe_use_anisotropy = false;
} else {
if (gi_probe_use_anisotropy) {
gi_probe_slots.resize(1024 / 3); //needs 3 textures
} else {
gi_probe_slots.resize(1024); //modern intel, nvidia, 8192 or greater
}
}
String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n";
if (gi_probe_use_anisotropy) {
defines += "\n#define MODE_ANISOTROPIC\n";
}
Vector<String> versions;
versions.push_back("");
giprobe_lighting_shader.initialize(versions, defines);
giprobe_lighting_shader_version = giprobe_lighting_shader.version_create();
giprobe_lighting_shader_version_shader = giprobe_lighting_shader.version_get_shader(giprobe_lighting_shader_version, 0);
versions.push_back("\n#define MODE_COMPUTE_LIGHT\n");
versions.push_back("\n#define MODE_SECOND_BOUNCE\n");
versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n");
versions.push_back("\n#define MODE_WRITE_TEXTURE\n");
giprobe_shader.initialize(versions, defines);
giprobe_lighting_shader_version = giprobe_shader.version_create();
for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) {
giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i);
giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]);
}
}
{
String defines;
if (gi_probe_use_anisotropy) {
defines += "\n#define USE_ANISOTROPY\n";
}
Vector<String> versions;
versions.push_back("\n#define MODE_DEBUG_COLOR\n");
versions.push_back("\n#define MODE_DEBUG_LIGHT\n");
giprobe_debug_shader.initialize(versions, defines);
giprobe_debug_shader_version = giprobe_debug_shader.version_create();
for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) {
giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i);
RD::PipelineRasterizationState rs;
rs.cull_mode = RD::POLYGON_CULL_FRONT;
RD::PipelineDepthStencilState ds;
ds.enable_depth_test = true;
ds.enable_depth_write = true;
ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
}
}
}
@ -1489,4 +2035,7 @@ RasterizerSceneRD::~RasterizerSceneRD() {
for (Map<int, ShadowCubemap>::Element *E = shadow_cubemaps.front(); E; E = E->next()) {
RD::get_singleton()->free(E->get().cubemap);
}
RD::get_singleton()->free(gi_probe_lights_uniform);
memdelete_arr(gi_probe_lights);
}

View file

@ -4,7 +4,8 @@
#include "core/rid_owner.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe_lighting.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h"
#include "servers/visual/rendering_device.h"
class RasterizerSceneRD : public RasterizerScene {
@ -16,9 +17,11 @@ 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_gi_probe_cull_result, int p_gi_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_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;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, float p_alpha);
private:
int roughness_layers;
@ -76,6 +79,7 @@ private:
RID reflection;
RID depth_buffer;
RID depth_fb;
struct Reflection {
RID owner;
@ -111,9 +115,110 @@ private:
/* GIPROBE INSTANCE */
GiprobeLightingShaderRD giprobe_lighting_shader;
struct GIProbeLight {
uint32_t type;
float energy;
float radius;
float attenuation;
float color[3];
float spot_angle_radians;
float position[3];
float spot_attenuation;
float direction[3];
uint32_t has_shadow;
};
struct GIProbePushConstant {
int32_t limits[3];
uint32_t stack_size;
float emission_scale;
float propagation;
float dynamic_range;
uint32_t light_count;
uint32_t cell_offset;
uint32_t cell_count;
float aniso_strength;
uint32_t pad;
};
struct GIProbeInstance {
RID probe;
RID texture;
RID anisotropy[2]; //only if anisotropy is used
RID write_buffer;
struct Mipmap {
RID texture;
RID anisotropy[2]; //only if anisotropy is used
RID uniform_set;
RID second_bounce_uniform_set;
RID write_uniform_set;
uint32_t level;
uint32_t cell_offset;
uint32_t cell_count;
};
Vector<Mipmap> mipmaps;
int slot = -1;
uint32_t last_probe_version = 0;
uint32_t last_probe_data_version = 0;
uint64_t last_pass = 0;
uint32_t render_index = 0;
Transform transform;
};
GIProbeLight *gi_probe_lights;
uint32_t gi_probe_max_lights;
RID gi_probe_lights_uniform;
bool gi_probe_use_anisotropy = false;
bool gi_probe_use_6_cones = false;
bool gi_probe_slots_dirty = true;
Vector<RID> gi_probe_slots;
enum {
GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT,
GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP,
GI_PROBE_SHADER_VERSION_WRITE_TEXTURE,
GI_PROBE_SHADER_VERSION_MAX
};
GiprobeShaderRD giprobe_shader;
RID giprobe_lighting_shader_version;
RID giprobe_lighting_shader_version_shader;
RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX];
RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX];
mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
enum {
GI_PROBE_DEBUG_COLOR,
GI_PROBE_DEBUG_LIGHT,
GI_PROBE_DEBUG_MAX
};
struct GIProbeDebugPushConstant {
float projection[16];
uint32_t cell_offset;
float dynamic_range;
float alpha;
uint32_t level;
};
GiprobeDebugShaderRD giprobe_debug_shader;
RID giprobe_debug_shader_version;
RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX];
RenderPipelineVertexFormatCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX];
RID giprobe_debug_uniform_set;
/* SHADOW ATLAS */
@ -497,6 +602,7 @@ public:
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
RID reflection_probe_instance_get_depth_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);
@ -545,15 +651,70 @@ public:
return rpi->atlas_index;
}
RID gi_probe_instance_create() { return RID(); }
void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {}
void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {}
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
void gi_probe_update(RID p_probe, const Vector<RID> &p_light_instances);
_FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
return gi_probe->slot;
}
_FORCE_INLINE_ RID gi_probe_instance_get_base_probe(RID p_probe) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
return gi_probe->probe;
}
_FORCE_INLINE_ Transform gi_probe_instance_get_transform_to_cell(RID p_probe) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
return storage->gi_probe_get_to_cell_xform(gi_probe->probe) * gi_probe->transform.affine_inverse();
}
_FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
return gi_probe->texture;
}
_FORCE_INLINE_ RID gi_probe_instance_get_aniso_texture(RID p_probe, int p_index) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
return gi_probe->anisotropy[p_index];
}
_FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND(!gi_probe);
gi_probe->render_index = p_render_index;
}
_FORCE_INLINE_ uint32_t gi_probe_instance_get_render_index(RID p_instance) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->render_index;
}
_FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND(!g_probe);
g_probe->last_pass = p_render_pass;
}
_FORCE_INLINE_ uint32_t gi_probe_instance_get_render_pass(RID p_instance) {
GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!g_probe, 0);
return g_probe->last_pass;
}
const Vector<RID> &gi_probe_get_slots() const;
bool gi_probe_slots_are_dirty() const;
void gi_probe_slots_make_not_dirty();
_FORCE_INLINE_ bool gi_probe_is_anisotropic() const {
return gi_probe_use_anisotropy;
}
bool gi_probe_is_high_quality() const;
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_gi_probe_cull_result, int p_gi_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_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);

View file

@ -987,6 +987,7 @@ void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_t
/* COMMON MATERIAL API */
RID RasterizerStorageRD::material_create() {
Material material;
material.data = NULL;
material.shader = NULL;
@ -1924,7 +1925,7 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_
mesh->aabb.merge_with(p_surface.aabb);
}
s->material = p_mesh;
s->material = p_surface.material;
mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
mesh->surfaces[mesh->surface_count] = s;
@ -1995,6 +1996,8 @@ VS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface)
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
sd.vertex_count = s.vertex_count;
sd.index_count = s.index_count;
sd.primitive = s.primitive;
if (sd.index_count) {
sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
}
@ -3544,6 +3547,253 @@ float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribut
return reflection_probe->interior_ambient_probe_contrib;
}
RID RasterizerStorageRD::gi_probe_create() {
return gi_probe_owner.make_rid(GIProbe());
}
void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
bool data_version_changed = false;
if (gi_probe->octree_buffer_size != p_octree_cells.size() || gi_probe->data_buffer_size != p_data_cells.size()) {
//buffer size changed, clear if needed
if (gi_probe->octree_buffer.is_valid()) {
RD::get_singleton()->free(gi_probe->octree_buffer);
RD::get_singleton()->free(gi_probe->data_buffer);
gi_probe->octree_buffer = RID();
gi_probe->data_buffer = RID();
gi_probe->octree_buffer_size = 0;
gi_probe->data_buffer_size = 0;
gi_probe->cell_count = 0;
}
data_version_changed = true;
} else if (gi_probe->octree_buffer_size) {
//they are the same and size did not change..
//update
PoolVector<uint8_t>::Read rc = p_octree_cells.read();
PoolVector<uint8_t>::Read rd = p_data_cells.read();
RD::get_singleton()->buffer_update(gi_probe->octree_buffer, 0, gi_probe->octree_buffer_size, rc.ptr());
RD::get_singleton()->buffer_update(gi_probe->data_buffer, 0, gi_probe->data_buffer_size, rd.ptr());
}
if (gi_probe->level_counts.size() != p_level_counts.size()) {
data_version_changed = true;
} else {
for (int i = 0; i < p_level_counts.size(); i++) {
if (gi_probe->level_counts[i] != p_level_counts[i]) {
data_version_changed = true;
break;
}
}
}
gi_probe->to_cell_xform = p_to_cell_xform;
gi_probe->bounds = p_aabb;
gi_probe->octree_size = p_octree_size;
gi_probe->level_counts = p_level_counts;
if (p_octree_cells.size() && gi_probe->octree_buffer.is_null()) {
ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32
uint32_t cell_count = p_octree_cells.size() / 32;
ERR_FAIL_COND(p_data_cells.size() != cell_count * 16); //see that data size matches
gi_probe->cell_count = cell_count;
gi_probe->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells);
gi_probe->octree_buffer_size = p_octree_cells.size();
gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
gi_probe->data_buffer_size = p_data_cells.size();
data_version_changed = true;
}
gi_probe->version++;
if (data_version_changed) {
gi_probe->data_version++;
}
gi_probe->instance_dependency.instance_notify_changed(true, false);
}
AABB RasterizerStorageRD::gi_probe_get_bounds(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, AABB());
return gi_probe->bounds;
}
Vector3i RasterizerStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Vector3i());
return gi_probe->octree_size;
}
PoolVector<uint8_t> RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, PoolVector<uint8_t>());
if (gi_probe->octree_buffer.is_valid()) {
return RD::get_singleton()->buffer_get_data(gi_probe->octree_buffer);
}
return PoolVector<uint8_t>();
}
PoolVector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, PoolVector<uint8_t>());
if (gi_probe->data_buffer.is_valid()) {
return RD::get_singleton()->buffer_get_data(gi_probe->data_buffer);
}
return PoolVector<uint8_t>();
}
PoolVector<int> RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, PoolVector<int>());
return gi_probe->level_counts;
}
Transform RasterizerStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Transform());
return gi_probe->to_cell_xform;
}
void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->dynamic_range = p_range;
gi_probe->version++;
}
float RasterizerStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->dynamic_range;
}
void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->propagation = p_range;
gi_probe->version++;
}
float RasterizerStorageRD::gi_probe_get_propagation(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->propagation;
}
void RasterizerStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->energy = p_energy;
}
float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->energy;
}
void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->bias = p_bias;
}
float RasterizerStorageRD::gi_probe_get_bias(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->bias;
}
void RasterizerStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->normal_bias = p_normal_bias;
}
float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->normal_bias;
}
void RasterizerStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->anisotropy_strength = p_strength;
}
float RasterizerStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->anisotropy_strength;
}
void RasterizerStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->interior = p_enable;
}
void RasterizerStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->use_two_bounces = p_enable;
gi_probe->version++;
}
bool RasterizerStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, false);
return gi_probe->use_two_bounces;
}
bool RasterizerStorageRD::gi_probe_is_interior(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->interior;
}
uint32_t RasterizerStorageRD::gi_probe_get_version(RID p_gi_probe) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->version;
}
uint32_t RasterizerStorageRD::gi_probe_get_data_version(RID p_gi_probe) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
return gi_probe->data_version;
}
RID RasterizerStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, RID());
return gi_probe->octree_buffer;
}
RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, RID());
return gi_probe->data_buffer;
}
/* RENDER TARGET API */
void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
@ -3821,7 +4071,7 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
}
Vector<Color> clear_colors;
clear_colors.push_back(rt->clear_color);
RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors);
RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
RD::get_singleton()->draw_list_end();
rt->clear_requested = false;
}
@ -3899,6 +4149,9 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
} 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 (gi_probe_owner.owns(p_base)) {
GIProbe *gip = gi_probe_owner.getornull(p_base);
p_instance->update_dependency(&gip->instance_dependency);
} else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base);
p_instance->update_dependency(&l->instance_dependency);
@ -3924,6 +4177,9 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE;
}
if (gi_probe_owner.owns(p_rid)) {
return VS::INSTANCE_GI_PROBE;
}
if (light_owner.owns(p_rid)) {
return VS::INSTANCE_LIGHT;
}
@ -4032,6 +4288,11 @@ bool RasterizerStorageRD::free(RID 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 (gi_probe_owner.owns(p_rid)) {
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), PoolVector<uint8_t>(), PoolVector<uint8_t>(), PoolVector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
gi_probe->instance_dependency.instance_notify_deleted(p_rid);
gi_probe_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {

View file

@ -401,6 +401,42 @@ private:
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
/* GI PROBE */
struct GIProbe {
RID octree_buffer;
RID data_buffer;
uint32_t octree_buffer_size = 0;
uint32_t data_buffer_size = 0;
PoolVector<int> level_counts;
int cell_count = 0;
Transform to_cell_xform;
AABB bounds;
Vector3i octree_size;
float dynamic_range = 4.0;
float energy = 1.0;
float bias = 1.4;
float normal_bias = 0.0;
float propagation = 0.7;
bool interior = false;
bool use_two_bounces = false;
float anisotropy_strength = 0.5;
uint32_t version = 1;
uint32_t data_version = 1;
RasterizerScene::InstanceDependency instance_dependency;
};
mutable RID_Owner<GIProbe> gi_probe_owner;
/* RENDER TARGET */
struct RenderTarget {
@ -922,49 +958,46 @@ public:
/* GI PROBE API */
RID gi_probe_create() { return RID(); }
RID gi_probe_create();
void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {}
AABB gi_probe_get_bounds(RID p_probe) const { return AABB(); }
void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts);
void gi_probe_set_cell_size(RID p_probe, float p_range) {}
float gi_probe_get_cell_size(RID p_probe) const { return 0.0; }
AABB gi_probe_get_bounds(RID p_gi_probe) const;
Vector3i gi_probe_get_octree_size(RID p_gi_probe) const;
PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const;
PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const;
PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const;
Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const;
void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) {}
Transform gi_probe_get_to_cell_xform(RID p_probe) const { return Transform(); }
void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range);
float gi_probe_get_dynamic_range(RID p_gi_probe) const;
void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) {}
PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const {
PoolVector<int> p;
return p;
}
void gi_probe_set_propagation(RID p_gi_probe, float p_range);
float gi_probe_get_propagation(RID p_gi_probe) const;
void gi_probe_set_dynamic_range(RID p_probe, int p_range) {}
int gi_probe_get_dynamic_range(RID p_probe) const { return 0; }
void gi_probe_set_energy(RID p_gi_probe, float p_energy);
float gi_probe_get_energy(RID p_gi_probe) const;
void gi_probe_set_energy(RID p_probe, float p_range) {}
float gi_probe_get_energy(RID p_probe) const { return 0.0; }
void gi_probe_set_bias(RID p_gi_probe, float p_bias);
float gi_probe_get_bias(RID p_gi_probe) const;
void gi_probe_set_bias(RID p_probe, float p_range) {}
float gi_probe_get_bias(RID p_probe) const { return 0.0; }
void gi_probe_set_normal_bias(RID p_gi_probe, float p_range);
float gi_probe_get_normal_bias(RID p_gi_probe) const;
void gi_probe_set_normal_bias(RID p_probe, float p_range) {}
float gi_probe_get_normal_bias(RID p_probe) const { return 0.0; }
void gi_probe_set_interior(RID p_gi_probe, bool p_enable);
bool gi_probe_is_interior(RID p_gi_probe) const;
void gi_probe_set_propagation(RID p_probe, float p_range) {}
float gi_probe_get_propagation(RID p_probe) const { return 0.0; }
void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable);
bool gi_probe_is_using_two_bounces(RID p_gi_probe) const;
void gi_probe_set_interior(RID p_probe, bool p_enable) {}
bool gi_probe_is_interior(RID p_probe) const { return false; }
void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength);
float gi_probe_get_anisotropy_strength(RID p_gi_probe) const;
void gi_probe_set_compress(RID p_probe, bool p_enable) {}
bool gi_probe_is_compressed(RID p_probe) const { return false; }
uint32_t gi_probe_get_version(RID p_probe);
uint32_t gi_probe_get_data_version(RID p_probe);
uint32_t gi_probe_get_version(RID p_probe) { return 0; }
GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const { return GI_PROBE_UNCOMPRESSED; }
RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { return RID(); }
void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {}
RID gi_probe_get_octree_buffer(RID p_gi_probe) const;
RID gi_probe_get_data_buffer(RID p_gi_probe) const;
/* LIGHTMAP CAPTURE */

View file

@ -11,5 +11,6 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('sky.glsl');
env.RD_GLSL('tonemap.glsl');
env.RD_GLSL('copy.glsl');
env.RD_GLSL('giprobe_lighting.glsl');
env.RD_GLSL('giprobe.glsl');
env.RD_GLSL('giprobe_debug.glsl');

View file

@ -0,0 +1,543 @@
[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333,0.33333,0.33333)
struct CellChildren {
uint children[8];
};
layout(set=0,binding=1,std430) buffer CellChildrenBuffer {
CellChildren data[];
} cell_children;
struct CellData {
uint position; // xyz 10 bits
uint albedo; //rgb albedo
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
layout(set=0,binding=2,std430) buffer CellDataBuffer {
CellData data[];
} cell_data;
#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_OMNI 1
#define LIGHT_TYPE_SPOT 2
#ifdef MODE_COMPUTE_LIGHT
struct Light {
uint type;
float energy;
float radius;
float attenuation;
vec3 color;
float spot_angle_radians;
vec3 position;
float spot_attenuation;
vec3 direction;
bool has_shadow;
};
layout(set=0,binding=3,std140) uniform Lights {
Light data[MAX_LIGHTS];
} lights;
#endif // MODE COMPUTE LIGHT
#ifdef MODE_SECOND_BOUNCE
layout (set=0,binding=5) uniform texture3D color_texture;
layout (set=0,binding=6) uniform sampler texture_sampler;
#ifdef MODE_ANISOTROPIC
layout (set=0,binding=7) uniform texture3D aniso_pos_texture;
layout (set=0,binding=8) uniform texture3D aniso_neg_texture;
#endif // MODE ANISOTROPIC
#endif // MODE_SECOND_BOUNCE
layout(push_constant, binding = 0, std430) uniform Params {
ivec3 limits;
uint stack_size;
float emission_scale;
float propagation;
float dynamic_range;
uint light_count;
uint cell_offset;
uint cell_count;
float aniso_strength;
uint pad;
} params;
layout(set=0,binding=4,std430) buffer Outputs {
vec4 data[];
} outputs;
#ifdef MODE_WRITE_TEXTURE
layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
#ifdef MODE_ANISOTROPIC
layout (r16ui,set=0,binding=6) uniform restrict writeonly uimage3D aniso_pos_tex;
layout (r16ui,set=0,binding=7) uniform restrict writeonly uimage3D aniso_neg_tex;
#endif
#endif
#ifdef MODE_COMPUTE_LIGHT
uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
uint result = NO_CHILDREN;
ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
while (distance > -distance_adv) { //use this to avoid precision errors
uint cell = 0;
ivec3 pos = ivec3(from);
if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
ivec3 ofs = ivec3(0);
ivec3 half_size = size / 2;
for (int i = 0; i < params.stack_size - 1; i++) {
bvec3 greater = greaterThanEqual(pos,ofs+half_size);
ofs += mix(ivec3(0),half_size,greater);
uint child = 0; //wonder if this can be done faster
if (greater.x) {
child|=1;
}
if (greater.y) {
child|=2;
}
if (greater.z) {
child|=4;
}
cell = cell_children.data[cell].children[child];
if (cell == NO_CHILDREN)
break;
half_size >>= ivec3(1);
}
if ( cell != NO_CHILDREN) {
return cell; //found cell!
}
}
from += direction * distance_adv;
distance -= distance_adv;
}
return NO_CHILDREN;
}
bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
} else {
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
return false;
}
attenuation = pow( clamp( 1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation );
if (lights.data[light].type==LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel,lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
return false;
}
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
}
}
return true;
}
float get_normal_advance(vec3 p_normal) {
vec3 normal = p_normal;
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);
}
return 1.0 / dot(normal,unorm);
}
#endif
void main() {
uint cell_index = gl_GlobalInvocationID.x;;
if (cell_index >= params.cell_count) {
return;
}
cell_index += params.cell_offset;
uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
/////////////////COMPUTE LIGHT///////////////////////////////
#ifdef MODE_COMPUTE_LIGHT
vec3 pos = vec3(posu) + vec3(0.5);
vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission&0x3FF,(cell_data.data[cell_index].emission>>10)&0x7FF,cell_data.data[cell_index].emission>>21)) * params.emission_scale;
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
#ifdef MODE_ANISOTROPIC
vec3 accum[6]=vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
#else
vec3 accum = vec3(0.0);
#endif
for(uint i=0;i<params.light_count;i++) {
float attenuation;
vec3 light_pos;
if (!compute_light_vector(i,cell_index,pos,attenuation,light_pos)) {
continue;
}
vec3 light_dir = pos - light_pos;
float distance = length(light_dir);
light_dir=normalize(light_dir);
if (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0) {
continue; //not facing the light
}
if (lights.data[i].has_shadow) {
float distance_adv = get_normal_advance(light_dir);
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
vec3 from = pos - light_dir * distance; //approximate
from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
uint result = raymarch(distance,distance_adv,from,light_dir);
if (result != cell_index) {
continue; //was occluded
}
}
vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
#ifdef MODE_ANISOTROPIC
for(uint j=0;j<6;j++) {
accum[j]+=max(0.0,dot(accum_dirs[j],-light_dir))*light+emission;
}
#else
if (length(normal.xyz) > 0.2) {
accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
} else {
//all directions
accum+=light+emission;
}
#endif
}
#ifdef MODE_ANISOTROPIC
outputs.data[cell_index*6+0]=vec4(accum[0],0.0);
outputs.data[cell_index*6+1]=vec4(accum[1],0.0);
outputs.data[cell_index*6+2]=vec4(accum[2],0.0);
outputs.data[cell_index*6+3]=vec4(accum[3],0.0);
outputs.data[cell_index*6+4]=vec4(accum[4],0.0);
outputs.data[cell_index*6+5]=vec4(accum[5],0.0);
#else
outputs.data[cell_index]=vec4(accum,0.0);
#endif
#endif //MODE_COMPUTE_LIGHT
/////////////////SECOND BOUNCE///////////////////////////////
#ifdef MODE_SECOND_BOUNCE
vec3 pos = vec3(posu) + vec3(0.5);
ivec3 ipos = ivec3(posu);
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
#ifdef MODE_ANISOTROPIC
vec3 accum[6];
const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
/*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range;
vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb;
vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb;
accum[0]=src_col * src_aniso_pos.x;
accum[1]=src_col * src_aniso_neg.x;
accum[2]=src_col * src_aniso_pos.y;
accum[3]=src_col * src_aniso_neg.y;
accum[4]=src_col * src_aniso_pos.z;
accum[5]=src_col * src_aniso_neg.z;*/
accum[0] = outputs.data[cell_index*6+0].rgb;
accum[1] = outputs.data[cell_index*6+1].rgb;
accum[2] = outputs.data[cell_index*6+2].rgb;
accum[3] = outputs.data[cell_index*6+3].rgb;
accum[4] = outputs.data[cell_index*6+4].rgb;
accum[5] = outputs.data[cell_index*6+5].rgb;
#else
vec3 accum = outputs.data[cell_index].rgb;
#endif
if (length(normal.xyz) > 0.2) {
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal.xyz));
vec3 bitangent = normalize(cross(tangent, normal.xyz));
mat3 normal_mat = mat3(tangent, bitangent, normal.xyz);
#define MAX_CONE_DIRS 6
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
vec3(0.0, 0.0, 1.0),
vec3(0.866025, 0.0, 0.5),
vec3(0.267617, 0.823639, 0.5),
vec3(-0.700629, 0.509037, 0.5),
vec3(-0.700629, -0.509037, 0.5),
vec3(0.267617, -0.823639, 0.5));
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
float tan_half_angle = 0.577;
for (int i = 0; i < MAX_CONE_DIRS; i++) {
vec3 direction = normal_mat * cone_dirs[i];
vec4 color = vec4(0.0);
{
float dist = 1.5;
float max_distance = length(vec3(params.limits));
vec3 cell_size = 1.0 / vec3(params.limits);
#ifdef MODE_ANISOTROPIC
vec3 aniso_normal = mix(direction,normal.xyz,params.aniso_strength);
#endif
while (dist < max_distance && color.a < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec3 uvw_pos = (pos + dist * direction) * cell_size;
float half_diameter = diameter * 0.5;
//check if outside, then break
//if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
// break;
//}
float log2_diameter = log2(diameter);
vec4 scolor = textureLod(sampler3D(color_texture,texture_sampler), uvw_pos, log2_diameter);
#ifdef MODE_ANISOTROPIC
vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture,texture_sampler), uvw_pos, log2_diameter).rgb;
vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture,texture_sampler), uvw_pos, log2_diameter).rgb;
scolor.rgb*=dot(max(vec3(0.0),(aniso_normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-aniso_normal * aniso_neg)),vec3(1.0));
#endif
float a = (1.0 - color.a);
color += a * scolor;
dist += half_diameter;
}
}
color *= cone_weights[i] * params.dynamic_range; //restore range
#ifdef MODE_ANISOTROPIC
for(uint j=0;j<6;j++) {
accum[j]+=max(0.0,dot(accum_dirs[j],direction))*color.rgb;
}
#else
accum+=color.rgb;
#endif
}
}
#ifdef MODE_ANISOTROPIC
outputs.data[cell_index*6+0]=vec4(accum[0],0.0);
outputs.data[cell_index*6+1]=vec4(accum[1],0.0);
outputs.data[cell_index*6+2]=vec4(accum[2],0.0);
outputs.data[cell_index*6+3]=vec4(accum[3],0.0);
outputs.data[cell_index*6+4]=vec4(accum[4],0.0);
outputs.data[cell_index*6+5]=vec4(accum[5],0.0);
#else
outputs.data[cell_index]=vec4(accum,0.0);
#endif
#endif // MODE_SECOND_BOUNCE
/////////////////UPDATE MIPMAPS///////////////////////////////
#ifdef MODE_UPDATE_MIPMAPS
{
#ifdef MODE_ANISOTROPIC
vec3 light_accum[6] = vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
#else
vec3 light_accum = vec3(0.0);
#endif
float count = 0.0;
for(uint i=0;i<8;i++) {
uint child_index = cell_children.data[cell_index].children[i];
if (child_index==NO_CHILDREN) {
continue;
}
#ifdef MODE_ANISOTROPIC
light_accum[0] += outputs.data[child_index*6+0].rgb;
light_accum[1] += outputs.data[child_index*6+1].rgb;
light_accum[2] += outputs.data[child_index*6+2].rgb;
light_accum[3] += outputs.data[child_index*6+3].rgb;
light_accum[4] += outputs.data[child_index*6+4].rgb;
light_accum[5] += outputs.data[child_index*6+5].rgb;
#else
light_accum += outputs.data[child_index].rgb;
#endif
count+=1.0;
}
float divisor = mix(8.0,count,params.propagation);
#ifdef MODE_ANISOTROPIC
outputs.data[cell_index*6+0]=vec4(light_accum[0] / divisor,0.0);
outputs.data[cell_index*6+1]=vec4(light_accum[1] / divisor,0.0);
outputs.data[cell_index*6+2]=vec4(light_accum[2] / divisor,0.0);
outputs.data[cell_index*6+3]=vec4(light_accum[3] / divisor,0.0);
outputs.data[cell_index*6+4]=vec4(light_accum[4] / divisor,0.0);
outputs.data[cell_index*6+5]=vec4(light_accum[5] / divisor,0.0);
#else
outputs.data[cell_index]=vec4(light_accum / divisor,0.0);
#endif
}
#endif
///////////////////WRITE TEXTURE/////////////////////////////
#ifdef MODE_WRITE_TEXTURE
{
#ifdef MODE_ANISOTROPIC
vec3 accum_total = vec3(0.0);
accum_total += outputs.data[cell_index*6+0].rgb;
accum_total += outputs.data[cell_index*6+1].rgb;
accum_total += outputs.data[cell_index*6+2].rgb;
accum_total += outputs.data[cell_index*6+3].rgb;
accum_total += outputs.data[cell_index*6+4].rgb;
accum_total += outputs.data[cell_index*6+5].rgb;
float accum_total_energy = max(dot(accum_total,GREY_VEC),0.00001);
vec3 iso_positive = vec3(dot(outputs.data[cell_index*6+0].rgb,GREY_VEC),dot(outputs.data[cell_index*6+2].rgb,GREY_VEC),dot(outputs.data[cell_index*6+4].rgb,GREY_VEC))/vec3(accum_total_energy);
vec3 iso_negative = vec3(dot(outputs.data[cell_index*6+1].rgb,GREY_VEC),dot(outputs.data[cell_index*6+3].rgb,GREY_VEC),dot(outputs.data[cell_index*6+5].rgb,GREY_VEC))/vec3(accum_total_energy);
{
uint aniso_pos = uint(clamp(iso_positive.b * 31.0,0.0,31.0));
aniso_pos |= uint(clamp(iso_positive.g * 63.0,0.0,63.0))<<5;
aniso_pos |= uint(clamp(iso_positive.r * 31.0,0.0,31.0))<<11;
imageStore(aniso_pos_tex,ivec3(posu),uvec4(aniso_pos));
}
{
uint aniso_neg = uint(clamp(iso_negative.b * 31.0,0.0,31.0));
aniso_neg |= uint(clamp(iso_negative.g * 63.0,0.0,63.0))<<5;
aniso_neg |= uint(clamp(iso_negative.r * 31.0,0.0,31.0))<<11;
imageStore(aniso_neg_tex,ivec3(posu),uvec4(aniso_neg));
}
imageStore(color_tex,ivec3(posu),vec4(accum_total / params.dynamic_range ,albedo.a));
#else
imageStore(color_tex,ivec3(posu),vec4(outputs.data[cell_index].rgb / params.dynamic_range,albedo.a));
#endif
}
#endif
}

View file

@ -0,0 +1,160 @@
[vertex]
#version 450
VERSION_DEFINES
struct CellData {
uint position; // xyz 10 bits
uint albedo; //rgb albedo
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
layout(set=0,binding=1,std140) buffer CellDataBuffer {
CellData data[];
} cell_data;
layout (set=0,binding=2) uniform texture3D color_tex;
layout (set=0,binding=3) uniform sampler tex_sampler;
#ifdef USE_ANISOTROPY
layout (set=0,binding=4) uniform texture3D aniso_pos_tex;
layout (set=0,binding=5) uniform texture3D aniso_neg_tex;
#endif
layout(push_constant, binding = 0, std430) uniform Params {
mat4 projection;
uint cell_offset;
float dynamic_range;
float alpha;
uint level;
} params;
layout(location=0) out vec4 color_interp;
void main() {
const vec3 cube_triangles[36] = vec3[](
vec3(-1.0f,-1.0f,-1.0f),
vec3(-1.0f,-1.0f, 1.0f),
vec3(-1.0f, 1.0f, 1.0f),
vec3(1.0f, 1.0f,-1.0f),
vec3(-1.0f,-1.0f,-1.0f),
vec3(-1.0f, 1.0f,-1.0f),
vec3(1.0f,-1.0f, 1.0f),
vec3(-1.0f,-1.0f,-1.0f),
vec3(1.0f,-1.0f,-1.0f),
vec3(1.0f, 1.0f,-1.0f),
vec3(1.0f,-1.0f,-1.0f),
vec3(-1.0f,-1.0f,-1.0f),
vec3(-1.0f,-1.0f,-1.0f),
vec3(-1.0f, 1.0f, 1.0f),
vec3(-1.0f, 1.0f,-1.0f),
vec3(1.0f,-1.0f, 1.0f),
vec3(-1.0f,-1.0f, 1.0f),
vec3(-1.0f,-1.0f,-1.0f),
vec3(-1.0f, 1.0f, 1.0f),
vec3(-1.0f,-1.0f, 1.0f),
vec3(1.0f,-1.0f, 1.0f),
vec3(1.0f, 1.0f, 1.0f),
vec3(1.0f,-1.0f,-1.0f),
vec3(1.0f, 1.0f,-1.0f),
vec3(1.0f,-1.0f,-1.0f),
vec3(1.0f, 1.0f, 1.0f),
vec3(1.0f,-1.0f, 1.0f),
vec3(1.0f, 1.0f, 1.0f),
vec3(1.0f, 1.0f,-1.0f),
vec3(-1.0f, 1.0f,-1.0f),
vec3(1.0f, 1.0f, 1.0f),
vec3(-1.0f, 1.0f,-1.0f),
vec3(-1.0f, 1.0f, 1.0f),
vec3(1.0f, 1.0f, 1.0f),
vec3(-1.0f, 1.0f, 1.0f),
vec3(1.0f,-1.0f, 1.0f)
);
vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5;
uint cell_index = gl_InstanceIndex + params.cell_offset;
uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
#ifdef MODE_DEBUG_COLOR
color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz;
#endif
#ifdef MODE_DEBUG_LIGHT
#ifdef USE_ANISOTROPY
#define POS_X 0
#define POS_Y 1
#define POS_Z 2
#define NEG_X 3
#define NEG_Y 4
#define NEG_Z 5
const uint triangle_aniso[12] = uint[](
NEG_X,
NEG_Z,
NEG_Y,
NEG_Z,
NEG_X,
NEG_Y,
POS_Z,
POS_X,
POS_X,
POS_Y,
POS_Y,
POS_Z
);
color_interp.xyz = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level)).xyz * params.dynamic_range;
vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex,tex_sampler),ivec3(posu),int(params.level)).xyz;
vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex,tex_sampler),ivec3(posu),int(params.level)).xyz;
uint side = triangle_aniso[gl_VertexIndex/3];
float strength = 0.0;
switch(side) {
case POS_X: strength = aniso_pos.x; break;
case POS_Y: strength = aniso_pos.y; break;
case POS_Z: strength = aniso_pos.z; break;
case NEG_X: strength = aniso_neg.x; break;
case NEG_Y: strength = aniso_neg.y; break;
case NEG_Z: strength = aniso_neg.z; break;
}
color_interp.xyz *= strength;
#else
color_interp.xyz = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level)).xyz * params.dynamic_range;
#endif
#endif
float scale = (1<<params.level);
color_interp.a = params.alpha;
gl_Position = params.projection * vec4((vec3(posu)+vertex)*scale,1.0);
}
[fragment]
#version 450
VERSION_DEFINES
layout(location=0) in vec4 color_interp;
layout(location=0) out vec4 frag_color;
void main() {
frag_color = color_interp;
}

View file

@ -1,241 +0,0 @@
[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333,0.33333,0.33333)
struct CellPosition {
uint children[8];
};
layout(set=0,binding=1,std140) buffer CellPositions {
CellPosition data[];
} cell_positions;
struct CellMaterial {
uint position; // xyz 10 bits
uint albedo; //rgb albedo
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
layout(set=0,binding=2,std140) buffer CellMaterials {
CellMaterial data[];
} cell_materials;
#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_OMNI 1
#define LIGHT_TYPE_SPOT 2
struct Light {
uint type;
float energy;
float radius;
float attenuation;
vec3 color;
float spot_angle_radians;
float advance;
float max_length;
uint pad0;
uint pad2;
vec3 position;
float spot_attenuation;
vec3 direction;
bool visible;
vec4 clip_planes[3];
};
layout(set=0,binding=3,std140) buffer Lights {
Light data[];
} lights;
layout(set=0,binding=4,std140) uniform Params {
vec3 limits;
float max_length;
uint size;
uint stack_size;
uint light_count;
float emission_scale;
} params;
layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
uint result = NO_CHILDREN;
while (distance > -distance_adv) { //use this to avoid precision errors
uint cell = 0;
ivec3 pos = ivec3(from);
ivec3 ofs = ivec3(0);
ivec3 half_size = ivec3(params.size) / 2;
if (any(lessThan(pos,ivec3(0))) || any(greaterThanEqual(pos,ivec3(params.size)))) {
return NO_CHILDREN; //outside range
}
for (int i = 0; i < params.stack_size - 1; i++) {
bvec3 greater = greaterThanEqual(pos,ofs+half_size);
ofs += mix(ivec3(0),half_size,greater);
uint child = 0; //wonder if this can be done faster
if (greater.x) {
child|=1;
}
if (greater.y) {
child|=2;
}
if (greater.z) {
child|=4;
}
cell = cell_positions.data[cell].children[child];
if (cell == NO_CHILDREN)
break;
half_size >>= ivec3(1);
}
if ( cell != NO_CHILDREN) {
return cell; //found cell!
}
from += direction * distance_adv;
distance -= distance_adv;
}
return NO_CHILDREN;
}
bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * params.max_length;
attenuation = 1.0;
} else {
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
return false;
}
attenuation = pow( distance / lights.data[light].radius + 0.0001, lights.data[light].attenuation );
if (lights.data[light].type==LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel,lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
return false;
}
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
}
}
return true;
}
void main() {
uint cell_index = gl_GlobalInvocationID.x;
uvec3 posu = uvec3(cell_materials.data[cell_index].position&0x3FF,(cell_materials.data[cell_index].position>>10)&0x3FF,cell_materials.data[cell_index].position>>20);
vec3 pos = vec3(posu);
vec3 emission = vec3(ivec3(cell_materials.data[cell_index].emission&0x3FF,(cell_materials.data[cell_index].emission>>10)&0x7FF,cell_materials.data[cell_index].emission>>21)) * params.emission_scale;
vec4 albedo = unpackUnorm4x8(cell_materials.data[cell_index].albedo);
vec4 normal = unpackSnorm4x8(cell_materials.data[cell_index].normal); //w >0.5 means, all directions
#ifdef MODE_ANISOTROPIC
vec3 accum[6]=vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
#else
vec3 accum = vec3(0);
#endif
for(uint i=0;i<params.light_count;i++) {
float attenuation;
vec3 light_pos;
if (!compute_light_vector(i,cell_index,pos,attenuation,light_pos)) {
continue;
}
float distance_adv = lights.data[i].advance;
vec3 light_dir = pos - light_pos;
float distance = length(light_dir);
light_dir=normalize(light_dir);
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
vec3 from = pos - light_dir * distance; //approximate
if (normal.w < 0.5 && dot(normal.xyz,light_dir)>=0) {
continue; //not facing the light
}
uint result = raymarch(distance,distance_adv,from,lights.data[i].direction);
if (result != cell_index) {
continue; //was occluded
}
vec3 light = lights.data[i].color * albedo.rgb * attenuation;
#ifdef MODE_ANISOTROPIC
for(uint j=0;j<6;j++) {
accum[j]+=max(0.0,dot(accum_dir,-light_dir))*light+emission;
}
#else
if (normal.w < 0.5) {
accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
} else {
//all directions
accum+=light+emission;
}
#endif
}
#ifdef MODE_ANISOTROPIC
vec3 accum_total = accum[0]+accum[1]+accum[2]+accum[3]+accum[4]+accum[5];
float accum_total_energy = max(dot(accum_total,GREY_VEC),0.00001);
vec3 iso_positive = vec3(dot(aniso[0],GREY_VEC),dot(aniso[2],GREY_VEC),dot(aniso[4],GREY_VEC))/vec3(accum_total_energy);
vec3 iso_negative = vec3(dot(aniso[1],GREY_VEC),dot(aniso[3],GREY_VEC),dot(aniso[5],GREY_VEC))/vec3(accum_total_energy);
//store in 3D textures, total color, and isotropic magnitudes
#else
//store in 3D texture pos, accum
imageStore(color_tex,ivec3(posu),vec4(accum,albedo.a));
#endif
}

View file

@ -0,0 +1,353 @@
[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333,0.33333,0.33333)
struct CellChildren {
uint children[8];
};
layout(set=0,binding=1,std430) buffer CellChildrenBuffer {
CellChildren data[];
} cell_children;
struct CellData {
uint position; // xyz 10 bits
uint albedo; //rgb albedo
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
layout(set=0,binding=2,std430) buffer CellDataBuffer {
CellData data[];
} cell_data;
#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_OMNI 1
#define LIGHT_TYPE_SPOT 2
#ifdef MODE_COMPUTE_LIGHT
struct Light {
uint type;
float energy;
float radius;
float attenuation;
vec3 color;
float spot_angle_radians;
vec3 position;
float spot_attenuation;
vec3 direction;
bool has_shadow;
};
layout(set=0,binding=3,std140) uniform Lights {
Light data[MAX_LIGHTS];
} lights;
#endif
layout(push_constant, binding = 0, std430) uniform Params {
ivec3 limits;
uint stack_size;
float emission_scale;
float propagation;
float dynamic_range;
uint light_count;
uint cell_offset;
uint cell_count;
uint pad[2];
} params;
layout(set=0,binding=4,std140) uniform Outputs {
vec4 data[];
} output;
#ifdef MODE_COMPUTE_LIGHT
uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
uint result = NO_CHILDREN;
ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
while (distance > -distance_adv) { //use this to avoid precision errors
uint cell = 0;
ivec3 pos = ivec3(from);
if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
ivec3 ofs = ivec3(0);
ivec3 half_size = size / 2;
for (int i = 0; i < params.stack_size - 1; i++) {
bvec3 greater = greaterThanEqual(pos,ofs+half_size);
ofs += mix(ivec3(0),half_size,greater);
uint child = 0; //wonder if this can be done faster
if (greater.x) {
child|=1;
}
if (greater.y) {
child|=2;
}
if (greater.z) {
child|=4;
}
cell = cell_children.data[cell].children[child];
if (cell == NO_CHILDREN)
break;
half_size >>= ivec3(1);
}
if ( cell != NO_CHILDREN) {
return cell; //found cell!
}
}
from += direction * distance_adv;
distance -= distance_adv;
}
return NO_CHILDREN;
}
bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
} else {
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
return false;
}
attenuation = pow( clamp( 1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation );
if (lights.data[light].type==LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel,lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
return false;
}
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
}
}
return true;
}
float get_normal_advance(vec3 p_normal) {
vec3 normal = p_normal;
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);
}
return 1.0 / dot(normal,unorm);
}
#endif
void main() {
uint cell_index = gl_GlobalInvocationID.x;;
if (cell_index >= params.cell_count) {
return;
}
cell_index += params.cell_offset;
uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
#ifdef MODE_COMPUTE_LIGHT
vec3 pos = vec3(posu) + vec3(0.5);
vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission&0x3FF,(cell_data.data[cell_index].emission>>10)&0x7FF,cell_data.data[cell_index].emission>>21)) * params.emission_scale;
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
#ifdef MODE_ANISOTROPIC
vec3 accum[6]=vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
#else
vec3 accum = vec3(0.0);
#endif
for(uint i=0;i<params.light_count;i++) {
float attenuation;
vec3 light_pos;
if (!compute_light_vector(i,cell_index,pos,attenuation,light_pos)) {
continue;
}
vec3 light_dir = pos - light_pos;
float distance = length(light_dir);
light_dir=normalize(light_dir);
if (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0) {
continue; //not facing the light
}
if (lights.data[i].has_shadow) {
float distance_adv = get_normal_advance(light_dir);
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
vec3 from = pos - light_dir * distance; //approximate
from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
uint result = raymarch(distance,distance_adv,from,light_dir);
if (result != cell_index) {
continue; //was occluded
}
}
vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
#ifdef MODE_ANISOTROPIC
for(uint j=0;j<6;j++) {
accum[j]+=max(0.0,dot(accum_dir,-light_dir))*light+emission;
}
#else
if (length(normal.xyz) > 0.2) {
accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
} else {
//all directions
accum+=light+emission;
}
#endif
}
#ifdef MODE_ANISOTROPIC
output.data[cell_index*6+0]=vec4(accum[0],0.0);
output.data[cell_index*6+1]=vec4(accum[1],0.0);
output.data[cell_index*6+2]=vec4(accum[2],0.0);
output.data[cell_index*6+3]=vec4(accum[3],0.0);
output.data[cell_index*6+4]=vec4(accum[4],0.0);
output.data[cell_index*6+5]=vec4(accum[5],0.0);
#else
output.data[cell_index]=vec4(accum,0.0);
#endif
#endif //MODE_COMPUTE_LIGHT
#ifdef MODE_UPDATE_MIPMAPS
{
#ifdef MODE_ANISOTROPIC
vec3 light_accum[6] = vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
#else
vec3 light_accum = vec3(0.0);
#endif
float count = 0.0;
for(uint i=0;i<8;i++) {
uint child_index = cell_children.data[cell_index].children[i];
if (child_index==NO_CHILDREN) {
continue;
}
#ifdef MODE_ANISOTROPIC
light_accum[1] += output.data[child_index*6+0].rgb;
light_accum[2] += output.data[child_index*6+1].rgb;
light_accum[3] += output.data[child_index*6+2].rgb;
light_accum[4] += output.data[child_index*6+3].rgb;
light_accum[5] += output.data[child_index*6+4].rgb;
light_accum[6] += output.data[child_index*6+5].rgb;
#else
light_accum += output.data[child_index].rgb;
#endif
count+=1.0;
}
float divisor = mix(8.0,count,params.propagation);
#ifdef MODE_ANISOTROPIC
output.data[cell_index*6+0]=vec4(light_accum[0] / divisor,0.0);
output.data[cell_index*6+1]=vec4(light_accum[1] / divisor,0.0);
output.data[cell_index*6+2]=vec4(light_accum[2] / divisor,0.0);
output.data[cell_index*6+3]=vec4(light_accum[3] / divisor,0.0);
output.data[cell_index*6+4]=vec4(light_accum[4] / divisor,0.0);
output.data[cell_index*6+5]=vec4(light_accum[5] / divisor,0.0);
#else
output.data[cell_index]=vec4(light_accum / divisor,0.0);
#endif
}
#endif
#ifdef MODE_WRITE_TEXTURE
{
}
#endif
}

View file

@ -57,7 +57,7 @@ layout(location = 6) out vec3 binormal_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
layout(set = 3, binding = 0, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@ -73,7 +73,7 @@ VERTEX_SHADER_GLOBALS
// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
//invariant gl_Position;
invariant gl_Position;
layout(location =7) flat out uint instance_index;
@ -274,7 +274,7 @@ VERTEX_SHADER_CODE
#endif //MODE_RENDER_DEPTH
#ifdef USE_OVERRIDE_POSITION
gl_Position = position;;
gl_Position = position;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
@ -331,7 +331,7 @@ layout(location =8) in float dp_clip;
#define projection_matrix scene_data.projection_matrix;
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
layout(set = 3, binding = 0, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@ -918,6 +918,265 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal,float roughness
#endif //USE_LIGHTMAP
}
#ifdef USE_VOXEL_CONE_TRACING
//standard voxel cone trace
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
float dist = p_bias;
vec4 color = vec4(0.0);
while (dist < max_distance && color.a < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec3 uvw_pos = (pos + dist * direction) * cell_size;
float half_diameter = diameter * 0.5;
//check if outside, then break
if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
break;
}
vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
float a = (1.0 - color.a);
color += a * scolor;
dist += half_diameter;
}
return color;
}
#if 0
vec4 voxel_cone_trace_skiplod(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
float dist = p_bias;
vec4 color = vec4(0.0);
float skip_lod = 1.0;
while (dist < max_distance && color.a < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec3 uvw_pos = (pos + dist * direction) * cell_size;
float half_diameter = diameter * 0.5;
//check if outside, then break
if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
break;
}
vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
float a = (1.0 - color.a);
color += a * scolor;
float upper_opacity = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, skip_lod).a;
float skip_factor = exp2( max( 0.0f, skip_lod * 0.5f - 1.0f ) ) * (1.0f - upper_opacity) + upper_opacity;
skip_factor = mix( skip_factor, 1.0f, min( -1.0 + upper_opacity * probeParams.vctSpecularSdfFactor + tan_half_angle * 50.0f, 1.0f ) );
skip_lod = clamp( skip_lod + (1.0f - upper_opacity) * 2.0f - 1.0f, 1.0f, probeParams.vctSpecSdfMaxMip );
dist += half_diameter * skip_factor;
}
return color;
}
#endif
#ifndef GI_PROBE_HIGH_QUALITY
//faster version for 45 degrees
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
float lod_level = log2(radius*2.0);
while (dist < max_distance && color.a < 0.95) {
vec3 uvw_pos = (pos + dist * direction) * cell_size;
//check if outside, then break
if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + radius * cell_size)) ) ) {
break;
}
vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
vec3 aniso_neg = textureLod(sampler3D(aniso_neg,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
vec3 aniso_pos = textureLod(sampler3D(aniso_pos,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
scolor.rgb*=dot(max(vec3(0.0),(normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-normal * aniso_neg)),vec3(1.0));
lod_level+=1.0;
float a = (1.0 - color.a);
color += a * scolor;
dist += radius;
radius = max(0.5, tan_half_angle * dist);
}
return color;
}
#else
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
float lod_level = log2(radius*2.0);
while (dist < max_distance && color.a < 0.95) {
vec3 uvw_pos = (pos + dist * direction) * cell_size;
//check if outside, then break
if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + radius * cell_size)) ) ) {
break;
}
vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
lod_level+=1.0;
float a = (1.0 - color.a);
color += a * scolor;
dist += radius;
radius = max(0.5, tan_half_angle * dist);
}
return color;
}
#endif
#elif defined(GI_PROBE_USE_ANISOTROPY)
//standard voxel cone trace
vec4 voxel_cone_trace_anisotropic(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
float dist = p_bias;
vec4 color = vec4(0.0);
while (dist < max_distance && color.a < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec3 uvw_pos = (pos + dist * direction) * cell_size;
float half_diameter = diameter * 0.5;
//check if outside, then break
if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
break;
}
float log2_diameter = log2(diameter);
vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter);
vec3 aniso_neg = textureLod(sampler3D(aniso_neg,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
vec3 aniso_pos = textureLod(sampler3D(aniso_pos,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
scolor.rgb*=dot(max(vec3(0.0),(normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-normal * aniso_neg)),vec3(1.0));
float a = (1.0 - color.a);
color += a * scolor;
dist += half_diameter;
}
return color;
}
#endif
void gi_probe_compute(uint index, vec3 position, vec3 normal,vec3 ref_vec, mat3 normal_xform, float roughness,vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
position += normal * gi_probes.data[index].normal_bias;
//this causes corrupted pixels, i have no idea why..
if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
return;
}
vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
//float blend=1.0;
float max_distance = length(gi_probes.data[index].bounds);
vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
//radiance
#ifdef GI_PROBE_HIGH_QUALITY
#define MAX_CONE_DIRS 6
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
vec3(0.0, 0.0, 1.0),
vec3(0.866025, 0.0, 0.5),
vec3(0.267617, 0.823639, 0.5),
vec3(-0.700629, 0.509037, 0.5),
vec3(-0.700629, -0.509037, 0.5),
vec3(0.267617, -0.823639, 0.5));
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
float cone_angle_tan = 0.577;
#else
#define MAX_CONE_DIRS 4
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
vec3(0.707107, 0.0, 0.707107),
vec3(0.0, 0.707107, 0.707107),
vec3(-0.707107, 0.0, 0.707107),
vec3(0.0, -0.707107, 0.707107));
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25);
float cone_angle_tan = 0.98269;
#endif
vec3 light = vec3(0.0);
for (int i = 0; i < MAX_CONE_DIRS; i++) {
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
#ifdef GI_PROBE_HIGH_QUALITY
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#else
vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#endif // GI_PROBE_USE_ANISOTROPY
#else
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#else
vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#endif // GI_PROBE_USE_ANISOTROPY
#endif
if (gi_probes.data[index].blend_ambient) {
cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
}
light+=cone_weights[i] * cone_light.rgb;
}
light *= gi_probes.data[index].dynamic_range;
out_diff += vec4(light * blend, blend);
//irradiance
vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
if (gi_probes.data[index].blend_ambient) {
irr_light.rgb = mix(environment,irr_light.rgb, min(1.0, irr_light.a / 0.95));
}
irr_light.rgb *= gi_probes.data[index].dynamic_range;
//irr_light=vec3(0.0);
out_spec += vec4(irr_light.rgb * blend, blend);
}
#endif //USE_VOXEL_CONE_TRACING
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@ -1118,7 +1377,42 @@ FRAGMENT_SHADER_CODE
//lightmap capture
#ifdef USE_VOXEL_CONE_TRACING
{ // process giprobes
uint index1 = instances.data[instance_index].gi_offset&0xFFFF;
if (index1!=0xFFFF) {
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal));
vec3 bitangent = normalize(cross(tangent, normal));
mat3 normal_mat = mat3(tangent, bitangent, normal);
vec4 amb_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
gi_probe_compute(index1, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
uint index2 = instances.data[instance_index].gi_offset>>16;
if (index2!=0xFFFF) {
gi_probe_compute(index2, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
}
if (amb_accum.a > 0.0) {
amb_accum.rgb /= amb_accum.a;
}
if (spec_accum.a > 0.0) {
spec_accum.rgb /= spec_accum.a;
}
specular_light = spec_accum.rgb;
ambient_light = amb_accum.rgb;
}
}
#endif
{ // process reflections

View file

@ -9,22 +9,7 @@ layout(push_constant, binding = 0, std430) uniform DrawCall {
/* Set 0 Scene data, screen and sources (changes the least) */
layout(set=0,binding=1) uniform texture2D depth_buffer;
layout(set=0,binding=2) uniform texture2D color_buffer;
layout(set=0,binding=3) uniform texture2D normal_buffer;
layout(set=0,binding=4) uniform texture2D roughness_limit;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
layout(set = 0, binding = 5) uniform textureCubeArray radiance_cubemap;
#else
layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
#endif
/* Set 0 Scene data that never changes, ever */
#define SAMPLER_NEAREST_CLAMP 0
@ -40,11 +25,11 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
#define SAMPLER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
layout(set = 0, binding = 6) uniform sampler material_samplers[12];
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 7) uniform sampler shadow_sampler;
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
layout(set=0,binding=8,std140) uniform SceneData {
layout(set=0,binding=3,std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
@ -149,28 +134,10 @@ struct InstanceData {
};
layout(set=0,binding=9,std430) buffer Instances {
layout(set=0,binding=4,std430) buffer Instances {
InstanceData data[];
} instances;
struct ReflectionData {
vec3 box_extents;
float index;
vec3 box_offset;
uint mask;
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;
layout(set=0,binding=11) uniform textureCubeArray reflection_atlas;
struct LightData { //this structure needs to be 128 bits
vec3 position;
@ -185,11 +152,25 @@ struct LightData { //this structure needs to be 128 bits
mat4 shadow_matrix;
};
layout(set=0,binding=12,std140) uniform Lights {
layout(set=0,binding=5,std140) uniform Lights {
LightData data[MAX_LIGHT_DATA_STRUCTS];
} lights;
layout(set=0,binding=13) uniform texture2D shadow_atlas;
struct ReflectionData {
vec3 box_extents;
float index;
vec3 box_offset;
uint mask;
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=6,std140) uniform ReflectionProbeData {
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
} reflections;
struct DirectionalLightData {
@ -211,51 +192,65 @@ struct DirectionalLightData {
};
layout(set=0,binding=14,std140) uniform DirectionalLights {
layout(set=0,binding=7,std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
} directional_lights;
layout(set=0,binding=15) uniform texture2D directional_shadow_atlas;
struct GIProbeData {
mat4 xform;
vec3 bounds;
float dynamic_range;
/*
layout(set=0,binding=15,std430) buffer Skeletons {
vec4 data[];
} skeletons;
*/
float bias;
float normal_bias;
bool blend_ambient;
uint texture_slot;
/* Set 1 Instancing (Multimesh) */
float anisotropy_strength;
uint pad0;
uint pad1;
uint pad2;
};
//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
layout(set=0,binding=8,std140) uniform GIProbes {
GIProbeData data[MAX_GI_PROBES];
} gi_probes;
layout(set=1,binding=0,std430) buffer Transforms {
vec4 data[];
} transforms;
layout(set=0,binding=9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
/* Set 2 Instancing (Multimesh) data */
/* Set 1, Scene data that changes per render pass */
#if 0
layout(set=1,binding=0) uniform texture2D depth_buffer;
layout(set=1,binding=1) uniform texture2D color_buffer;
layout(set=1,binding=2) uniform texture2D normal_buffer;
layout(set=1,binding=3) uniform texture2D roughness_limit;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
layout(set = 1, binding = 4) uniform textureCubeArray radiance_cubemap;
#else
layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
layout(set = 1, binding = 4) uniform textureCube radiance_cubemap;
#endif
#ifdef USE_VOXEL_CONE_TRACING
layout(set=1,binding=5) uniform textureCubeArray reflection_atlas;
layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
layout(set=1,binding=6) uniform texture2D shadow_atlas;
#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
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
layout(set=1,binding=7) uniform texture2D directional_shadow_atlas;
/* Set 2 Skeleton & Instancing (Multimesh) */
layout(set=2,binding=0,std430) buffer Transforms {
vec4 data[];
} transforms;
/* Set 3 User Material */
#endif
#endif

View file

@ -412,7 +412,8 @@ public:
enum TextureSliceType {
TEXTURE_SLICE_2D,
TEXTURE_SLICE_CUBEMAP
TEXTURE_SLICE_CUBEMAP,
TEXTURE_SLICE_3D,
};
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0;
@ -425,6 +426,8 @@ public:
virtual bool texture_is_valid(RID p_texture) = 0;
virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false) = 0;
virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false) = 0;
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
@ -903,15 +906,13 @@ public:
enum InitialAction {
INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params)
INITIAL_ACTION_KEEP_COLOR, //start rendering, but keep attached color texture contents (depth will be cleared)
INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, //start rendering, but keep attached color and depth texture contents (depth will be cleared)
INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action prevously)
INITIAL_ACTION_MAX
};
enum FinalAction {
FINAL_ACTION_READ_COLOR_AND_DEPTH, //will no longer render to it, allows attached textures to be read again, but depth buffer contents will be dropped (Can't be read from)
FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, //will no longer render to it, allows attached textures to be read again
FINAL_ACTION_READ, //will no longer render to it, allows attached textures to be read again, but depth buffer contents will be dropped (Can't be read from)
FINAL_ACTION_DISCARD, // discard contents after rendering
FINAL_ACTION_CONTINUE, //will continue rendering later, attached textures can't be read until re-bound with "finish"
FINAL_ACTION_MAX
@ -920,8 +921,8 @@ public:
typedef int64_t DrawListID;
virtual DrawListID draw_list_begin_for_screen(int p_screen = 0, const Color &p_clear_color = Color()) = 0;
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), const Rect2 &p_region = Rect2()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), const Rect2 &p_region = Rect2()) = 0;
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0;
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
@ -930,7 +931,7 @@ public:
virtual void draw_list_set_line_width(DrawListID p_list, float p_width) = 0;
virtual void draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size) = 0;
virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1) = 0;
virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0) = 0;
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0;
virtual void draw_list_disable_scissor(DrawListID p_list) = 0;
@ -948,6 +949,8 @@ public:
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size) = 0;
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0;
virtual void compute_list_add_barrier(ComputeListID p_list) = 0;
virtual void compute_list_end() = 0;
/***************/

View file

@ -344,17 +344,20 @@ public:
BIND0R(RID, gi_probe_create)
BIND2(gi_probe_set_bounds, RID, const AABB &)
BIND7(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
BIND1RC(AABB, gi_probe_get_bounds, RID)
BIND2(gi_probe_set_cell_size, RID, float)
BIND1RC(float, gi_probe_get_cell_size, RID)
BIND2(gi_probe_set_to_cell_xform, RID, const Transform &)
BIND1RC(Vector3i, gi_probe_get_octree_size, RID)
BIND1RC(PoolVector<uint8_t>, gi_probe_get_octree_cells, RID)
BIND1RC(PoolVector<uint8_t>, gi_probe_get_data_cells, RID)
BIND1RC(PoolVector<int>, gi_probe_get_level_counts, RID)
BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
BIND2(gi_probe_set_dynamic_range, RID, int)
BIND1RC(int, gi_probe_get_dynamic_range, RID)
BIND2(gi_probe_set_dynamic_range, RID, float)
BIND1RC(float, gi_probe_get_dynamic_range, RID)
BIND2(gi_probe_set_propagation, RID, float)
BIND1RC(float, gi_probe_get_propagation, RID)
BIND2(gi_probe_set_energy, RID, float)
BIND1RC(float, gi_probe_get_energy, RID)
@ -365,17 +368,14 @@ public:
BIND2(gi_probe_set_normal_bias, RID, float)
BIND1RC(float, gi_probe_get_normal_bias, RID)
BIND2(gi_probe_set_propagation, RID, float)
BIND1RC(float, gi_probe_get_propagation, RID)
BIND2(gi_probe_set_interior, RID, bool)
BIND1RC(bool, gi_probe_is_interior, RID)
BIND2(gi_probe_set_compress, RID, bool)
BIND1RC(bool, gi_probe_is_compressed, RID)
BIND2(gi_probe_set_use_two_bounces, RID, bool)
BIND1RC(bool, gi_probe_is_using_two_bounces, RID)
BIND2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &)
BIND1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID)
BIND2(gi_probe_set_anisotropy_strength, RID, float)
BIND1RC(float, gi_probe_get_anisotropy_strength, RID)
/* LIGHTMAP CAPTURE */

File diff suppressed because it is too large Load diff

View file

@ -48,6 +48,7 @@ public:
MAX_INSTANCE_CULL = 65536,
MAX_LIGHTS_CULLED = 4096,
MAX_REFLECTION_PROBES_CULLED = 4096,
MAX_GI_PROBES_CULLED = 4096,
MAX_ROOM_CULL = 32,
MAX_EXTERIOR_PORTALS = 128,
};
@ -324,77 +325,16 @@ public:
Transform transform;
Color color;
float energy;
float bake_energy;
float radius;
float attenuation;
float spot_angle;
float spot_attenuation;
bool visible;
bool operator==(const LightCache &p_cache) {
return (type == p_cache.type &&
transform == p_cache.transform &&
color == p_cache.color &&
energy == p_cache.energy &&
radius == p_cache.radius &&
attenuation == p_cache.attenuation &&
spot_angle == p_cache.spot_angle &&
spot_attenuation == p_cache.spot_attenuation &&
visible == p_cache.visible);
}
bool operator!=(const LightCache &p_cache) {
return !operator==(p_cache);
}
LightCache() {
type = VS::LIGHT_DIRECTIONAL;
energy = 1.0;
radius = 1.0;
attenuation = 1.0;
spot_angle = 1.0;
spot_attenuation = 1.0;
visible = true;
}
bool has_shadow;
};
struct LocalData {
uint16_t pos[3];
uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights
};
struct CompBlockS3TC {
uint32_t offset; //offset in mipmap
uint32_t source_count; //sources
uint32_t sources[16]; //id for each source
uint8_t alpha[8]; //alpha block is pre-computed
};
struct Dynamic {
Map<RID, LightCache> light_cache;
Map<RID, LightCache> light_cache_changes;
PoolVector<int> light_data;
PoolVector<LocalData> local_data;
Vector<Vector<uint32_t> > level_cell_lists;
RID probe_data;
bool enabled;
int bake_dynamic_range;
RasterizerStorage::GIProbeCompression compression;
Vector<PoolVector<uint8_t> > mipmaps_3d;
Vector<PoolVector<CompBlockS3TC> > mipmaps_s3tc; //for s3tc
int updating_stage;
float propagate;
int grid_size[3];
Transform light_to_cell_xform;
} dynamic;
Vector<LightCache> light_cache;
Vector<RID> light_instances;
RID probe_instance;
@ -407,7 +347,6 @@ public:
update_element(this) {
invalid = true;
base_version = 0;
dynamic.updating_stage = GI_UPDATE_STAGE_CHECK;
}
};
@ -436,6 +375,8 @@ public:
int directional_light_count;
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
int reflection_probe_cull_count;
RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
int gi_probe_cull_count;
RID_PtrOwner<Instance> instance_owner;
@ -477,6 +418,7 @@ public:
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
@ -485,52 +427,6 @@ public:
void render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
void update_dirty_instances();
//probes
struct GIProbeDataHeader {
uint32_t version;
uint32_t cell_subdiv;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t cell_count;
uint32_t leaf_cell_count;
};
struct GIProbeDataCell {
uint32_t children[8];
uint32_t albedo;
uint32_t emission;
uint32_t normal;
uint32_t level_alpha;
};
enum {
GI_UPDATE_STAGE_CHECK,
GI_UPDATE_STAGE_LIGHTING,
GI_UPDATE_STAGE_UPLOADING,
};
void _gi_probe_bake_thread();
static void _gi_probe_bake_threads(void *);
volatile bool probe_bake_thread_exit;
Thread *probe_bake_thread;
SemaphoreOld *probe_bake_sem;
Mutex *probe_bake_mutex;
List<Instance *> probe_bake_list;
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
void _gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell *p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell);
_FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells, int x, int y, int z, int p_cell_subdiv);
void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell *p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate);
void _bake_gi_probe_light(const GIProbeDataHeader *header, const GIProbeDataCell *cells, InstanceGIProbeData::LocalData *local_data, const uint32_t *leaves, int p_leaf_count, const InstanceGIProbeData::LightCache &light_cache, int p_sign);
void _bake_gi_probe(Instance *p_gi_probe);
bool _check_gi_probe(Instance *p_gi_probe);
void _setup_gi_probe(Instance *p_instance);
void render_probes();
bool free(RID p_rid);

View file

@ -268,17 +268,20 @@ public:
FUNCRID(gi_probe)
FUNC2(gi_probe_set_bounds, RID, const AABB &)
FUNC7(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
FUNC1RC(AABB, gi_probe_get_bounds, RID)
FUNC2(gi_probe_set_cell_size, RID, float)
FUNC1RC(float, gi_probe_get_cell_size, RID)
FUNC2(gi_probe_set_to_cell_xform, RID, const Transform &)
FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
FUNC1RC(PoolVector<uint8_t>, gi_probe_get_octree_cells, RID)
FUNC1RC(PoolVector<uint8_t>, gi_probe_get_data_cells, RID)
FUNC1RC(PoolVector<int>, gi_probe_get_level_counts, RID)
FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
FUNC2(gi_probe_set_dynamic_range, RID, int)
FUNC1RC(int, gi_probe_get_dynamic_range, RID)
FUNC2(gi_probe_set_dynamic_range, RID, float)
FUNC1RC(float, gi_probe_get_dynamic_range, RID)
FUNC2(gi_probe_set_propagation, RID, float)
FUNC1RC(float, gi_probe_get_propagation, RID)
FUNC2(gi_probe_set_energy, RID, float)
FUNC1RC(float, gi_probe_get_energy, RID)
@ -289,17 +292,14 @@ public:
FUNC2(gi_probe_set_normal_bias, RID, float)
FUNC1RC(float, gi_probe_get_normal_bias, RID)
FUNC2(gi_probe_set_propagation, RID, float)
FUNC1RC(float, gi_probe_get_propagation, RID)
FUNC2(gi_probe_set_interior, RID, bool)
FUNC1RC(bool, gi_probe_is_interior, RID)
FUNC2(gi_probe_set_compress, RID, bool)
FUNC1RC(bool, gi_probe_is_compressed, RID)
FUNC2(gi_probe_set_use_two_bounces, RID, bool)
FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
FUNC2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &)
FUNC1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID)
FUNC2(gi_probe_set_anisotropy_strength, RID, float)
FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
/* LIGHTMAP CAPTURE */

View file

@ -1710,6 +1710,10 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &VisualServer::reflection_probe_set_enable_shadows);
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &VisualServer::reflection_probe_set_cull_mask);
#ifndef _MSC_VER
#warning TODO all giprobe methods need re-binding
#endif
#if 0
ClassDB::bind_method(D_METHOD("gi_probe_create"), &VisualServer::gi_probe_create);
ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &VisualServer::gi_probe_set_bounds);
ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &VisualServer::gi_probe_get_bounds);
@ -1733,6 +1737,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &VisualServer::gi_probe_is_interior);
ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &VisualServer::gi_probe_set_compress);
ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &VisualServer::gi_probe_is_compressed);
#endif
ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &VisualServer::lightmap_capture_create);
ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &VisualServer::lightmap_capture_set_bounds);
@ -2297,6 +2302,9 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128);
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64);
GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false);
GLOBAL_DEF("rendering/quality/gi_probes/high_quality", false);
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);
GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley", false);

View file

@ -465,38 +465,38 @@ public:
virtual RID gi_probe_create() = 0;
virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) = 0;
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
virtual PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0;
virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0;
virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) = 0;
virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const = 0;
virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0;
virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0;
virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0;
virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_energy(RID p_probe) const = 0;
virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;
virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_bias(RID p_probe) const = 0;
virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0;
virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0;
virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_normal_bias(RID p_probe) const = 0;
virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0;
virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0;
virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_propagation(RID p_probe) const = 0;
virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0;
virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0;
virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0;
virtual bool gi_probe_is_interior(RID p_probe) const = 0;
virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0;
virtual bool gi_probe_is_compressed(RID p_probe) const = 0;
virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0;
virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0;
/* LIGHTMAP CAPTURE */
@ -650,7 +650,10 @@ public:
VIEWPORT_DEBUG_DRAW_LIGHTING,
VIEWPORT_DEBUG_DRAW_OVERDRAW,
VIEWPORT_DEBUG_DRAW_WIREFRAME,
VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS
VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO,
VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING,
VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS,
VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
};