GIProbes working.
This commit is contained in:
parent
52f96abd8b
commit
acf0f6c8a7
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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 "";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 : ");
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
{
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/***************/
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue