Implement decals
Also implemented decal atlas, so projectors and other stuff can be added. Sidenote: Had to make RID hashable, so some unrelated includes changed in order to include it in hashfuncs.h
This commit is contained in:
parent
451d5bd492
commit
5944eb6e7f
|
@ -34,6 +34,7 @@
|
||||||
#include "core/callable.h"
|
#include "core/callable.h"
|
||||||
#include "core/hashfuncs.h"
|
#include "core/hashfuncs.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
|
#include "core/os/copymem.h"
|
||||||
#include "core/simple_type.h"
|
#include "core/simple_type.h"
|
||||||
|
|
||||||
class CallableCustomMethodPointerBase : public CallableCustom {
|
class CallableCustomMethodPointerBase : public CallableCustom {
|
||||||
|
|
|
@ -35,10 +35,10 @@
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
#include "core/node_path.h"
|
#include "core/node_path.h"
|
||||||
#include "core/object_id.h"
|
#include "core/object_id.h"
|
||||||
|
#include "core/rid.h"
|
||||||
#include "core/string_name.h"
|
#include "core/string_name.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
#include "core/ustring.h"
|
#include "core/ustring.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashing functions
|
* Hashing functions
|
||||||
*/
|
*/
|
||||||
|
@ -150,6 +150,7 @@ struct HashMapHasherDefault {
|
||||||
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
|
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
|
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
|
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
|
||||||
|
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
|
||||||
|
|
||||||
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
|
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
|
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
|
||||||
|
|
|
@ -31,11 +31,6 @@
|
||||||
#ifndef RID_H
|
#ifndef RID_H
|
||||||
#define RID_H
|
#define RID_H
|
||||||
|
|
||||||
#include "core/list.h"
|
|
||||||
#include "core/oa_hash_map.h"
|
|
||||||
#include "core/os/memory.h"
|
|
||||||
#include "core/safe_refcount.h"
|
|
||||||
#include "core/set.h"
|
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
class RID_AllocBase;
|
class RID_AllocBase;
|
||||||
|
|
|
@ -31,8 +31,13 @@
|
||||||
#ifndef RID_OWNER_H
|
#ifndef RID_OWNER_H
|
||||||
#define RID_OWNER_H
|
#define RID_OWNER_H
|
||||||
|
|
||||||
|
#include "core/list.h"
|
||||||
|
#include "core/oa_hash_map.h"
|
||||||
|
#include "core/os/memory.h"
|
||||||
#include "core/print_string.h"
|
#include "core/print_string.h"
|
||||||
#include "core/rid.h"
|
#include "core/rid.h"
|
||||||
|
#include "core/safe_refcount.h"
|
||||||
|
#include "core/set.h"
|
||||||
#include "core/spin_lock.h"
|
#include "core/spin_lock.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
|
@ -2851,8 +2851,8 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
|
||||||
src_layer_count *= 6;
|
src_layer_count *= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V(src_tex->base_mipmap + p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
|
||||||
ERR_FAIL_COND_V(src_tex->base_layer + p_base_layer + p_layers > src_layer_count, 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;
|
VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
|
||||||
|
|
||||||
|
@ -2888,9 +2888,9 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
|
||||||
|
|
||||||
VkImageSubresourceRange range;
|
VkImageSubresourceRange range;
|
||||||
range.aspectMask = src_tex->read_aspect_mask;
|
range.aspectMask = src_tex->read_aspect_mask;
|
||||||
range.baseArrayLayer = p_base_layer;
|
range.baseArrayLayer = src_tex->base_layer + p_base_layer;
|
||||||
range.layerCount = p_layers;
|
range.layerCount = p_layers;
|
||||||
range.baseMipLevel = p_base_mipmap;
|
range.baseMipLevel = src_tex->base_mipmap + p_base_mipmap;
|
||||||
range.levelCount = p_mipmaps;
|
range.levelCount = p_mipmaps;
|
||||||
|
|
||||||
vkCmdClearColorImage(command_buffer, src_tex->image, layout, &clear_color, 1, &range);
|
vkCmdClearColorImage(command_buffer, src_tex->image, layout, &clear_color, 1, &range);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "scene/3d/collision_polygon_3d.h"
|
#include "scene/3d/collision_polygon_3d.h"
|
||||||
#include "scene/3d/collision_shape_3d.h"
|
#include "scene/3d/collision_shape_3d.h"
|
||||||
#include "scene/3d/cpu_particles_3d.h"
|
#include "scene/3d/cpu_particles_3d.h"
|
||||||
|
#include "scene/3d/decal.h"
|
||||||
#include "scene/3d/gi_probe.h"
|
#include "scene/3d/gi_probe.h"
|
||||||
#include "scene/3d/gpu_particles_3d.h"
|
#include "scene/3d/gpu_particles_3d.h"
|
||||||
#include "scene/3d/light_3d.h"
|
#include "scene/3d/light_3d.h"
|
||||||
|
@ -2718,7 +2719,143 @@ void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||||
p_gizmo->add_unscaled_billboard(icon, 0.05);
|
p_gizmo->add_unscaled_billboard(icon, 0.05);
|
||||||
p_gizmo->add_handles(handles, get_material("handles"));
|
p_gizmo->add_handles(handles, get_material("handles"));
|
||||||
}
|
}
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
DecalGizmoPlugin::DecalGizmoPlugin() {
|
||||||
|
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/decal", Color(0.6, 0.5, 1.0));
|
||||||
|
|
||||||
|
create_material("decal_material", gizmo_color);
|
||||||
|
|
||||||
|
create_handle_material("handles");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecalGizmoPlugin::has_gizmo(Node3D *p_spatial) {
|
||||||
|
return Object::cast_to<Decal>(p_spatial) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
String DecalGizmoPlugin::get_name() const {
|
||||||
|
return "Decal";
|
||||||
|
}
|
||||||
|
|
||||||
|
int DecalGizmoPlugin::get_priority() const {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
|
||||||
|
|
||||||
|
switch (p_idx) {
|
||||||
|
case 0: return "Extents X";
|
||||||
|
case 1: return "Extents Y";
|
||||||
|
case 2: return "Extents Z";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
Variant DecalGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
|
||||||
|
|
||||||
|
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
|
||||||
|
return decal->get_extents();
|
||||||
|
}
|
||||||
|
void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
|
||||||
|
|
||||||
|
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
|
||||||
|
Transform gt = decal->get_global_transform();
|
||||||
|
|
||||||
|
Transform gi = gt.affine_inverse();
|
||||||
|
|
||||||
|
Vector3 extents = decal->get_extents();
|
||||||
|
|
||||||
|
Vector3 ray_from = p_camera->project_ray_origin(p_point);
|
||||||
|
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
|
||||||
|
|
||||||
|
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
|
||||||
|
|
||||||
|
Vector3 axis;
|
||||||
|
axis[p_idx] = 1.0;
|
||||||
|
|
||||||
|
Vector3 ra, rb;
|
||||||
|
Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
|
||||||
|
float d = ra[p_idx];
|
||||||
|
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
|
||||||
|
d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d < 0.001)
|
||||||
|
d = 0.001;
|
||||||
|
|
||||||
|
extents[p_idx] = d;
|
||||||
|
decal->set_extents(extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecalGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
|
||||||
|
|
||||||
|
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
|
||||||
|
|
||||||
|
Vector3 restore = p_restore;
|
||||||
|
|
||||||
|
if (p_cancel) {
|
||||||
|
decal->set_extents(restore);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
|
||||||
|
ur->create_action(TTR("Change Decal Extents"));
|
||||||
|
ur->add_do_method(decal, "set_extents", decal->get_extents());
|
||||||
|
ur->add_undo_method(decal, "set_extents", restore);
|
||||||
|
ur->commit_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||||
|
|
||||||
|
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
|
||||||
|
|
||||||
|
p_gizmo->clear();
|
||||||
|
|
||||||
|
Vector<Vector3> lines;
|
||||||
|
Vector3 extents = decal->get_extents();
|
||||||
|
|
||||||
|
AABB aabb;
|
||||||
|
aabb.position = -extents;
|
||||||
|
aabb.size = extents * 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
Vector3 a, b;
|
||||||
|
aabb.get_edge(i, a, b);
|
||||||
|
if (a.y == b.y) {
|
||||||
|
lines.push_back(a);
|
||||||
|
lines.push_back(b);
|
||||||
|
} else {
|
||||||
|
Vector3 ah = a.linear_interpolate(b, 0.2);
|
||||||
|
lines.push_back(a);
|
||||||
|
lines.push_back(ah);
|
||||||
|
Vector3 bh = b.linear_interpolate(a, 0.2);
|
||||||
|
lines.push_back(b);
|
||||||
|
lines.push_back(bh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push_back(Vector3(0, extents.y, 0));
|
||||||
|
lines.push_back(Vector3(0, extents.y * 1.2, 0));
|
||||||
|
|
||||||
|
Vector<Vector3> handles;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
|
||||||
|
Vector3 ax;
|
||||||
|
ax[i] = aabb.position[i] + aabb.size[i];
|
||||||
|
handles.push_back(ax);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Material> material = get_material("decal_material", p_gizmo);
|
||||||
|
|
||||||
|
p_gizmo->add_lines(lines, material);
|
||||||
|
|
||||||
|
p_gizmo->add_handles(handles, get_material("handles"));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
GIProbeGizmoPlugin::GIProbeGizmoPlugin() {
|
GIProbeGizmoPlugin::GIProbeGizmoPlugin() {
|
||||||
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6));
|
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6));
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,24 @@ public:
|
||||||
ReflectionProbeGizmoPlugin();
|
ReflectionProbeGizmoPlugin();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DecalGizmoPlugin : public EditorNode3DGizmoPlugin {
|
||||||
|
|
||||||
|
GDCLASS(DecalGizmoPlugin, EditorNode3DGizmoPlugin);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool has_gizmo(Node3D *p_spatial);
|
||||||
|
String get_name() const;
|
||||||
|
int get_priority() const;
|
||||||
|
void redraw(EditorNode3DGizmo *p_gizmo);
|
||||||
|
|
||||||
|
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const;
|
||||||
|
Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const;
|
||||||
|
void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point);
|
||||||
|
void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false);
|
||||||
|
|
||||||
|
DecalGizmoPlugin();
|
||||||
|
};
|
||||||
|
|
||||||
class GIProbeGizmoPlugin : public EditorNode3DGizmoPlugin {
|
class GIProbeGizmoPlugin : public EditorNode3DGizmoPlugin {
|
||||||
|
|
||||||
GDCLASS(GIProbeGizmoPlugin, EditorNode3DGizmoPlugin);
|
GDCLASS(GIProbeGizmoPlugin, EditorNode3DGizmoPlugin);
|
||||||
|
|
|
@ -3034,6 +3034,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
||||||
case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE:
|
case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE:
|
||||||
case VIEW_DISPLAY_DEBUG_SSAO:
|
case VIEW_DISPLAY_DEBUG_SSAO:
|
||||||
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS:
|
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS:
|
||||||
|
case VIEW_DISPLAY_DEBUG_DECAL_ATLAS:
|
||||||
case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: {
|
case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: {
|
||||||
|
|
||||||
static const int display_options[] = {
|
static const int display_options[] = {
|
||||||
|
@ -3053,6 +3054,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
||||||
VIEW_DISPLAY_DEBUG_SSAO,
|
VIEW_DISPLAY_DEBUG_SSAO,
|
||||||
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
||||||
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
||||||
|
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
|
||||||
VIEW_MAX
|
VIEW_MAX
|
||||||
};
|
};
|
||||||
static const Viewport::DebugDraw debug_draw_modes[] = {
|
static const Viewport::DebugDraw debug_draw_modes[] = {
|
||||||
|
@ -3072,6 +3074,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
||||||
Viewport::DEBUG_DRAW_SSAO,
|
Viewport::DEBUG_DRAW_SSAO,
|
||||||
Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER,
|
Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||||
Viewport::DEBUG_DRAW_PSSM_SPLITS,
|
Viewport::DEBUG_DRAW_PSSM_SPLITS,
|
||||||
|
Viewport::DEBUG_DRAW_DECAL_ATLAS,
|
||||||
};
|
};
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
@ -3933,6 +3936,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
|
||||||
display_submenu->add_radio_check_item(TTR("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS);
|
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_radio_check_item(TTR("Directional Shadow"), VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS);
|
||||||
display_submenu->add_separator();
|
display_submenu->add_separator();
|
||||||
|
display_submenu->add_radio_check_item(TTR("Decal Atlas"), VIEW_DISPLAY_DEBUG_DECAL_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 Lighting"), VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING);
|
||||||
display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO);
|
display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO);
|
||||||
display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION);
|
display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION);
|
||||||
|
@ -5963,6 +5968,7 @@ void Node3DEditor::_register_all_gizmos() {
|
||||||
add_gizmo_plugin(Ref<GPUParticles3DGizmoPlugin>(memnew(GPUParticles3DGizmoPlugin)));
|
add_gizmo_plugin(Ref<GPUParticles3DGizmoPlugin>(memnew(GPUParticles3DGizmoPlugin)));
|
||||||
add_gizmo_plugin(Ref<CPUParticles3DGizmoPlugin>(memnew(CPUParticles3DGizmoPlugin)));
|
add_gizmo_plugin(Ref<CPUParticles3DGizmoPlugin>(memnew(CPUParticles3DGizmoPlugin)));
|
||||||
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
|
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
|
||||||
|
add_gizmo_plugin(Ref<DecalGizmoPlugin>(memnew(DecalGizmoPlugin)));
|
||||||
add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
|
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<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
|
add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
|
||||||
|
|
|
@ -219,6 +219,7 @@ class Node3DEditorViewport : public Control {
|
||||||
VIEW_DISPLAY_DEBUG_SSAO,
|
VIEW_DISPLAY_DEBUG_SSAO,
|
||||||
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
|
||||||
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
||||||
|
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
|
||||||
VIEW_LOCK_ROTATION,
|
VIEW_LOCK_ROTATION,
|
||||||
VIEW_CINEMATIC_PREVIEW,
|
VIEW_CINEMATIC_PREVIEW,
|
||||||
VIEW_AUTO_ORTHOGONAL,
|
VIEW_AUTO_ORTHOGONAL,
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define GDSCRIPT_TOKENIZER_H
|
#define GDSCRIPT_TOKENIZER_H
|
||||||
|
|
||||||
#include "core/pair.h"
|
#include "core/pair.h"
|
||||||
|
#include "core/set.h"
|
||||||
#include "core/string_name.h"
|
#include "core/string_name.h"
|
||||||
#include "core/ustring.h"
|
#include "core/ustring.h"
|
||||||
#include "core/variant.h"
|
#include "core/variant.h"
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* decal.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "decal.h"
|
||||||
|
|
||||||
|
void Decal::set_extents(const Vector3 &p_extents) {
|
||||||
|
extents = p_extents;
|
||||||
|
RS::get_singleton()->decal_set_extents(decal, p_extents);
|
||||||
|
update_gizmo();
|
||||||
|
_change_notify("extents");
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Decal::get_extents() const {
|
||||||
|
return extents;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) {
|
||||||
|
ERR_FAIL_INDEX(p_type, TEXTURE_MAX);
|
||||||
|
textures[p_type] = p_texture;
|
||||||
|
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||||
|
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
|
||||||
|
}
|
||||||
|
Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
|
||||||
|
ERR_FAIL_INDEX_V(p_type, TEXTURE_MAX, Ref<Texture2D>());
|
||||||
|
return textures[p_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_emission_energy(float p_energy) {
|
||||||
|
emission_energy = p_energy;
|
||||||
|
RS::get_singleton()->decal_set_emission_energy(decal, emission_energy);
|
||||||
|
}
|
||||||
|
float Decal::get_emission_energy() const {
|
||||||
|
return emission_energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_albedo_mix(float p_energy) {
|
||||||
|
albedo_mix = p_energy;
|
||||||
|
RS::get_singleton()->decal_set_albedo_mix(decal, albedo_mix);
|
||||||
|
}
|
||||||
|
float Decal::get_albedo_mix() const {
|
||||||
|
return albedo_mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_upper_fade(float p_energy) {
|
||||||
|
upper_fade = p_energy;
|
||||||
|
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
|
||||||
|
}
|
||||||
|
float Decal::get_upper_fade() const {
|
||||||
|
return upper_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_lower_fade(float p_energy) {
|
||||||
|
lower_fade = p_energy;
|
||||||
|
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
|
||||||
|
}
|
||||||
|
float Decal::get_lower_fade() const {
|
||||||
|
return lower_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_normal_fade(float p_fade) {
|
||||||
|
normal_fade = p_fade;
|
||||||
|
RS::get_singleton()->decal_set_normal_fade(decal, normal_fade);
|
||||||
|
}
|
||||||
|
float Decal::get_normal_fade() const {
|
||||||
|
return normal_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_modulate(Color p_modulate) {
|
||||||
|
modulate = p_modulate;
|
||||||
|
RS::get_singleton()->decal_set_modulate(decal, p_modulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Decal::get_modulate() const {
|
||||||
|
return modulate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_enable_distance_fade(bool p_enable) {
|
||||||
|
distance_fade_enabled = p_enable;
|
||||||
|
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
|
||||||
|
}
|
||||||
|
bool Decal::is_distance_fade_enabled() const {
|
||||||
|
return distance_fade_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_distance_fade_begin(float p_distance) {
|
||||||
|
distance_fade_begin = p_distance;
|
||||||
|
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
|
||||||
|
}
|
||||||
|
float Decal::get_distance_fade_begin() const {
|
||||||
|
return distance_fade_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_distance_fade_length(float p_length) {
|
||||||
|
distance_fade_length = p_length;
|
||||||
|
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
|
||||||
|
}
|
||||||
|
float Decal::get_distance_fade_length() const {
|
||||||
|
return distance_fade_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::set_cull_mask(uint32_t p_layers) {
|
||||||
|
cull_mask = p_layers;
|
||||||
|
RS::get_singleton()->decal_set_cull_mask(decal, cull_mask);
|
||||||
|
}
|
||||||
|
uint32_t Decal::get_cull_mask() const {
|
||||||
|
return cull_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB Decal::get_aabb() const {
|
||||||
|
|
||||||
|
AABB aabb;
|
||||||
|
aabb.position = -extents;
|
||||||
|
aabb.size = extents * 2.0;
|
||||||
|
return aabb;
|
||||||
|
}
|
||||||
|
Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
|
||||||
|
|
||||||
|
return Vector<Face3>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decal::_bind_methods() {
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_texture", "type", "texture"), &Decal::set_texture);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_texture", "type"), &Decal::get_texture);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_emission_energy", "energy"), &Decal::set_emission_energy);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_emission_energy"), &Decal::get_emission_energy);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_albedo_mix", "energy"), &Decal::set_albedo_mix);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_albedo_mix"), &Decal::get_albedo_mix);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_modulate", "color"), &Decal::set_modulate);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_modulate"), &Decal::get_modulate);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_upper_fade", "fade"), &Decal::set_upper_fade);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_upper_fade"), &Decal::get_upper_fade);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_lower_fade", "fade"), &Decal::set_lower_fade);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_lower_fade"), &Decal::get_lower_fade);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_normal_fade", "fade"), &Decal::set_normal_fade);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_normal_fade"), &Decal::get_normal_fade);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_enable_distance_fade", "enable"), &Decal::set_enable_distance_fade);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &Decal::is_distance_fade_enabled);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_distance_fade_begin", "distance"), &Decal::set_distance_fade_begin);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_distance_fade_begin"), &Decal::get_distance_fade_begin);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_distance_fade_length", "distance"), &Decal::set_distance_fade_length);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_distance_fade_length"), &Decal::get_distance_fade_length);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Decal::set_cull_mask);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater"), "set_extents", "get_extents");
|
||||||
|
ADD_GROUP("Textures", "texture_");
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ORM);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION);
|
||||||
|
ADD_GROUP("Parameters", "");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_normal_fade", "get_normal_fade");
|
||||||
|
ADD_GROUP("Vertical Fade", "");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
|
||||||
|
ADD_GROUP("Distance Fade", "distance_fade_");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin"), "set_distance_fade_begin", "get_distance_fade_begin");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length"), "set_distance_fade_length", "get_distance_fade_length");
|
||||||
|
ADD_GROUP("Cull Mask", "");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||||
|
|
||||||
|
BIND_CONSTANT(TEXTURE_ALBEDO);
|
||||||
|
BIND_CONSTANT(TEXTURE_NORMAL);
|
||||||
|
BIND_CONSTANT(TEXTURE_ORM);
|
||||||
|
BIND_CONSTANT(TEXTURE_EMISSION);
|
||||||
|
BIND_CONSTANT(TEXTURE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
Decal::Decal() {
|
||||||
|
|
||||||
|
extents = Vector3(1, 1, 1);
|
||||||
|
emission_energy = 1.0;
|
||||||
|
modulate = Color(1, 1, 1, 1);
|
||||||
|
albedo_mix = 1.0;
|
||||||
|
cull_mask = (1 << 20) - 1;
|
||||||
|
upper_fade = 0.3;
|
||||||
|
lower_fade = 0.3;
|
||||||
|
normal_fade = 0;
|
||||||
|
distance_fade_enabled = false;
|
||||||
|
distance_fade_begin = 10;
|
||||||
|
distance_fade_length = 1;
|
||||||
|
|
||||||
|
decal = RenderingServer::get_singleton()->decal_create();
|
||||||
|
RS::get_singleton()->instance_set_base(get_instance(), decal);
|
||||||
|
}
|
||||||
|
|
||||||
|
Decal::~Decal() {
|
||||||
|
|
||||||
|
RS::get_singleton()->free(decal);
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* decal.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DECAL_H
|
||||||
|
#define DECAL_H
|
||||||
|
|
||||||
|
#include "scene/3d/visual_instance_3d.h"
|
||||||
|
#include "scene/resources/texture.h"
|
||||||
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
|
class Decal : public VisualInstance3D {
|
||||||
|
GDCLASS(Decal, VisualInstance3D);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum DecalTexture {
|
||||||
|
TEXTURE_ALBEDO,
|
||||||
|
TEXTURE_NORMAL,
|
||||||
|
TEXTURE_ORM,
|
||||||
|
TEXTURE_EMISSION,
|
||||||
|
TEXTURE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
RID decal;
|
||||||
|
Vector3 extents;
|
||||||
|
Ref<Texture2D> textures[TEXTURE_MAX];
|
||||||
|
float emission_energy;
|
||||||
|
float albedo_mix;
|
||||||
|
Color modulate;
|
||||||
|
uint32_t cull_mask;
|
||||||
|
float normal_fade;
|
||||||
|
float upper_fade;
|
||||||
|
float lower_fade;
|
||||||
|
bool distance_fade_enabled;
|
||||||
|
float distance_fade_begin;
|
||||||
|
float distance_fade_length;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_extents(const Vector3 &p_extents);
|
||||||
|
Vector3 get_extents() const;
|
||||||
|
|
||||||
|
void set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture);
|
||||||
|
Ref<Texture2D> get_texture(DecalTexture p_type) const;
|
||||||
|
|
||||||
|
void set_emission_energy(float p_energy);
|
||||||
|
float get_emission_energy() const;
|
||||||
|
|
||||||
|
void set_albedo_mix(float p_energy);
|
||||||
|
float get_albedo_mix() const;
|
||||||
|
|
||||||
|
void set_modulate(Color p_modulate);
|
||||||
|
Color get_modulate() const;
|
||||||
|
|
||||||
|
void set_upper_fade(float p_energy);
|
||||||
|
float get_upper_fade() const;
|
||||||
|
|
||||||
|
void set_lower_fade(float p_energy);
|
||||||
|
float get_lower_fade() const;
|
||||||
|
|
||||||
|
void set_normal_fade(float p_energy);
|
||||||
|
float get_normal_fade() const;
|
||||||
|
|
||||||
|
void set_enable_distance_fade(bool p_enable);
|
||||||
|
bool is_distance_fade_enabled() const;
|
||||||
|
|
||||||
|
void set_distance_fade_begin(float p_distance);
|
||||||
|
float get_distance_fade_begin() const;
|
||||||
|
|
||||||
|
void set_distance_fade_length(float p_length);
|
||||||
|
float get_distance_fade_length() const;
|
||||||
|
|
||||||
|
void set_cull_mask(uint32_t p_layers);
|
||||||
|
uint32_t get_cull_mask() const;
|
||||||
|
|
||||||
|
virtual AABB get_aabb() const;
|
||||||
|
virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||||
|
|
||||||
|
Decal();
|
||||||
|
~Decal();
|
||||||
|
};
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(Decal::DecalTexture);
|
||||||
|
|
||||||
|
#endif // DECAL_H
|
|
@ -3517,6 +3517,7 @@ void Viewport::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO);
|
BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO);
|
||||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_ROUGHNESS_LIMITER);
|
BIND_ENUM_CONSTANT(DEBUG_DRAW_ROUGHNESS_LIMITER);
|
||||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_PSSM_SPLITS);
|
BIND_ENUM_CONSTANT(DEBUG_DRAW_PSSM_SPLITS);
|
||||||
|
BIND_ENUM_CONSTANT(DEBUG_DRAW_DECAL_ATLAS);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(MSAA_DISABLED);
|
BIND_ENUM_CONSTANT(MSAA_DISABLED);
|
||||||
BIND_ENUM_CONSTANT(MSAA_2X);
|
BIND_ENUM_CONSTANT(MSAA_2X);
|
||||||
|
|
|
@ -141,7 +141,8 @@ public:
|
||||||
DEBUG_DRAW_SCENE_LUMINANCE,
|
DEBUG_DRAW_SCENE_LUMINANCE,
|
||||||
DEBUG_DRAW_SSAO,
|
DEBUG_DRAW_SSAO,
|
||||||
DEBUG_DRAW_ROUGHNESS_LIMITER,
|
DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||||
DEBUG_DRAW_PSSM_SPLITS
|
DEBUG_DRAW_PSSM_SPLITS,
|
||||||
|
DEBUG_DRAW_DECAL_ATLAS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DefaultCanvasItemTextureFilter {
|
enum DefaultCanvasItemTextureFilter {
|
||||||
|
|
|
@ -186,6 +186,7 @@
|
||||||
#include "scene/3d/collision_polygon_3d.h"
|
#include "scene/3d/collision_polygon_3d.h"
|
||||||
#include "scene/3d/collision_shape_3d.h"
|
#include "scene/3d/collision_shape_3d.h"
|
||||||
#include "scene/3d/cpu_particles_3d.h"
|
#include "scene/3d/cpu_particles_3d.h"
|
||||||
|
#include "scene/3d/decal.h"
|
||||||
#include "scene/3d/gi_probe.h"
|
#include "scene/3d/gi_probe.h"
|
||||||
#include "scene/3d/gpu_particles_3d.h"
|
#include "scene/3d/gpu_particles_3d.h"
|
||||||
#include "scene/3d/immediate_geometry_3d.h"
|
#include "scene/3d/immediate_geometry_3d.h"
|
||||||
|
@ -424,6 +425,7 @@ void register_scene_types() {
|
||||||
ClassDB::register_class<OmniLight3D>();
|
ClassDB::register_class<OmniLight3D>();
|
||||||
ClassDB::register_class<SpotLight3D>();
|
ClassDB::register_class<SpotLight3D>();
|
||||||
ClassDB::register_class<ReflectionProbe>();
|
ClassDB::register_class<ReflectionProbe>();
|
||||||
|
ClassDB::register_class<Decal>();
|
||||||
ClassDB::register_class<GIProbe>();
|
ClassDB::register_class<GIProbe>();
|
||||||
ClassDB::register_class<GIProbeData>();
|
ClassDB::register_class<GIProbeData>();
|
||||||
//ClassDB::register_class<BakedLightmap>();
|
//ClassDB::register_class<BakedLightmap>();
|
||||||
|
|
|
@ -248,12 +248,15 @@ public:
|
||||||
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
|
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 bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
|
||||||
|
|
||||||
|
virtual RID decal_instance_create(RID p_decal) = 0;
|
||||||
|
virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
|
||||||
|
|
||||||
virtual RID gi_probe_instance_create(RID p_gi_probe) = 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_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
|
||||||
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
|
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
|
||||||
virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
|
virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
|
||||||
|
|
||||||
virtual void 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_camera_effects, 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_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||||
|
|
||||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||||
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||||
|
@ -323,6 +326,9 @@ public:
|
||||||
|
|
||||||
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
|
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
|
||||||
|
|
||||||
|
virtual void texture_add_to_decal_atlas(RID p_texture) = 0;
|
||||||
|
virtual void texture_remove_from_decal_atlas(RID p_texture) = 0;
|
||||||
|
|
||||||
/* SHADER API */
|
/* SHADER API */
|
||||||
|
|
||||||
virtual RID shader_create() = 0;
|
virtual RID shader_create() = 0;
|
||||||
|
@ -503,6 +509,21 @@ public:
|
||||||
virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
||||||
virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
||||||
|
|
||||||
|
/* DECAL API */
|
||||||
|
|
||||||
|
virtual RID decal_create() = 0;
|
||||||
|
virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
|
||||||
|
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
|
||||||
|
virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
|
||||||
|
virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
|
||||||
|
virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
|
||||||
|
virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
|
||||||
|
virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
|
||||||
|
virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
|
||||||
|
virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
|
||||||
|
|
||||||
|
virtual AABB decal_get_aabb(RID p_decal) const = 0;
|
||||||
|
|
||||||
/* GI PROBE API */
|
/* GI PROBE API */
|
||||||
|
|
||||||
virtual RID gi_probe_create() = 0;
|
virtual RID gi_probe_create() = 0;
|
||||||
|
|
|
@ -39,6 +39,7 @@ void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraM
|
||||||
//reset counts
|
//reset counts
|
||||||
light_count = 0;
|
light_count = 0;
|
||||||
refprobe_count = 0;
|
refprobe_count = 0;
|
||||||
|
decal_count = 0;
|
||||||
item_count = 0;
|
item_count = 0;
|
||||||
sort_id_count = 0;
|
sort_id_count = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,23 +193,25 @@ public:
|
||||||
refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
|
refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform xform = view_xform * p_transform;
|
||||||
|
|
||||||
OrientedBoxData &rp = refprobes[refprobe_count];
|
OrientedBoxData &rp = refprobes[refprobe_count];
|
||||||
Vector3 origin = p_transform.origin;
|
Vector3 origin = xform.origin;
|
||||||
rp.position[0] = origin.x;
|
rp.position[0] = origin.x;
|
||||||
rp.position[1] = origin.y;
|
rp.position[1] = origin.y;
|
||||||
rp.position[2] = origin.z;
|
rp.position[2] = origin.z;
|
||||||
|
|
||||||
Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
|
Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
|
||||||
rp.x_axis[0] = x_axis.x;
|
rp.x_axis[0] = x_axis.x;
|
||||||
rp.x_axis[1] = x_axis.y;
|
rp.x_axis[1] = x_axis.y;
|
||||||
rp.x_axis[2] = x_axis.z;
|
rp.x_axis[2] = x_axis.z;
|
||||||
|
|
||||||
Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
|
Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
|
||||||
rp.y_axis[0] = y_axis.x;
|
rp.y_axis[0] = y_axis.x;
|
||||||
rp.y_axis[1] = y_axis.y;
|
rp.y_axis[1] = y_axis.y;
|
||||||
rp.y_axis[2] = y_axis.z;
|
rp.y_axis[2] = y_axis.z;
|
||||||
|
|
||||||
Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z;
|
Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
|
||||||
rp.z_axis[0] = z_axis.x;
|
rp.z_axis[0] = z_axis.x;
|
||||||
rp.z_axis[1] = z_axis.y;
|
rp.z_axis[1] = z_axis.y;
|
||||||
rp.z_axis[2] = z_axis.z;
|
rp.z_axis[2] = z_axis.z;
|
||||||
|
@ -230,35 +232,37 @@ public:
|
||||||
refprobe_count++;
|
refprobe_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) {
|
_FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector3 &p_half_extents) {
|
||||||
|
|
||||||
if (unlikely(decal_count == decal_max)) {
|
if (unlikely(decal_count == decal_max)) {
|
||||||
decal_max = nearest_power_of_2_templated(decal_max + 1);
|
decal_max = nearest_power_of_2_templated(decal_max + 1);
|
||||||
decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
|
decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform xform = view_xform * p_transform;
|
||||||
|
|
||||||
OrientedBoxData &dc = decals[decal_count];
|
OrientedBoxData &dc = decals[decal_count];
|
||||||
|
|
||||||
Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5;
|
Vector3 origin = xform.origin;
|
||||||
dc.z_axis[0] = z_axis.x;
|
|
||||||
dc.z_axis[1] = z_axis.y;
|
|
||||||
dc.z_axis[2] = z_axis.z;
|
|
||||||
|
|
||||||
Vector3 origin = p_transform.origin - z_axis;
|
|
||||||
dc.position[0] = origin.x;
|
dc.position[0] = origin.x;
|
||||||
dc.position[1] = origin.y;
|
dc.position[1] = origin.y;
|
||||||
dc.position[2] = origin.z;
|
dc.position[2] = origin.z;
|
||||||
|
|
||||||
Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
|
Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
|
||||||
dc.x_axis[0] = x_axis.x;
|
dc.x_axis[0] = x_axis.x;
|
||||||
dc.x_axis[1] = x_axis.y;
|
dc.x_axis[1] = x_axis.y;
|
||||||
dc.x_axis[2] = x_axis.z;
|
dc.x_axis[2] = x_axis.z;
|
||||||
|
|
||||||
Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
|
Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
|
||||||
dc.y_axis[0] = y_axis.x;
|
dc.y_axis[0] = y_axis.x;
|
||||||
dc.y_axis[1] = y_axis.y;
|
dc.y_axis[1] = y_axis.y;
|
||||||
dc.y_axis[2] = y_axis.z;
|
dc.y_axis[2] = y_axis.z;
|
||||||
|
|
||||||
|
Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
|
||||||
|
dc.z_axis[0] = z_axis.x;
|
||||||
|
dc.z_axis[1] = z_axis.y;
|
||||||
|
dc.z_axis[2] = z_axis.z;
|
||||||
|
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
|
|
||||||
aabb.position = origin + x_axis + y_axis + z_axis;
|
aabb.position = origin + x_axis + y_axis + z_axis;
|
||||||
|
|
|
@ -204,7 +204,29 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1
|
||||||
return uniform_set;
|
return uniform_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance) {
|
void RasterizerEffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y) {
|
||||||
|
|
||||||
|
zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||||
|
|
||||||
|
copy_to_fb.push_constant.use_section = true;
|
||||||
|
copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
|
||||||
|
copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
|
||||||
|
copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
|
||||||
|
copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
|
||||||
|
|
||||||
|
if (p_flip_y) {
|
||||||
|
copy_to_fb.push_constant.flip_y = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RD::DrawListID draw_list = p_draw_list;
|
||||||
|
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||||
|
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||||
|
RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||||
|
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero) {
|
||||||
zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||||
|
|
||||||
if (p_flip_y) {
|
if (p_flip_y) {
|
||||||
|
@ -213,9 +235,12 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr
|
||||||
if (p_force_luminance) {
|
if (p_force_luminance) {
|
||||||
copy_to_fb.push_constant.force_luminance = true;
|
copy_to_fb.push_constant.force_luminance = true;
|
||||||
}
|
}
|
||||||
|
if (p_alpha_to_zero) {
|
||||||
|
copy_to_fb.push_constant.alpha_to_zero = true;
|
||||||
|
}
|
||||||
|
|
||||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
|
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
|
||||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||||
|
@ -1220,7 +1245,9 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
|
||||||
|
|
||||||
//use additive
|
//use additive
|
||||||
|
|
||||||
copy_to_fb.pipeline.setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
for (int i = 0; i < COPY_TO_FB_MAX; i++) {
|
||||||
|
copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,21 +111,29 @@ class RasterizerEffectsRD {
|
||||||
|
|
||||||
} copy;
|
} copy;
|
||||||
|
|
||||||
|
enum CopyToFBMode {
|
||||||
|
COPY_TO_FB_COPY,
|
||||||
|
COPY_TO_FB_MAX,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct CopyToFbPushConstant {
|
struct CopyToFbPushConstant {
|
||||||
|
|
||||||
float section[4];
|
float section[4];
|
||||||
float pixel_size[2];
|
float pixel_size[2];
|
||||||
uint32_t flip_y;
|
uint32_t flip_y;
|
||||||
uint32_t use_section;
|
uint32_t use_section;
|
||||||
|
|
||||||
uint32_t force_luminance;
|
uint32_t force_luminance;
|
||||||
uint32_t pad[3];
|
uint32_t alpha_to_zero;
|
||||||
|
uint32_t pad[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyToFb {
|
struct CopyToFb {
|
||||||
CopyToFbPushConstant push_constant;
|
CopyToFbPushConstant push_constant;
|
||||||
CopyToFbShaderRD shader;
|
CopyToFbShaderRD shader;
|
||||||
RID shader_version;
|
RID shader_version;
|
||||||
RenderPipelineVertexFormatCacheRD pipeline;
|
RenderPipelineVertexFormatCacheRD pipelines[COPY_TO_FB_MAX];
|
||||||
|
|
||||||
} copy_to_fb;
|
} copy_to_fb;
|
||||||
|
|
||||||
|
@ -553,10 +561,11 @@ class RasterizerEffectsRD {
|
||||||
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
|
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
|
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false);
|
||||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false);
|
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false);
|
||||||
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
|
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
|
||||||
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
|
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
|
||||||
|
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false);
|
||||||
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
|
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||||
void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,21 @@ static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_arra
|
||||||
p_array[15] = 1;
|
p_array[15] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
|
||||||
|
p_array[0] = p_mtx.elements[0][0];
|
||||||
|
p_array[1] = p_mtx.elements[1][0];
|
||||||
|
p_array[2] = p_mtx.elements[2][0];
|
||||||
|
p_array[3] = 0;
|
||||||
|
p_array[4] = p_mtx.elements[0][1];
|
||||||
|
p_array[5] = p_mtx.elements[1][1];
|
||||||
|
p_array[6] = p_mtx.elements[2][1];
|
||||||
|
p_array[7] = 0;
|
||||||
|
p_array[8] = p_mtx.elements[0][2];
|
||||||
|
p_array[9] = p_mtx.elements[1][2];
|
||||||
|
p_array[10] = p_mtx.elements[2][2];
|
||||||
|
p_array[11] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) {
|
static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) {
|
||||||
p_array[0] = p_mtx.basis.elements[0][0];
|
p_array[0] = p_mtx.basis.elements[0][0];
|
||||||
p_array[1] = p_mtx.basis.elements[1][0];
|
p_array[1] = p_mtx.basis.elements[1][0];
|
||||||
|
@ -1903,7 +1918,143 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
|
void RasterizerSceneHighEndRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
|
||||||
|
|
||||||
|
Transform uv_xform;
|
||||||
|
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
|
||||||
|
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
|
||||||
|
|
||||||
|
p_decal_count = MIN((uint32_t)p_decal_count, scene_state.max_decals);
|
||||||
|
int idx = 0;
|
||||||
|
for (int i = 0; i < p_decal_count; i++) {
|
||||||
|
|
||||||
|
RID di = p_decal_instances[i];
|
||||||
|
RID decal = decal_instance_get_base(di);
|
||||||
|
|
||||||
|
Transform xform = decal_instance_get_transform(di);
|
||||||
|
|
||||||
|
float fade = 1.0;
|
||||||
|
|
||||||
|
if (storage->decal_is_distance_fade_enabled(decal)) {
|
||||||
|
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
|
||||||
|
float fade_begin = storage->decal_get_distance_fade_begin(decal);
|
||||||
|
float fade_length = storage->decal_get_distance_fade_length(decal);
|
||||||
|
|
||||||
|
if (distance > fade_begin) {
|
||||||
|
if (distance > fade_begin + fade_length) {
|
||||||
|
continue; // do not use this decal, its invisible
|
||||||
|
}
|
||||||
|
|
||||||
|
fade = 1.0 - (distance - fade_begin) / fade_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DecalData &dd = scene_state.decals[idx];
|
||||||
|
|
||||||
|
Vector3 decal_extents = storage->decal_get_extents(decal);
|
||||||
|
|
||||||
|
Transform scale_xform;
|
||||||
|
scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
|
||||||
|
Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse();
|
||||||
|
store_transform(to_decal_xform, dd.xform);
|
||||||
|
|
||||||
|
Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
|
||||||
|
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
|
||||||
|
|
||||||
|
dd.normal[0] = normal.x;
|
||||||
|
dd.normal[1] = normal.y;
|
||||||
|
dd.normal[2] = normal.z;
|
||||||
|
dd.normal_fade = storage->decal_get_normal_fade(decal);
|
||||||
|
|
||||||
|
RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
|
||||||
|
if (albedo_tex.is_valid()) {
|
||||||
|
Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
|
||||||
|
dd.albedo_rect[0] = rect.position.x;
|
||||||
|
dd.albedo_rect[1] = rect.position.y;
|
||||||
|
dd.albedo_rect[2] = rect.size.x;
|
||||||
|
dd.albedo_rect[3] = rect.size.y;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
dd.albedo_rect[0] = 0;
|
||||||
|
dd.albedo_rect[1] = 0;
|
||||||
|
dd.albedo_rect[2] = 0;
|
||||||
|
dd.albedo_rect[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
|
||||||
|
RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
|
||||||
|
|
||||||
|
if (normal_tex.is_valid()) {
|
||||||
|
Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
|
||||||
|
dd.normal_rect[0] = rect.position.x;
|
||||||
|
dd.normal_rect[1] = rect.position.y;
|
||||||
|
dd.normal_rect[2] = rect.size.x;
|
||||||
|
dd.normal_rect[3] = rect.size.y;
|
||||||
|
|
||||||
|
Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
|
||||||
|
store_basis_3x4(normal_xform, dd.normal_xform);
|
||||||
|
|
||||||
|
//store normal xform
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!emission_tex.is_valid()) {
|
||||||
|
continue; //no albedo, no emission, no decal.
|
||||||
|
}
|
||||||
|
dd.normal_rect[0] = 0;
|
||||||
|
dd.normal_rect[1] = 0;
|
||||||
|
dd.normal_rect[2] = 0;
|
||||||
|
dd.normal_rect[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
|
||||||
|
if (orm_tex.is_valid()) {
|
||||||
|
Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
|
||||||
|
dd.orm_rect[0] = rect.position.x;
|
||||||
|
dd.orm_rect[1] = rect.position.y;
|
||||||
|
dd.orm_rect[2] = rect.size.x;
|
||||||
|
dd.orm_rect[3] = rect.size.y;
|
||||||
|
} else {
|
||||||
|
dd.orm_rect[0] = 0;
|
||||||
|
dd.orm_rect[1] = 0;
|
||||||
|
dd.orm_rect[2] = 0;
|
||||||
|
dd.orm_rect[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emission_tex.is_valid()) {
|
||||||
|
Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
|
||||||
|
dd.emission_rect[0] = rect.position.x;
|
||||||
|
dd.emission_rect[1] = rect.position.y;
|
||||||
|
dd.emission_rect[2] = rect.size.x;
|
||||||
|
dd.emission_rect[3] = rect.size.y;
|
||||||
|
} else {
|
||||||
|
dd.emission_rect[0] = 0;
|
||||||
|
dd.emission_rect[1] = 0;
|
||||||
|
dd.emission_rect[2] = 0;
|
||||||
|
dd.emission_rect[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color modulate = storage->decal_get_modulate(decal);
|
||||||
|
dd.modulate[0] = modulate.r;
|
||||||
|
dd.modulate[1] = modulate.g;
|
||||||
|
dd.modulate[2] = modulate.b;
|
||||||
|
dd.modulate[3] = modulate.a * fade;
|
||||||
|
dd.emission_energy = storage->decal_get_emission_energy(decal) * fade;
|
||||||
|
dd.albedo_mix = storage->decal_get_albedo_mix(decal);
|
||||||
|
dd.mask = storage->decal_get_cull_mask(decal);
|
||||||
|
dd.upper_fade = storage->decal_get_upper_fade(decal);
|
||||||
|
dd.lower_fade = storage->decal_get_lower_fade(decal);
|
||||||
|
|
||||||
|
cluster_builder.add_decal(xform, decal_extents);
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx > 0) {
|
||||||
|
RD::get_singleton()->buffer_update(scene_state.decal_buffer, 0, sizeof(DecalData) * idx, scene_state.decals, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
|
||||||
|
|
||||||
RenderBufferDataHighEnd *render_buffer = nullptr;
|
RenderBufferDataHighEnd *render_buffer = nullptr;
|
||||||
if (p_render_buffer.is_valid()) {
|
if (p_render_buffer.is_valid()) {
|
||||||
|
@ -2020,6 +2171,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
||||||
cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
|
cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
|
||||||
|
|
||||||
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
|
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
|
||||||
|
_setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
|
||||||
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
|
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
|
||||||
_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
|
_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
|
||||||
_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
|
_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
|
||||||
|
@ -2461,17 +2613,40 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
||||||
|
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.binding = 10;
|
u.binding = 10;
|
||||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
|
RID decal_atlas = storage->decal_atlas_get_texture();
|
||||||
|
u.ids.push_back(decal_atlas);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.binding = 11;
|
||||||
|
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
|
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
|
||||||
|
u.ids.push_back(decal_atlas);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.binding = 12;
|
||||||
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
|
u.ids.push_back(scene_state.decal_buffer);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.binding = 13;
|
||||||
|
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
u.ids.push_back(cluster_builder.get_cluster_texture());
|
u.ids.push_back(cluster_builder.get_cluster_texture());
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.binding = 11;
|
u.binding = 14;
|
||||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
u.ids.push_back(cluster_builder.get_cluster_indices_buffer());
|
u.ids.push_back(cluster_builder.get_cluster_indices_buffer());
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
|
@ -2479,7 +2654,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
||||||
|
|
||||||
{
|
{
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.binding = 12;
|
u.binding = 15;
|
||||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
if (directional_shadow_get_texture().is_valid()) {
|
if (directional_shadow_get_texture().is_valid()) {
|
||||||
u.ids.push_back(directional_shadow_get_texture());
|
u.ids.push_back(directional_shadow_get_texture());
|
||||||
|
@ -2700,6 +2875,13 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
||||||
defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n";
|
defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ //decals
|
||||||
|
scene_state.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(DecalData); //1mb of decals
|
||||||
|
uint32_t decal_buffer_size = scene_state.max_decals * sizeof(DecalData);
|
||||||
|
scene_state.decals = memnew_arr(DecalData, scene_state.max_decals);
|
||||||
|
scene_state.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
Vector<String> shader_versions;
|
Vector<String> shader_versions;
|
||||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
|
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
|
||||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
|
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
|
||||||
|
@ -2979,10 +3161,12 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() {
|
||||||
RD::get_singleton()->free(scene_state.directional_light_buffer);
|
RD::get_singleton()->free(scene_state.directional_light_buffer);
|
||||||
RD::get_singleton()->free(scene_state.light_buffer);
|
RD::get_singleton()->free(scene_state.light_buffer);
|
||||||
RD::get_singleton()->free(scene_state.reflection_buffer);
|
RD::get_singleton()->free(scene_state.reflection_buffer);
|
||||||
|
RD::get_singleton()->free(scene_state.decal_buffer);
|
||||||
memdelete_arr(scene_state.instances);
|
memdelete_arr(scene_state.instances);
|
||||||
memdelete_arr(scene_state.gi_probes);
|
memdelete_arr(scene_state.gi_probes);
|
||||||
memdelete_arr(scene_state.directional_lights);
|
memdelete_arr(scene_state.directional_lights);
|
||||||
memdelete_arr(scene_state.lights);
|
memdelete_arr(scene_state.lights);
|
||||||
memdelete_arr(scene_state.reflections);
|
memdelete_arr(scene_state.reflections);
|
||||||
|
memdelete_arr(scene_state.decals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,6 +327,24 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
uint32_t pad[1];
|
uint32_t pad[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DecalData {
|
||||||
|
float xform[16];
|
||||||
|
float inv_extents[3];
|
||||||
|
float albedo_mix;
|
||||||
|
float albedo_rect[4];
|
||||||
|
float normal_rect[4];
|
||||||
|
float orm_rect[4];
|
||||||
|
float emission_rect[4];
|
||||||
|
float modulate[4];
|
||||||
|
float emission_energy;
|
||||||
|
uint32_t mask;
|
||||||
|
float upper_fade;
|
||||||
|
float lower_fade;
|
||||||
|
float normal_xform[12];
|
||||||
|
float normal[3];
|
||||||
|
float normal_fade;
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
|
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
|
||||||
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
||||||
|
@ -405,6 +423,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
RID gi_probe_buffer;
|
RID gi_probe_buffer;
|
||||||
uint32_t max_gi_probe_probes_per_instance;
|
uint32_t max_gi_probe_probes_per_instance;
|
||||||
|
|
||||||
|
DecalData *decals;
|
||||||
|
uint32_t max_decals;
|
||||||
|
RID decal_buffer;
|
||||||
|
|
||||||
LightData *lights;
|
LightData *lights;
|
||||||
uint32_t max_lights;
|
uint32_t max_lights;
|
||||||
RID light_buffer;
|
RID light_buffer;
|
||||||
|
@ -596,6 +618,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
|
|
||||||
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
|
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
|
||||||
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
|
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
|
||||||
|
void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
|
||||||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||||
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
|
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
|
||||||
|
|
||||||
|
@ -607,7 +630,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
|
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
|
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
|
||||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
|
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
|
||||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||||
|
|
||||||
|
|
|
@ -2104,6 +2104,21 @@ RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p
|
||||||
|
|
||||||
return &shadow_maps[p_size];
|
return &shadow_maps[p_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
RID RasterizerSceneRD::decal_instance_create(RID p_decal) {
|
||||||
|
DecalInstance di;
|
||||||
|
di.decal = p_decal;
|
||||||
|
return decal_instance_owner.make_rid(di);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneRD::decal_instance_set_transform(RID p_decal, const Transform &p_transform) {
|
||||||
|
DecalInstance *di = decal_instance_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!di);
|
||||||
|
di->transform = p_transform;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
|
||||||
RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
|
RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
|
||||||
|
@ -3481,6 +3496,16 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
|
||||||
|
RID decal_atlas = storage->decal_atlas_get_texture();
|
||||||
|
|
||||||
|
if (decal_atlas.is_valid()) {
|
||||||
|
Size2 rtsize = storage->render_target_get_size(rb->render_target);
|
||||||
|
|
||||||
|
effects->copy_to_fb_rect(decal_atlas, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
|
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
|
||||||
if (rb->luminance.current.is_valid()) {
|
if (rb->luminance.current.is_valid()) {
|
||||||
Size2 rtsize = storage->render_target_get_size(rb->render_target);
|
Size2 rtsize = storage->render_target_get_size(rb->render_target);
|
||||||
|
@ -3596,7 +3621,7 @@ RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(
|
||||||
return rb->data;
|
return rb->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_camera_effects, 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_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||||
|
|
||||||
Color clear_color;
|
Color clear_color;
|
||||||
if (p_render_buffers.is_valid()) {
|
if (p_render_buffers.is_valid()) {
|
||||||
|
@ -3607,7 +3632,7 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca
|
||||||
clear_color = storage->get_default_clear_color();
|
clear_color = storage->get_default_clear_color();
|
||||||
}
|
}
|
||||||
|
|
||||||
_render_scene(p_render_buffers, 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_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
|
_render_scene(p_render_buffers, 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_decal_cull_result, p_decal_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
|
||||||
|
|
||||||
if (p_render_buffers.is_valid()) {
|
if (p_render_buffers.is_valid()) {
|
||||||
RENDER_TIMESTAMP("Tonemap");
|
RENDER_TIMESTAMP("Tonemap");
|
||||||
|
@ -3827,6 +3852,8 @@ bool RasterizerSceneRD::free(RID p_rid) {
|
||||||
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
|
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
|
||||||
reflection_probe_release_atlas_index(p_rid);
|
reflection_probe_release_atlas_index(p_rid);
|
||||||
reflection_probe_instance_owner.free(p_rid);
|
reflection_probe_instance_owner.free(p_rid);
|
||||||
|
} else if (decal_instance_owner.owns(p_rid)) {
|
||||||
|
decal_instance_owner.free(p_rid);
|
||||||
} else if (gi_probe_instance_owner.owns(p_rid)) {
|
} else if (gi_probe_instance_owner.owns(p_rid)) {
|
||||||
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
|
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
|
||||||
if (gi_probe->texture.is_valid()) {
|
if (gi_probe->texture.is_valid()) {
|
||||||
|
|
|
@ -78,7 +78,7 @@ protected:
|
||||||
};
|
};
|
||||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||||
|
|
||||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
|
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 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, bool p_use_pancake) = 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, bool p_use_pancake) = 0;
|
||||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||||
|
|
||||||
|
@ -324,6 +324,16 @@ private:
|
||||||
|
|
||||||
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
|
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
|
||||||
|
|
||||||
|
/* REFLECTION PROBE INSTANCE */
|
||||||
|
|
||||||
|
struct DecalInstance {
|
||||||
|
|
||||||
|
RID decal;
|
||||||
|
Transform transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RID_Owner<DecalInstance> decal_instance_owner;
|
||||||
|
|
||||||
/* GIPROBE INSTANCE */
|
/* GIPROBE INSTANCE */
|
||||||
|
|
||||||
struct GIProbeLight {
|
struct GIProbeLight {
|
||||||
|
@ -1091,6 +1101,19 @@ public:
|
||||||
return rpi->atlas_index;
|
return rpi->atlas_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual RID decal_instance_create(RID p_decal);
|
||||||
|
virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform);
|
||||||
|
|
||||||
|
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
|
||||||
|
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
|
||||||
|
return decal->decal;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Transform decal_instance_get_transform(RID p_decal) const {
|
||||||
|
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
|
||||||
|
return decal->transform;
|
||||||
|
}
|
||||||
|
|
||||||
RID gi_probe_instance_create(RID p_base);
|
RID gi_probe_instance_create(RID p_base);
|
||||||
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
|
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
|
||||||
bool gi_probe_needs_update(RID p_probe) const;
|
bool gi_probe_needs_update(RID p_probe) const;
|
||||||
|
@ -1156,7 +1179,7 @@ public:
|
||||||
RID render_buffers_get_ao_texture(RID p_render_buffers);
|
RID render_buffers_get_ao_texture(RID p_render_buffers);
|
||||||
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
|
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
|
||||||
|
|
||||||
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_camera_effects, 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_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||||
|
|
||||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
|
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
|
||||||
|
|
||||||
|
|
|
@ -809,6 +809,12 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
|
||||||
}
|
}
|
||||||
//delete last, so proxies can be updated
|
//delete last, so proxies can be updated
|
||||||
texture_owner.free(p_by_texture);
|
texture_owner.free(p_by_texture);
|
||||||
|
|
||||||
|
if (decal_atlas.textures.has(p_texture)) {
|
||||||
|
//belongs to decal atlas..
|
||||||
|
|
||||||
|
decal_atlas.dirty = true; //mark it dirty since it was most likely modified
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
|
void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
|
||||||
Texture *tex = texture_owner.getornull(p_texture);
|
Texture *tex = texture_owner.getornull(p_texture);
|
||||||
|
@ -3553,6 +3559,94 @@ float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribut
|
||||||
return reflection_probe->interior_ambient_probe_contrib;
|
return reflection_probe->interior_ambient_probe_contrib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID RasterizerStorageRD::decal_create() {
|
||||||
|
return decal_owner.make_rid(Decal());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->extents = p_extents;
|
||||||
|
decal->instance_dependency.instance_notify_changed(true, false);
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
|
||||||
|
|
||||||
|
if (decal->textures[p_type] == p_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
|
||||||
|
|
||||||
|
if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) {
|
||||||
|
texture_remove_from_decal_atlas(decal->textures[p_type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
decal->textures[p_type] = p_texture;
|
||||||
|
|
||||||
|
if (decal->textures[p_type].is_valid()) {
|
||||||
|
texture_add_to_decal_atlas(decal->textures[p_type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
decal->instance_dependency.instance_notify_changed(false, true);
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->emission_energy = p_energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->albedo_mix = p_mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->modulate = p_modulate;
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->cull_mask = p_layers;
|
||||||
|
decal->instance_dependency.instance_notify_changed(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
|
||||||
|
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->distance_fade = p_enabled;
|
||||||
|
decal->distance_fade_begin = p_begin;
|
||||||
|
decal->distance_fade_length = p_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) {
|
||||||
|
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->upper_fade = p_above;
|
||||||
|
decal->lower_fade = p_below;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) {
|
||||||
|
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND(!decal);
|
||||||
|
decal->normal_fade = p_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB RasterizerStorageRD::decal_get_aabb(RID p_decal) const {
|
||||||
|
Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
ERR_FAIL_COND_V(!decal, AABB());
|
||||||
|
|
||||||
|
return AABB(-decal->extents, decal->extents * 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
RID RasterizerStorageRD::gi_probe_create() {
|
RID RasterizerStorageRD::gi_probe_create() {
|
||||||
|
|
||||||
return gi_probe_owner.make_rid(GIProbe());
|
return gi_probe_owner.make_rid(GIProbe());
|
||||||
|
@ -4243,6 +4337,9 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
|
||||||
} else if (reflection_probe_owner.owns(p_base)) {
|
} else if (reflection_probe_owner.owns(p_base)) {
|
||||||
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
|
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
|
||||||
p_instance->update_dependency(&rp->instance_dependency);
|
p_instance->update_dependency(&rp->instance_dependency);
|
||||||
|
} else if (decal_owner.owns(p_base)) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_base);
|
||||||
|
p_instance->update_dependency(&decal->instance_dependency);
|
||||||
} else if (gi_probe_owner.owns(p_base)) {
|
} else if (gi_probe_owner.owns(p_base)) {
|
||||||
GIProbe *gip = gi_probe_owner.getornull(p_base);
|
GIProbe *gip = gi_probe_owner.getornull(p_base);
|
||||||
p_instance->update_dependency(&gip->instance_dependency);
|
p_instance->update_dependency(&gip->instance_dependency);
|
||||||
|
@ -4271,6 +4368,9 @@ RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
|
||||||
if (reflection_probe_owner.owns(p_rid)) {
|
if (reflection_probe_owner.owns(p_rid)) {
|
||||||
return RS::INSTANCE_REFLECTION_PROBE;
|
return RS::INSTANCE_REFLECTION_PROBE;
|
||||||
}
|
}
|
||||||
|
if (decal_owner.owns(p_rid)) {
|
||||||
|
return RS::INSTANCE_DECAL;
|
||||||
|
}
|
||||||
if (gi_probe_owner.owns(p_rid)) {
|
if (gi_probe_owner.owns(p_rid)) {
|
||||||
return RS::INSTANCE_GI_PROBE;
|
return RS::INSTANCE_GI_PROBE;
|
||||||
}
|
}
|
||||||
|
@ -4280,10 +4380,238 @@ RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
|
||||||
|
|
||||||
return RS::INSTANCE_NONE;
|
return RS::INSTANCE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::texture_add_to_decal_atlas(RID p_texture) {
|
||||||
|
if (!decal_atlas.textures.has(p_texture)) {
|
||||||
|
DecalAtlas::Texture t;
|
||||||
|
t.users = 1;
|
||||||
|
decal_atlas.textures[p_texture] = t;
|
||||||
|
decal_atlas.dirty = true;
|
||||||
|
} else {
|
||||||
|
DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
|
||||||
|
t->users++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::texture_remove_from_decal_atlas(RID p_texture) {
|
||||||
|
DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
|
||||||
|
ERR_FAIL_COND(!t);
|
||||||
|
t->users--;
|
||||||
|
if (t->users == 0) {
|
||||||
|
decal_atlas.textures.erase(p_texture);
|
||||||
|
//do not mark it dirty, there is no need to since it remains working
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RID RasterizerStorageRD::decal_atlas_get_texture() const {
|
||||||
|
return decal_atlas.texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID RasterizerStorageRD::decal_atlas_get_texture_srgb() const {
|
||||||
|
return decal_atlas.texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_update_decal_atlas() {
|
||||||
|
if (!decal_atlas.dirty) {
|
||||||
|
return; //nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
decal_atlas.dirty = false;
|
||||||
|
|
||||||
|
if (decal_atlas.texture.is_valid()) {
|
||||||
|
RD::get_singleton()->free(decal_atlas.texture);
|
||||||
|
decal_atlas.texture = RID();
|
||||||
|
decal_atlas.texture_srgb = RID();
|
||||||
|
decal_atlas.texture_mipmaps.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int border = 1 << decal_atlas.mipmaps;
|
||||||
|
|
||||||
|
if (decal_atlas.textures.size()) {
|
||||||
|
//generate atlas
|
||||||
|
Vector<DecalAtlas::SortItem> itemsv;
|
||||||
|
itemsv.resize(decal_atlas.textures.size());
|
||||||
|
int base_size = 8;
|
||||||
|
const RID *K = NULL;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
while ((K = decal_atlas.textures.next(K))) {
|
||||||
|
DecalAtlas::SortItem &si = itemsv.write[idx];
|
||||||
|
|
||||||
|
Texture *src_tex = texture_owner.getornull(*K);
|
||||||
|
|
||||||
|
si.size.width = (src_tex->width / border) + 1;
|
||||||
|
si.size.height = (src_tex->height / border) + 1;
|
||||||
|
si.pixel_size = Size2i(src_tex->width, src_tex->height);
|
||||||
|
|
||||||
|
if (base_size < si.size.width) {
|
||||||
|
base_size = nearest_power_of_2_templated(si.size.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
si.texture = *K;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort items by size
|
||||||
|
itemsv.sort();
|
||||||
|
|
||||||
|
//attempt to create atlas
|
||||||
|
int item_count = itemsv.size();
|
||||||
|
DecalAtlas::SortItem *items = itemsv.ptrw();
|
||||||
|
|
||||||
|
int atlas_height = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
Vector<int> v_offsetsv;
|
||||||
|
v_offsetsv.resize(base_size);
|
||||||
|
|
||||||
|
int *v_offsets = v_offsetsv.ptrw();
|
||||||
|
zeromem(v_offsets, sizeof(int) * base_size);
|
||||||
|
|
||||||
|
int max_height = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < item_count; i++) {
|
||||||
|
//best fit
|
||||||
|
DecalAtlas::SortItem &si = items[i];
|
||||||
|
int best_idx = -1;
|
||||||
|
int best_height = 0x7FFFFFFF;
|
||||||
|
for (int j = 0; j <= base_size - si.size.width; j++) {
|
||||||
|
int height = 0;
|
||||||
|
for (int k = 0; k < si.size.width; k++) {
|
||||||
|
int h = v_offsets[k + j];
|
||||||
|
if (h > height) {
|
||||||
|
height = h;
|
||||||
|
if (height > best_height) {
|
||||||
|
break; //already bad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height < best_height) {
|
||||||
|
best_height = height;
|
||||||
|
best_idx = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update
|
||||||
|
for (int k = 0; k < si.size.width; k++) {
|
||||||
|
v_offsets[k + best_idx] = best_height + si.size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
si.pos.x = best_idx;
|
||||||
|
si.pos.y = best_height;
|
||||||
|
|
||||||
|
if (si.pos.y + si.size.height > max_height) {
|
||||||
|
max_height = si.pos.y + si.size.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_height <= base_size * 2) {
|
||||||
|
atlas_height = max_height;
|
||||||
|
break; //good ratio, break;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_size *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
decal_atlas.size.width = base_size * border;
|
||||||
|
decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
|
||||||
|
|
||||||
|
for (int i = 0; i < item_count; i++) {
|
||||||
|
DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
|
||||||
|
t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
|
||||||
|
t->uv_rect.size = items[i].pixel_size;
|
||||||
|
//print_line("blitrect: " + t->uv_rect);
|
||||||
|
t->uv_rect.position /= Size2(decal_atlas.size);
|
||||||
|
t->uv_rect.size /= Size2(decal_atlas.size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//use border as size, so it at least has enough mipmaps
|
||||||
|
decal_atlas.size.width = border;
|
||||||
|
decal_atlas.size.height = border;
|
||||||
|
}
|
||||||
|
|
||||||
|
//blit textures
|
||||||
|
|
||||||
|
RD::TextureFormat tformat;
|
||||||
|
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
tformat.width = decal_atlas.size.width;
|
||||||
|
tformat.height = decal_atlas.size.height;
|
||||||
|
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||||
|
tformat.type = RD::TEXTURE_TYPE_2D;
|
||||||
|
tformat.mipmaps = decal_atlas.mipmaps;
|
||||||
|
tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
|
||||||
|
tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
|
||||||
|
|
||||||
|
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||||
|
|
||||||
|
{
|
||||||
|
//create the framebuffer
|
||||||
|
|
||||||
|
Size2i s = decal_atlas.size;
|
||||||
|
|
||||||
|
for (int i = 0; i < decal_atlas.mipmaps; i++) {
|
||||||
|
DecalAtlas::MipMap mm;
|
||||||
|
mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
|
||||||
|
Vector<RID> fb;
|
||||||
|
fb.push_back(mm.texture);
|
||||||
|
mm.fb = RD::get_singleton()->framebuffer_create(fb);
|
||||||
|
mm.size = s;
|
||||||
|
decal_atlas.texture_mipmaps.push_back(mm);
|
||||||
|
|
||||||
|
s.width = MAX(1, s.width >> 1);
|
||||||
|
s.height = MAX(1, s.height >> 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//create the SRGB variant
|
||||||
|
RD::TextureView rd_view;
|
||||||
|
rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RID prev_texture;
|
||||||
|
for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
|
||||||
|
const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
|
||||||
|
|
||||||
|
Color clear_color(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if (decal_atlas.textures.size()) {
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
Vector<Color> cc;
|
||||||
|
cc.push_back(clear_color);
|
||||||
|
|
||||||
|
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
|
||||||
|
|
||||||
|
const RID *K = NULL;
|
||||||
|
while ((K = decal_atlas.textures.next(K))) {
|
||||||
|
DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
|
||||||
|
Texture *src_tex = texture_owner.getornull(*K);
|
||||||
|
effects.copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
RD::get_singleton()->draw_list_end();
|
||||||
|
|
||||||
|
prev_texture = mm.texture;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
effects.copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
|
||||||
|
prev_texture = mm.texture;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::update_dirty_resources() {
|
void RasterizerStorageRD::update_dirty_resources() {
|
||||||
_update_queued_materials();
|
_update_queued_materials();
|
||||||
_update_dirty_multimeshes();
|
_update_dirty_multimeshes();
|
||||||
_update_dirty_skeletons();
|
_update_dirty_skeletons();
|
||||||
|
_update_decal_atlas();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
|
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
|
||||||
|
@ -4332,6 +4660,11 @@ bool RasterizerStorageRD::free(RID p_rid) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (decal_atlas.textures.has(p_rid)) {
|
||||||
|
decal_atlas.textures.erase(p_rid);
|
||||||
|
//there is not much a point of making it dirty, just let it be.
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < t->proxies.size(); i++) {
|
for (int i = 0; i < t->proxies.size(); i++) {
|
||||||
Texture *p = texture_owner.getornull(t->proxies[i]);
|
Texture *p = texture_owner.getornull(t->proxies[i]);
|
||||||
ERR_CONTINUE(!p);
|
ERR_CONTINUE(!p);
|
||||||
|
@ -4382,6 +4715,15 @@ bool RasterizerStorageRD::free(RID p_rid) {
|
||||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
|
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
|
||||||
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
|
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
|
||||||
reflection_probe_owner.free(p_rid);
|
reflection_probe_owner.free(p_rid);
|
||||||
|
} else if (decal_owner.owns(p_rid)) {
|
||||||
|
Decal *decal = decal_owner.getornull(p_rid);
|
||||||
|
for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
|
||||||
|
if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) {
|
||||||
|
texture_remove_from_decal_atlas(decal->textures[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decal->instance_dependency.instance_notify_deleted(p_rid);
|
||||||
|
decal_owner.free(p_rid);
|
||||||
} else if (gi_probe_owner.owns(p_rid)) {
|
} else if (gi_probe_owner.owns(p_rid)) {
|
||||||
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
|
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
|
||||||
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
|
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
|
||||||
|
@ -4485,6 +4827,10 @@ RasterizerStorageRD::RasterizerStorageRD() {
|
||||||
Vector<Vector<uint8_t>> vpv;
|
Vector<Vector<uint8_t>> vpv;
|
||||||
vpv.push_back(pv);
|
vpv.push_back(pv);
|
||||||
default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||||
|
|
||||||
|
//take the chance and initialize decal atlas to something
|
||||||
|
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||||
|
decal_atlas.texture_srgb = decal_atlas.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
|
@ -4676,9 +5022,11 @@ RasterizerStorageRD::RasterizerStorageRD() {
|
||||||
//default rd buffers
|
//default rd buffers
|
||||||
{
|
{
|
||||||
|
|
||||||
{ //vertex
|
//vertex
|
||||||
|
{
|
||||||
|
|
||||||
Vector<uint8_t> buffer;
|
Vector<uint8_t> buffer;
|
||||||
|
|
||||||
buffer.resize(sizeof(float) * 3);
|
buffer.resize(sizeof(float) * 3);
|
||||||
{
|
{
|
||||||
uint8_t *w = buffer.ptrw();
|
uint8_t *w = buffer.ptrw();
|
||||||
|
@ -4813,4 +5161,12 @@ RasterizerStorageRD::~RasterizerStorageRD() {
|
||||||
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
|
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
|
||||||
}
|
}
|
||||||
giprobe_sdf_shader.version_free(giprobe_sdf_shader_version);
|
giprobe_sdf_shader.version_free(giprobe_sdf_shader_version);
|
||||||
|
|
||||||
|
if (decal_atlas.textures.size()) {
|
||||||
|
ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decal_atlas.texture.is_valid()) {
|
||||||
|
RD::get_singleton()->free(decal_atlas.texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,50 @@ private:
|
||||||
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
|
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
|
||||||
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
|
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
|
||||||
|
|
||||||
|
/* DECAL ATLAS */
|
||||||
|
|
||||||
|
struct DecalAtlas {
|
||||||
|
struct Texture {
|
||||||
|
|
||||||
|
int users;
|
||||||
|
Rect2 uv_rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SortItem {
|
||||||
|
RID texture;
|
||||||
|
Size2i pixel_size;
|
||||||
|
Size2i size;
|
||||||
|
Point2i pos;
|
||||||
|
|
||||||
|
bool operator<(const SortItem &p_item) const {
|
||||||
|
//sort larger to smaller
|
||||||
|
if (size.height == p_item.size.height) {
|
||||||
|
return size.width > p_item.size.width;
|
||||||
|
} else {
|
||||||
|
return size.height > p_item.size.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HashMap<RID, Texture> textures;
|
||||||
|
bool dirty = true;
|
||||||
|
int mipmaps = 5;
|
||||||
|
|
||||||
|
RID texture;
|
||||||
|
RID texture_srgb;
|
||||||
|
struct MipMap {
|
||||||
|
RID fb;
|
||||||
|
RID texture;
|
||||||
|
Size2i size;
|
||||||
|
};
|
||||||
|
Vector<MipMap> texture_mipmaps;
|
||||||
|
|
||||||
|
Size2i size;
|
||||||
|
|
||||||
|
} decal_atlas;
|
||||||
|
|
||||||
|
void _update_decal_atlas();
|
||||||
|
|
||||||
/* SHADER */
|
/* SHADER */
|
||||||
|
|
||||||
struct Material;
|
struct Material;
|
||||||
|
@ -403,6 +447,28 @@ private:
|
||||||
|
|
||||||
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
|
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
|
||||||
|
|
||||||
|
/* DECAL */
|
||||||
|
|
||||||
|
struct Decal {
|
||||||
|
|
||||||
|
Vector3 extents = Vector3(1, 1, 1);
|
||||||
|
RID textures[RS::DECAL_TEXTURE_MAX];
|
||||||
|
float emission_energy = 1.0;
|
||||||
|
float albedo_mix = 1.0;
|
||||||
|
Color modulate = Color(1, 1, 1, 1);
|
||||||
|
uint32_t cull_mask = (1 << 20) - 1;
|
||||||
|
float upper_fade = 0.3;
|
||||||
|
float lower_fade = 0.3;
|
||||||
|
bool distance_fade = false;
|
||||||
|
float distance_fade_begin = 10;
|
||||||
|
float distance_fade_length = 1;
|
||||||
|
float normal_fade = 0.0;
|
||||||
|
|
||||||
|
RasterizerScene::InstanceDependency instance_dependency;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RID_Owner<Decal> decal_owner;
|
||||||
|
|
||||||
/* GI PROBE */
|
/* GI PROBE */
|
||||||
|
|
||||||
struct GIProbe {
|
struct GIProbe {
|
||||||
|
@ -533,6 +599,20 @@ public:
|
||||||
|
|
||||||
virtual Size2 texture_size_with_proxy(RID p_proxy);
|
virtual Size2 texture_size_with_proxy(RID p_proxy);
|
||||||
|
|
||||||
|
virtual void texture_add_to_decal_atlas(RID p_texture);
|
||||||
|
virtual void texture_remove_from_decal_atlas(RID p_texture);
|
||||||
|
|
||||||
|
RID decal_atlas_get_texture() const;
|
||||||
|
RID decal_atlas_get_texture_srgb() const;
|
||||||
|
_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
|
||||||
|
DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
|
||||||
|
if (!t) {
|
||||||
|
return Rect2();
|
||||||
|
}
|
||||||
|
|
||||||
|
return t->uv_rect;
|
||||||
|
}
|
||||||
|
|
||||||
//internal usage
|
//internal usage
|
||||||
|
|
||||||
_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
|
_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
|
||||||
|
@ -972,6 +1052,81 @@ public:
|
||||||
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
|
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
|
||||||
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
||||||
|
|
||||||
|
/* DECAL API */
|
||||||
|
|
||||||
|
virtual RID decal_create();
|
||||||
|
virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
|
||||||
|
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
|
||||||
|
virtual void decal_set_emission_energy(RID p_decal, float p_energy);
|
||||||
|
virtual void decal_set_albedo_mix(RID p_decal, float p_mix);
|
||||||
|
virtual void decal_set_modulate(RID p_decal, const Color &p_modulate);
|
||||||
|
virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers);
|
||||||
|
virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length);
|
||||||
|
virtual void decal_set_fade(RID p_decal, float p_above, float p_below);
|
||||||
|
virtual void decal_set_normal_fade(RID p_decal, float p_fade);
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->extents;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->textures[p_texture];
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->modulate;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->emission_energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->albedo_mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->cull_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->upper_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->lower_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->normal_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->distance_fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->distance_fade_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
|
||||||
|
const Decal *decal = decal_owner.getornull(p_decal);
|
||||||
|
return decal->distance_fade_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual AABB decal_get_aabb(RID p_decal) const;
|
||||||
|
|
||||||
/* GI PROBE API */
|
/* GI PROBE API */
|
||||||
|
|
||||||
RID gi_probe_create();
|
RID gi_probe_create();
|
||||||
|
|
|
@ -35,7 +35,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
|
||||||
// DOF.
|
// DOF.
|
||||||
float camera_z_far;
|
float camera_z_far;
|
||||||
float camera_z_near;
|
float camera_z_near;
|
||||||
uvec2 pad2;
|
uint pad2[2];
|
||||||
}
|
}
|
||||||
params;
|
params;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
|
||||||
vec2 pixel_size;
|
vec2 pixel_size;
|
||||||
bool flip_y;
|
bool flip_y;
|
||||||
bool use_section;
|
bool use_section;
|
||||||
|
|
||||||
bool force_luminance;
|
bool force_luminance;
|
||||||
uint pad[3];
|
uint pad[3];
|
||||||
}
|
}
|
||||||
|
@ -23,11 +24,12 @@ void main() {
|
||||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||||
uv_interp = base_arr[gl_VertexIndex];
|
uv_interp = base_arr[gl_VertexIndex];
|
||||||
|
|
||||||
|
vec2 vpos = uv_interp;
|
||||||
if (params.use_section) {
|
if (params.use_section) {
|
||||||
uv_interp = params.section.xy + uv_interp * params.section.zw;
|
vpos = params.section.xy + vpos * params.section.zw;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
|
||||||
|
|
||||||
if (params.flip_y) {
|
if (params.flip_y) {
|
||||||
uv_interp.y = 1.0 - uv_interp.y;
|
uv_interp.y = 1.0 - uv_interp.y;
|
||||||
|
@ -46,8 +48,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
|
||||||
vec2 pixel_size;
|
vec2 pixel_size;
|
||||||
bool flip_y;
|
bool flip_y;
|
||||||
bool use_section;
|
bool use_section;
|
||||||
|
|
||||||
bool force_luminance;
|
bool force_luminance;
|
||||||
uint pad[3];
|
bool alpha_to_zero;
|
||||||
|
uint pad[2];
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,9 +64,13 @@ layout(location = 0) out vec4 frag_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
vec4 color = texture(source_color, uv_interp, 0.0);
|
vec2 uv = uv_interp;
|
||||||
|
vec4 color = textureLod(source_color, uv, 0.0);
|
||||||
if (params.force_luminance) {
|
if (params.force_luminance) {
|
||||||
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
||||||
}
|
}
|
||||||
|
if (params.alpha_to_zero) {
|
||||||
|
color.rgb *= color.a;
|
||||||
|
}
|
||||||
frag_color = color;
|
frag_color = color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,7 @@ layout(location = 2) in vec4 tangent_attrib;
|
||||||
layout(location = 3) in vec4 color_attrib;
|
layout(location = 3) in vec4 color_attrib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UV_USED)
|
|
||||||
layout(location = 4) in vec2 uv_attrib;
|
layout(location = 4) in vec2 uv_attrib;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
||||||
layout(location = 5) in vec2 uv2_attrib;
|
layout(location = 5) in vec2 uv2_attrib;
|
||||||
|
@ -39,9 +37,7 @@ layout(location = 1) out vec3 normal_interp;
|
||||||
layout(location = 2) out vec4 color_interp;
|
layout(location = 2) out vec4 color_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UV_USED)
|
|
||||||
layout(location = 3) out vec2 uv_interp;
|
layout(location = 3) out vec2 uv_interp;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
||||||
layout(location = 4) out vec2 uv2_interp;
|
layout(location = 4) out vec2 uv2_interp;
|
||||||
|
@ -157,9 +153,7 @@ void main() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(UV_USED)
|
|
||||||
uv_interp = uv_attrib;
|
uv_interp = uv_attrib;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
||||||
uv2_interp = uv2_attrib;
|
uv2_interp = uv2_attrib;
|
||||||
|
@ -290,9 +284,7 @@ layout(location = 1) in vec3 normal_interp;
|
||||||
layout(location = 2) in vec4 color_interp;
|
layout(location = 2) in vec4 color_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UV_USED)
|
|
||||||
layout(location = 3) in vec2 uv_interp;
|
layout(location = 3) in vec2 uv_interp;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
||||||
layout(location = 4) in vec2 uv2_interp;
|
layout(location = 4) in vec2 uv2_interp;
|
||||||
|
@ -1609,9 +1601,7 @@ void main() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UV_USED)
|
|
||||||
vec2 uv = uv_interp;
|
vec2 uv = uv_interp;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
|
||||||
vec2 uv2 = uv2_interp;
|
vec2 uv2 = uv2_interp;
|
||||||
|
@ -1693,7 +1683,80 @@ FRAGMENT_SHADER_CODE
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/////////////////////// DECALS ////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MODE_RENDER_DEPTH
|
||||||
|
|
||||||
|
uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
|
||||||
|
|
||||||
|
{ // process decals
|
||||||
|
|
||||||
|
uint decal_count = cluster_cell.w >> CLUSTER_COUNTER_SHIFT;
|
||||||
|
uint decal_pointer = cluster_cell.w & CLUSTER_POINTER_MASK;
|
||||||
|
|
||||||
|
//do outside for performance and avoiding arctifacts
|
||||||
|
vec3 vertex_ddx = dFdx(vertex);
|
||||||
|
vec3 vertex_ddy = dFdy(vertex);
|
||||||
|
|
||||||
|
for (uint i = 0; i < decal_count; i++) {
|
||||||
|
|
||||||
|
uint decal_index = cluster_data.indices[decal_pointer + i];
|
||||||
|
if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
|
||||||
|
continue; //not masked
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
|
||||||
|
if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
|
||||||
|
continue; //out of decal
|
||||||
|
}
|
||||||
|
|
||||||
|
//we need ddx/ddy for mipmaps, so simulate them
|
||||||
|
vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
|
||||||
|
vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
|
||||||
|
|
||||||
|
float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
|
||||||
|
|
||||||
|
if (decals.data[decal_index].normal_fade > 0.0) {
|
||||||
|
fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
|
||||||
|
//has albedo
|
||||||
|
vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
|
||||||
|
decal_albedo *= decals.data[decal_index].modulate;
|
||||||
|
decal_albedo.a *= fade;
|
||||||
|
albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
|
||||||
|
|
||||||
|
if (decals.data[decal_index].normal_rect != vec4(0.0)) {
|
||||||
|
|
||||||
|
vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
|
||||||
|
decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
|
||||||
|
decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
|
||||||
|
//convert to view space, use xzy because y is up
|
||||||
|
decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
|
||||||
|
|
||||||
|
normal = normalize(mix(normal, decal_normal, decal_albedo.a));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decals.data[decal_index].orm_rect != vec4(0.0)) {
|
||||||
|
|
||||||
|
vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
|
||||||
|
#if defined(AO_USED)
|
||||||
|
ao = mix(ao, decal_orm.r, decal_albedo.a);
|
||||||
|
#endif
|
||||||
|
roughness = mix(roughness, decal_orm.g, decal_albedo.a);
|
||||||
|
metallic = mix(metallic, decal_orm.b, decal_albedo.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decals.data[decal_index].emission_rect != vec4(0.0)) {
|
||||||
|
//emission is additive, so its independent from albedo
|
||||||
|
emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //not render depth
|
||||||
/////////////////////// LIGHTING //////////////////////////////
|
/////////////////////// LIGHTING //////////////////////////////
|
||||||
|
|
||||||
//apply energy conservation
|
//apply energy conservation
|
||||||
|
@ -1798,8 +1861,6 @@ FRAGMENT_SHADER_CODE
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
|
|
||||||
|
|
||||||
{ // process reflections
|
{ // process reflections
|
||||||
|
|
||||||
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
|
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
|
@ -137,7 +137,7 @@ struct InstanceData {
|
||||||
uint layer_mask;
|
uint layer_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 4, std430) buffer Instances {
|
layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
|
||||||
InstanceData data[];
|
InstanceData data[];
|
||||||
}
|
}
|
||||||
instances;
|
instances;
|
||||||
|
@ -161,7 +161,7 @@ struct LightData { //this structure needs to be as packed as possible
|
||||||
uint pad[3];
|
uint pad[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 5, std430) buffer Lights {
|
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
|
||||||
LightData data[];
|
LightData data[];
|
||||||
}
|
}
|
||||||
lights;
|
lights;
|
||||||
|
@ -248,14 +248,40 @@ layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TE
|
||||||
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
|
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
|
||||||
#define CLUSTER_COUNTER_MASK 0xfff
|
#define CLUSTER_COUNTER_MASK 0xfff
|
||||||
|
|
||||||
layout(set = 0, binding = 10) uniform utexture3D cluster_texture;
|
layout(set = 0, binding = 10) uniform texture2D decal_atlas;
|
||||||
|
layout(set = 0, binding = 11) uniform texture2D decal_atlas_srgb;
|
||||||
|
|
||||||
layout(set = 0, binding = 11, std430) buffer ClusterData {
|
struct DecalData {
|
||||||
|
mat4 xform; //to decal transform
|
||||||
|
vec3 inv_extents;
|
||||||
|
float albedo_mix;
|
||||||
|
vec4 albedo_rect;
|
||||||
|
vec4 normal_rect;
|
||||||
|
vec4 orm_rect;
|
||||||
|
vec4 emission_rect;
|
||||||
|
vec4 modulate;
|
||||||
|
float emission_energy;
|
||||||
|
uint mask;
|
||||||
|
float upper_fade;
|
||||||
|
float lower_fade;
|
||||||
|
mat3x4 normal_xform;
|
||||||
|
vec3 normal;
|
||||||
|
float normal_fade;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 12, std430) restrict readonly buffer Decals {
|
||||||
|
DecalData data[];
|
||||||
|
}
|
||||||
|
decals;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 13) uniform utexture3D cluster_texture;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 14, std430) restrict readonly buffer ClusterData {
|
||||||
uint indices[];
|
uint indices[];
|
||||||
}
|
}
|
||||||
cluster_data;
|
cluster_data;
|
||||||
|
|
||||||
layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas;
|
layout(set = 0, binding = 15) uniform texture2D directional_shadow_atlas;
|
||||||
|
|
||||||
// decal atlas
|
// decal atlas
|
||||||
|
|
||||||
|
@ -287,7 +313,7 @@ layout(set = 3, binding = 4) uniform texture2D ao_buffer;
|
||||||
|
|
||||||
/* Set 4 Skeleton & Instancing (Multimesh) */
|
/* Set 4 Skeleton & Instancing (Multimesh) */
|
||||||
|
|
||||||
layout(set = 4, binding = 0, std430) buffer Transforms {
|
layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms {
|
||||||
vec4 data[];
|
vec4 data[];
|
||||||
}
|
}
|
||||||
transforms;
|
transforms;
|
||||||
|
|
|
@ -340,6 +340,20 @@ public:
|
||||||
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||||
BIND2(reflection_probe_set_resolution, RID, int)
|
BIND2(reflection_probe_set_resolution, RID, int)
|
||||||
|
|
||||||
|
/* DECAL API */
|
||||||
|
|
||||||
|
BIND0R(RID, decal_create)
|
||||||
|
|
||||||
|
BIND2(decal_set_extents, RID, const Vector3 &)
|
||||||
|
BIND3(decal_set_texture, RID, DecalTexture, RID)
|
||||||
|
BIND2(decal_set_emission_energy, RID, float)
|
||||||
|
BIND2(decal_set_albedo_mix, RID, float)
|
||||||
|
BIND2(decal_set_modulate, RID, const Color &)
|
||||||
|
BIND2(decal_set_cull_mask, RID, uint32_t)
|
||||||
|
BIND4(decal_set_distance_fade, RID, bool, float, float)
|
||||||
|
BIND3(decal_set_fade, RID, float, float)
|
||||||
|
BIND2(decal_set_normal_fade, RID, float)
|
||||||
|
|
||||||
/* BAKED LIGHT API */
|
/* BAKED LIGHT API */
|
||||||
|
|
||||||
BIND0R(RID, gi_probe_create)
|
BIND0R(RID, gi_probe_create)
|
||||||
|
|
|
@ -154,6 +154,20 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
|
||||||
|
|
||||||
geom->reflection_dirty = true;
|
geom->reflection_dirty = true;
|
||||||
|
|
||||||
|
return E; //this element should make freeing faster
|
||||||
|
} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
|
||||||
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||||
|
|
||||||
|
InstanceDecalData::PairInfo pinfo;
|
||||||
|
pinfo.geometry = A;
|
||||||
|
pinfo.L = geom->decals.push_back(B);
|
||||||
|
|
||||||
|
List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo);
|
||||||
|
|
||||||
|
geom->decal_dirty = true;
|
||||||
|
|
||||||
return E; //this element should make freeing faster
|
return E; //this element should make freeing faster
|
||||||
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
|
||||||
|
@ -233,6 +247,17 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
|
||||||
reflection_probe->geometries.erase(E);
|
reflection_probe->geometries.erase(E);
|
||||||
|
|
||||||
geom->reflection_dirty = true;
|
geom->reflection_dirty = true;
|
||||||
|
} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
|
||||||
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||||
|
|
||||||
|
List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata);
|
||||||
|
|
||||||
|
geom->decals.erase(E->get().L);
|
||||||
|
decal->geometries.erase(E);
|
||||||
|
|
||||||
|
geom->decal_dirty = true;
|
||||||
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
|
||||||
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
|
||||||
|
@ -387,6 +412,12 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
|
||||||
reflection_probe_render_list.remove(&reflection_probe->update_list);
|
reflection_probe_render_list.remove(&reflection_probe->update_list);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_DECAL: {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
|
||||||
|
RSG::scene_render->free(decal->instance);
|
||||||
|
|
||||||
|
} break;
|
||||||
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
|
||||||
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(instance->base_data);
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(instance->base_data);
|
||||||
|
@ -476,6 +507,14 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
|
||||||
|
|
||||||
reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
|
reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_DECAL: {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = memnew(InstanceDecalData);
|
||||||
|
decal->owner = instance;
|
||||||
|
instance->base_data = decal;
|
||||||
|
|
||||||
|
decal->instance = RSG::scene_render->decal_instance_create(p_base);
|
||||||
|
} break;
|
||||||
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
|
||||||
InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData);
|
InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData);
|
||||||
|
@ -690,6 +729,12 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible)
|
||||||
instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::INSTANCE_DECAL: {
|
||||||
|
if (instance->octree_id && instance->scenario) {
|
||||||
|
instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
if (instance->octree_id && instance->scenario) {
|
if (instance->octree_id && instance->scenario) {
|
||||||
|
@ -943,6 +988,13 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
||||||
reflection_probe->reflection_dirty = true;
|
reflection_probe->reflection_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_instance->base_type == RS::INSTANCE_DECAL) {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
|
||||||
|
|
||||||
|
RSG::scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
|
||||||
|
}
|
||||||
|
|
||||||
if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
|
if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
|
||||||
|
|
||||||
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
|
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
|
||||||
|
@ -1000,7 +1052,7 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
||||||
uint32_t pairable_mask = 0;
|
uint32_t pairable_mask = 0;
|
||||||
bool pairable = false;
|
bool pairable = false;
|
||||||
|
|
||||||
if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) {
|
if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) {
|
||||||
|
|
||||||
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
|
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
|
||||||
pairable = true;
|
pairable = true;
|
||||||
|
@ -1079,6 +1131,11 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
|
||||||
|
|
||||||
new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
|
new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RenderingServer::INSTANCE_DECAL: {
|
||||||
|
|
||||||
|
new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RenderingServer::INSTANCE_GI_PROBE: {
|
case RenderingServer::INSTANCE_GI_PROBE: {
|
||||||
|
|
||||||
|
@ -2020,6 +2077,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
||||||
light_cull_count = 0;
|
light_cull_count = 0;
|
||||||
|
|
||||||
reflection_probe_cull_count = 0;
|
reflection_probe_cull_count = 0;
|
||||||
|
decal_cull_count = 0;
|
||||||
gi_probe_cull_count = 0;
|
gi_probe_cull_count = 0;
|
||||||
|
|
||||||
//light_samplers_culled=0;
|
//light_samplers_culled=0;
|
||||||
|
@ -2089,6 +2147,18 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) {
|
||||||
|
|
||||||
|
if (decal_cull_count < MAX_DECALS_CULLED) {
|
||||||
|
|
||||||
|
InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
|
||||||
|
|
||||||
|
if (!decal->geometries.empty()) {
|
||||||
|
//do not add this decal if no geometry is affected by it..
|
||||||
|
decal_instance_cull_result[decal_cull_count] = decal->instance;
|
||||||
|
decal_cull_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
|
} else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
|
||||||
|
|
||||||
|
@ -2356,7 +2426,7 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p
|
||||||
/* PROCESS GEOMETRY AND DRAW SCENE */
|
/* PROCESS GEOMETRY AND DRAW SCENE */
|
||||||
|
|
||||||
RENDER_TIMESTAMP("Render Scene ");
|
RENDER_TIMESTAMP("Render Scene ");
|
||||||
RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||||
|
@ -2371,7 +2441,7 @@ void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenar
|
||||||
else
|
else
|
||||||
environment = scenario->fallback_environment;
|
environment = scenario->fallback_environment;
|
||||||
RENDER_TIMESTAMP("Render Empty Scene ");
|
RENDER_TIMESTAMP("Render Empty Scene ");
|
||||||
RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
|
RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
MAX_INSTANCE_CULL = 65536,
|
MAX_INSTANCE_CULL = 65536,
|
||||||
MAX_LIGHTS_CULLED = 4096,
|
MAX_LIGHTS_CULLED = 4096,
|
||||||
MAX_REFLECTION_PROBES_CULLED = 4096,
|
MAX_REFLECTION_PROBES_CULLED = 4096,
|
||||||
|
MAX_DECALS_CULLED = 4096,
|
||||||
MAX_GI_PROBES_CULLED = 4096,
|
MAX_GI_PROBES_CULLED = 4096,
|
||||||
MAX_ROOM_CULL = 32,
|
MAX_ROOM_CULL = 32,
|
||||||
MAX_EXTERIOR_PORTALS = 128,
|
MAX_EXTERIOR_PORTALS = 128,
|
||||||
|
@ -237,6 +238,9 @@ public:
|
||||||
bool can_cast_shadows;
|
bool can_cast_shadows;
|
||||||
bool material_is_animated;
|
bool material_is_animated;
|
||||||
|
|
||||||
|
List<Instance *> decals;
|
||||||
|
bool decal_dirty;
|
||||||
|
|
||||||
List<Instance *> reflection_probes;
|
List<Instance *> reflection_probes;
|
||||||
bool reflection_dirty;
|
bool reflection_dirty;
|
||||||
|
|
||||||
|
@ -252,6 +256,7 @@ public:
|
||||||
can_cast_shadows = true;
|
can_cast_shadows = true;
|
||||||
material_is_animated = true;
|
material_is_animated = true;
|
||||||
gi_probes_dirty = true;
|
gi_probes_dirty = true;
|
||||||
|
decal_dirty = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -279,6 +284,21 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InstanceDecalData : public InstanceBaseData {
|
||||||
|
|
||||||
|
Instance *owner;
|
||||||
|
RID instance;
|
||||||
|
|
||||||
|
struct PairInfo {
|
||||||
|
List<Instance *>::Element *L; //reflection iterator in geometry
|
||||||
|
Instance *geometry;
|
||||||
|
};
|
||||||
|
List<PairInfo> geometries;
|
||||||
|
|
||||||
|
InstanceDecalData() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
|
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
|
||||||
|
|
||||||
struct InstanceLightData : public InstanceBaseData {
|
struct InstanceLightData : public InstanceBaseData {
|
||||||
|
@ -376,7 +396,9 @@ public:
|
||||||
int light_cull_count;
|
int light_cull_count;
|
||||||
int directional_light_count;
|
int directional_light_count;
|
||||||
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
|
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
|
||||||
|
RID decal_instance_cull_result[MAX_DECALS_CULLED];
|
||||||
int reflection_probe_cull_count;
|
int reflection_probe_cull_count;
|
||||||
|
int decal_cull_count;
|
||||||
RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
|
RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
|
||||||
int gi_probe_cull_count;
|
int gi_probe_cull_count;
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,20 @@ public:
|
||||||
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||||
FUNC2(reflection_probe_set_resolution, RID, int)
|
FUNC2(reflection_probe_set_resolution, RID, int)
|
||||||
|
|
||||||
|
/* DECAL API */
|
||||||
|
|
||||||
|
FUNCRID(decal)
|
||||||
|
|
||||||
|
FUNC2(decal_set_extents, RID, const Vector3 &)
|
||||||
|
FUNC3(decal_set_texture, RID, DecalTexture, RID)
|
||||||
|
FUNC2(decal_set_emission_energy, RID, float)
|
||||||
|
FUNC2(decal_set_albedo_mix, RID, float)
|
||||||
|
FUNC2(decal_set_modulate, RID, const Color &)
|
||||||
|
FUNC2(decal_set_cull_mask, RID, uint32_t)
|
||||||
|
FUNC4(decal_set_distance_fade, RID, bool, float, float)
|
||||||
|
FUNC3(decal_set_fade, RID, float, float)
|
||||||
|
FUNC2(decal_set_normal_fade, RID, float)
|
||||||
|
|
||||||
/* BAKED LIGHT API */
|
/* BAKED LIGHT API */
|
||||||
|
|
||||||
FUNCRID(gi_probe)
|
FUNCRID(gi_probe)
|
||||||
|
|
|
@ -461,6 +461,27 @@ public:
|
||||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||||
|
|
||||||
|
/* DECAL API */
|
||||||
|
|
||||||
|
enum DecalTexture {
|
||||||
|
DECAL_TEXTURE_ALBEDO,
|
||||||
|
DECAL_TEXTURE_NORMAL,
|
||||||
|
DECAL_TEXTURE_ORM,
|
||||||
|
DECAL_TEXTURE_EMISSION,
|
||||||
|
DECAL_TEXTURE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual RID decal_create() = 0;
|
||||||
|
virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
|
||||||
|
virtual void decal_set_texture(RID p_decal, DecalTexture p_type, RID p_texture) = 0;
|
||||||
|
virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
|
||||||
|
virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
|
||||||
|
virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
|
||||||
|
virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
|
||||||
|
virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
|
||||||
|
virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
|
||||||
|
virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
|
||||||
|
|
||||||
/* GI PROBE API */
|
/* GI PROBE API */
|
||||||
|
|
||||||
virtual RID gi_probe_create() = 0;
|
virtual RID gi_probe_create() = 0;
|
||||||
|
@ -673,6 +694,7 @@ public:
|
||||||
VIEWPORT_DEBUG_DRAW_SSAO,
|
VIEWPORT_DEBUG_DRAW_SSAO,
|
||||||
VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER,
|
VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER,
|
||||||
VIEWPORT_DEBUG_DRAW_PSSM_SPLITS,
|
VIEWPORT_DEBUG_DRAW_PSSM_SPLITS,
|
||||||
|
VIEWPORT_DEBUG_DRAW_DECAL_ATLAS,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -864,6 +886,7 @@ public:
|
||||||
INSTANCE_PARTICLES,
|
INSTANCE_PARTICLES,
|
||||||
INSTANCE_LIGHT,
|
INSTANCE_LIGHT,
|
||||||
INSTANCE_REFLECTION_PROBE,
|
INSTANCE_REFLECTION_PROBE,
|
||||||
|
INSTANCE_DECAL,
|
||||||
INSTANCE_GI_PROBE,
|
INSTANCE_GI_PROBE,
|
||||||
INSTANCE_LIGHTMAP_CAPTURE,
|
INSTANCE_LIGHTMAP_CAPTURE,
|
||||||
INSTANCE_MAX,
|
INSTANCE_MAX,
|
||||||
|
@ -1163,6 +1186,7 @@ VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
|
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode);
|
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
|
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
|
||||||
|
VARIANT_ENUM_CAST(RenderingServer::DecalTexture);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);
|
VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
|
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
|
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
|
||||||
|
|
Loading…
Reference in New Issue