initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
env.add_source_files(env.servers_sources, "*.cpp")

View File

@@ -0,0 +1,186 @@
/**************************************************************************/
/* camera_attributes_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "camera_attributes_storage.h"
RendererCameraAttributes *RendererCameraAttributes::singleton = nullptr;
uint64_t RendererCameraAttributes::auto_exposure_counter = 2;
RendererCameraAttributes::RendererCameraAttributes() {
singleton = this;
}
RendererCameraAttributes::~RendererCameraAttributes() {
singleton = nullptr;
}
RID RendererCameraAttributes::camera_attributes_allocate() {
return camera_attributes_owner.allocate_rid();
}
void RendererCameraAttributes::camera_attributes_initialize(RID p_rid) {
camera_attributes_owner.initialize_rid(p_rid, CameraAttributes());
}
void RendererCameraAttributes::camera_attributes_free(RID p_rid) {
camera_attributes_owner.free(p_rid);
}
void RendererCameraAttributes::camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
dof_blur_quality = p_quality;
dof_blur_use_jitter = p_use_jitter;
}
void RendererCameraAttributes::camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
dof_blur_bokeh_shape = p_shape;
}
void RendererCameraAttributes::camera_attributes_set_dof_blur(RID p_camera_attributes, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL(cam_attributes);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" && (p_far_enable || p_near_enable)) {
WARN_PRINT_ONCE_ED("DoF blur is only available when using the Forward+ or Mobile renderers.");
}
#endif
cam_attributes->dof_blur_far_enabled = p_far_enable;
cam_attributes->dof_blur_far_distance = p_far_distance;
cam_attributes->dof_blur_far_transition = p_far_transition;
cam_attributes->dof_blur_near_enabled = p_near_enable;
cam_attributes->dof_blur_near_distance = p_near_distance;
cam_attributes->dof_blur_near_transition = p_near_transition;
cam_attributes->dof_blur_amount = p_amount;
}
bool RendererCameraAttributes::camera_attributes_get_dof_far_enabled(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, false);
return cam_attributes->dof_blur_far_enabled;
}
float RendererCameraAttributes::camera_attributes_get_dof_far_distance(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->dof_blur_far_distance;
}
float RendererCameraAttributes::camera_attributes_get_dof_far_transition(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->dof_blur_far_transition;
}
bool RendererCameraAttributes::camera_attributes_get_dof_near_enabled(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, false);
return cam_attributes->dof_blur_near_enabled;
}
float RendererCameraAttributes::camera_attributes_get_dof_near_distance(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->dof_blur_near_distance;
}
float RendererCameraAttributes::camera_attributes_get_dof_near_transition(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->dof_blur_near_transition;
}
float RendererCameraAttributes::camera_attributes_get_dof_blur_amount(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->dof_blur_amount;
}
void RendererCameraAttributes::camera_attributes_set_exposure(RID p_camera_attributes, float p_multiplier, float p_exposure_normalization) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL(cam_attributes);
cam_attributes->exposure_multiplier = p_multiplier;
cam_attributes->exposure_normalization = p_exposure_normalization;
}
float RendererCameraAttributes::camera_attributes_get_exposure_normalization_factor(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 1.0);
return cam_attributes->exposure_multiplier * cam_attributes->exposure_normalization;
}
void RendererCameraAttributes::camera_attributes_set_auto_exposure(RID p_camera_attributes, bool p_enable, float p_min_sensitivity, float p_max_sensitivity, float p_speed, float p_scale) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL(cam_attributes);
if (!cam_attributes->use_auto_exposure && p_enable) {
cam_attributes->auto_exposure_version = ++auto_exposure_counter;
}
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" && p_enable) {
WARN_PRINT_ONCE_ED("Auto exposure is only available when using the Forward+ or Mobile renderers.");
}
#endif
cam_attributes->use_auto_exposure = p_enable;
cam_attributes->auto_exposure_min_sensitivity = p_min_sensitivity;
cam_attributes->auto_exposure_max_sensitivity = p_max_sensitivity;
cam_attributes->auto_exposure_adjust_speed = p_speed;
cam_attributes->auto_exposure_scale = p_scale;
}
float RendererCameraAttributes::camera_attributes_get_auto_exposure_min_sensitivity(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->auto_exposure_min_sensitivity;
}
float RendererCameraAttributes::camera_attributes_get_auto_exposure_max_sensitivity(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->auto_exposure_max_sensitivity;
}
float RendererCameraAttributes::camera_attributes_get_auto_exposure_adjust_speed(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->auto_exposure_adjust_speed;
}
float RendererCameraAttributes::camera_attributes_get_auto_exposure_scale(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0.0);
return cam_attributes->auto_exposure_scale;
}
uint64_t RendererCameraAttributes::camera_attributes_get_auto_exposure_version(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
ERR_FAIL_NULL_V(cam_attributes, 0);
return cam_attributes->auto_exposure_version;
}

View File

@@ -0,0 +1,126 @@
/**************************************************************************/
/* camera_attributes_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/rid_owner.h"
#include "servers/rendering_server.h"
class RendererCameraAttributes {
private:
static RendererCameraAttributes *singleton;
struct CameraAttributes {
float exposure_multiplier = 1.0;
float exposure_normalization = 1.0;
float exposure_sensitivity = 100.0; // In ISO.
bool use_auto_exposure = false;
float auto_exposure_min_sensitivity = 50.0;
float auto_exposure_max_sensitivity = 800.0;
float auto_exposure_adjust_speed = 1.0;
float auto_exposure_scale = 1.0;
uint64_t auto_exposure_version = 0;
bool dof_blur_far_enabled = false;
float dof_blur_far_distance = 10;
float dof_blur_far_transition = 5;
bool dof_blur_near_enabled = false;
float dof_blur_near_distance = 2;
float dof_blur_near_transition = 1;
float dof_blur_amount = 0.1;
};
RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
bool dof_blur_use_jitter = false;
static uint64_t auto_exposure_counter;
mutable RID_Owner<CameraAttributes, true> camera_attributes_owner;
public:
static RendererCameraAttributes *get_singleton() { return singleton; }
RendererCameraAttributes();
~RendererCameraAttributes();
CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); }
bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); }
RID camera_attributes_allocate();
void camera_attributes_initialize(RID p_rid);
void camera_attributes_free(RID p_rid);
void camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
void camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);
void camera_attributes_set_dof_blur(RID p_camera_attributes, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount);
bool camera_attributes_get_dof_far_enabled(RID p_camera_attributes);
float camera_attributes_get_dof_far_distance(RID p_camera_attributes);
float camera_attributes_get_dof_far_transition(RID p_camera_attributes);
bool camera_attributes_get_dof_near_enabled(RID p_camera_attributes);
float camera_attributes_get_dof_near_distance(RID p_camera_attributes);
float camera_attributes_get_dof_near_transition(RID p_camera_attributes);
float camera_attributes_get_dof_blur_amount(RID p_camera_attributes);
_FORCE_INLINE_ bool camera_attributes_uses_dof(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
return cam_attributes && (cam_attributes->dof_blur_near_enabled || cam_attributes->dof_blur_far_enabled) && cam_attributes->dof_blur_amount > 0.0;
}
void camera_attributes_set_exposure(RID p_camera_attributes, float p_multiplier, float p_exposure_normalization);
float camera_attributes_get_exposure_normalization_factor(RID p_camera_attributes);
void camera_attributes_set_auto_exposure(RID p_camera_attributes, bool p_enable, float p_min_sensitivity, float p_max_sensitivity, float p_speed, float p_scale);
float camera_attributes_get_auto_exposure_min_sensitivity(RID p_camera_attributes);
float camera_attributes_get_auto_exposure_max_sensitivity(RID p_camera_attributes);
float camera_attributes_get_auto_exposure_adjust_speed(RID p_camera_attributes);
float camera_attributes_get_auto_exposure_scale(RID p_camera_attributes);
uint64_t camera_attributes_get_auto_exposure_version(RID p_camera_attributes);
_FORCE_INLINE_ bool camera_attributes_uses_auto_exposure(RID p_camera_attributes) {
CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
return cam_attributes && cam_attributes->use_auto_exposure;
}
_FORCE_INLINE_ RS::DOFBlurQuality camera_attributes_get_dof_blur_quality() {
return dof_blur_quality;
}
_FORCE_INLINE_ RS::DOFBokehShape camera_attributes_get_dof_blur_bokeh_shape() {
return dof_blur_bokeh_shape;
}
_FORCE_INLINE_ bool camera_attributes_get_dof_blur_use_jitter() {
return dof_blur_use_jitter;
}
};

View File

@@ -0,0 +1,194 @@
/**************************************************************************/
/* compositor_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "compositor_storage.h"
// Storage
RendererCompositorStorage *RendererCompositorStorage::singleton = nullptr;
RendererCompositorStorage::RendererCompositorStorage() {
singleton = this;
}
RendererCompositorStorage::~RendererCompositorStorage() {
singleton = nullptr;
}
// Compositor effect
RID RendererCompositorStorage::compositor_effect_allocate() {
return compositor_effects_owner.allocate_rid();
}
void RendererCompositorStorage::compositor_effect_initialize(RID p_rid) {
compositor_effects_owner.initialize_rid(p_rid, CompositorEffect());
}
void RendererCompositorStorage::compositor_effect_free(RID p_rid) {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_rid);
ERR_FAIL_NULL(effect);
// Remove this RID from any compositor that uses it.
for (const RID &compositor_rid : compositor_owner.get_owned_list()) {
Compositor *compositor = compositor_owner.get_or_null(compositor_rid);
if (compositor) {
compositor->compositor_effects.erase(p_rid);
}
}
// Update motion vector count if needed.
if (effect->is_enabled && effect->flags.has_flag(RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) {
num_compositor_effects_with_motion_vectors--;
}
compositor_effects_owner.free(p_rid);
}
void RendererCompositorStorage::compositor_effect_set_callback(RID p_effect, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback) {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL(effect);
effect->callback_type = p_callback_type;
effect->callback = p_callback;
}
void RendererCompositorStorage::compositor_effect_set_enabled(RID p_effect, bool p_enabled) {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL(effect);
if (effect->is_enabled != p_enabled && effect->flags.has_flag(RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) {
if (p_enabled) {
num_compositor_effects_with_motion_vectors++;
} else {
num_compositor_effects_with_motion_vectors--;
}
}
effect->is_enabled = p_enabled;
}
bool RendererCompositorStorage::compositor_effect_get_enabled(RID p_effect) const {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL_V(effect, false);
return effect->is_enabled;
}
RS::CompositorEffectCallbackType RendererCompositorStorage::compositor_effect_get_callback_type(RID p_effect) const {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL_V(effect, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_MAX);
return effect->callback_type;
}
Callable RendererCompositorStorage::compositor_effect_get_callback(RID p_effect) const {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL_V(effect, Callable());
return effect->callback;
}
void RendererCompositorStorage::compositor_effect_set_flag(RID p_effect, RS::CompositorEffectFlags p_flag, bool p_set) {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL(effect);
if (effect->is_enabled && p_flag == RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS) {
bool was_set = effect->flags.has_flag(RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS);
if (was_set != p_set) {
if (p_set) {
num_compositor_effects_with_motion_vectors++;
} else {
num_compositor_effects_with_motion_vectors--;
}
}
}
if (p_set) {
effect->flags.set_flag(p_flag);
} else {
effect->flags.clear_flag(p_flag);
}
}
bool RendererCompositorStorage::compositor_effect_get_flag(RID p_effect, RS::CompositorEffectFlags p_flag) const {
CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect);
ERR_FAIL_NULL_V(effect, false);
return effect->flags.has_flag(p_flag);
}
// Compositor
RID RendererCompositorStorage::compositor_allocate() {
return compositor_owner.allocate_rid();
}
void RendererCompositorStorage::compositor_initialize(RID p_rid) {
compositor_owner.initialize_rid(p_rid, Compositor());
}
void RendererCompositorStorage::compositor_free(RID p_rid) {
compositor_owner.free(p_rid);
}
// compositor effects
void RendererCompositorStorage::compositor_set_compositor_effects(RID p_compositor, const Vector<RID> &p_effects) {
Compositor *compositor = compositor_owner.get_or_null(p_compositor);
ERR_FAIL_NULL(compositor);
compositor->compositor_effects.clear();
for (const RID &effect : p_effects) {
if (is_compositor_effect(effect)) {
compositor->compositor_effects.push_back(effect);
}
}
}
Vector<RID> RendererCompositorStorage::compositor_get_compositor_effects(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type, bool p_enabled_only) const {
Compositor *compositor = compositor_owner.get_or_null(p_compositor);
ERR_FAIL_NULL_V(compositor, Vector<RID>());
if (p_enabled_only || p_callback_type != RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY) {
Vector<RID> effects;
for (RID rid : compositor->compositor_effects) {
if ((!p_enabled_only || compositor_effect_get_enabled(rid)) && (p_callback_type == RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY || compositor_effect_get_callback_type(rid) == p_callback_type)) {
effects.push_back(rid);
}
}
return effects;
} else {
return compositor->compositor_effects;
}
}

View File

@@ -0,0 +1,97 @@
/**************************************************************************/
/* compositor_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/rid_owner.h"
#include "servers/rendering_server.h"
class RendererCompositorStorage {
private:
static RendererCompositorStorage *singleton;
int num_compositor_effects_with_motion_vectors = 0;
// Compositor effect
struct CompositorEffect {
bool is_enabled = true;
RS::CompositorEffectCallbackType callback_type;
Callable callback;
BitField<RS::CompositorEffectFlags> flags = {};
};
mutable RID_Owner<CompositorEffect, true> compositor_effects_owner;
// Compositor
struct Compositor {
// Compositor effects
Vector<RID> compositor_effects;
};
mutable RID_Owner<Compositor, true> compositor_owner;
public:
static RendererCompositorStorage *get_singleton() { return singleton; }
int get_num_compositor_effects_with_motion_vectors() const { return num_compositor_effects_with_motion_vectors; }
RendererCompositorStorage();
virtual ~RendererCompositorStorage();
// Compositor effect
RID compositor_effect_allocate();
void compositor_effect_initialize(RID p_rid);
void compositor_effect_free(RID p_rid);
bool is_compositor_effect(RID p_effect) const {
return compositor_effects_owner.owns(p_effect);
}
void compositor_effect_set_enabled(RID p_effect, bool p_enabled);
bool compositor_effect_get_enabled(RID p_effect) const;
void compositor_effect_set_callback(RID p_effect, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback);
RS::CompositorEffectCallbackType compositor_effect_get_callback_type(RID p_effect) const;
Callable compositor_effect_get_callback(RID p_effect) const;
void compositor_effect_set_flag(RID p_effect, RS::CompositorEffectFlags p_flag, bool p_set);
bool compositor_effect_get_flag(RID p_effect, RS::CompositorEffectFlags p_flag) const;
// Compositor
RID compositor_allocate();
void compositor_initialize(RID p_rid);
void compositor_free(RID p_rid);
bool is_compositor(RID p_compositor) const {
return compositor_owner.owns(p_compositor);
}
void compositor_set_compositor_effects(RID p_compositor, const Vector<RID> &p_effects);
Vector<RID> compositor_get_compositor_effects(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type = RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY, bool p_enabled_only = true) const;
};

View File

@@ -0,0 +1,831 @@
/**************************************************************************/
/* environment_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "environment_storage.h"
// Storage
RendererEnvironmentStorage *RendererEnvironmentStorage::singleton = nullptr;
RendererEnvironmentStorage::RendererEnvironmentStorage() {
singleton = this;
}
RendererEnvironmentStorage::~RendererEnvironmentStorage() {
singleton = nullptr;
}
// Environment
RID RendererEnvironmentStorage::environment_allocate() {
return environment_owner.allocate_rid();
}
void RendererEnvironmentStorage::environment_initialize(RID p_rid) {
environment_owner.initialize_rid(p_rid, Environment());
}
void RendererEnvironmentStorage::environment_free(RID p_rid) {
environment_owner.free(p_rid);
}
// Background
void RendererEnvironmentStorage::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->background = p_bg;
}
void RendererEnvironmentStorage::environment_set_sky(RID p_env, RID p_sky) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->sky = p_sky;
}
void RendererEnvironmentStorage::environment_set_sky_custom_fov(RID p_env, float p_scale) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->sky_custom_fov = p_scale;
}
void RendererEnvironmentStorage::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->sky_orientation = p_orientation;
}
void RendererEnvironmentStorage::environment_set_bg_color(RID p_env, const Color &p_color) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->bg_color = p_color;
}
void RendererEnvironmentStorage::environment_set_bg_energy(RID p_env, float p_multiplier, float p_intensity) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->bg_energy_multiplier = p_multiplier;
env->bg_intensity = p_intensity;
}
void RendererEnvironmentStorage::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->canvas_max_layer = p_max_layer;
}
void RendererEnvironmentStorage::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->ambient_light = p_color;
env->ambient_source = p_ambient;
env->ambient_light_energy = p_energy;
env->ambient_sky_contribution = p_sky_contribution;
env->reflection_source = p_reflection_source;
}
RS::EnvironmentBG RendererEnvironmentStorage::environment_get_background(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_BG_CLEAR_COLOR);
return env->background;
}
RID RendererEnvironmentStorage::environment_get_sky(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RID());
return env->sky;
}
float RendererEnvironmentStorage::environment_get_sky_custom_fov(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->sky_custom_fov;
}
Basis RendererEnvironmentStorage::environment_get_sky_orientation(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Basis());
return env->sky_orientation;
}
Color RendererEnvironmentStorage::environment_get_bg_color(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color());
return env->bg_color;
}
float RendererEnvironmentStorage::environment_get_bg_energy_multiplier(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->bg_energy_multiplier;
}
float RendererEnvironmentStorage::environment_get_bg_intensity(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->bg_intensity;
}
int RendererEnvironmentStorage::environment_get_canvas_max_layer(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0);
return env->canvas_max_layer;
}
RS::EnvironmentAmbientSource RendererEnvironmentStorage::environment_get_ambient_source(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_AMBIENT_SOURCE_BG);
return env->ambient_source;
}
Color RendererEnvironmentStorage::environment_get_ambient_light(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color());
return env->ambient_light;
}
float RendererEnvironmentStorage::environment_get_ambient_light_energy(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->ambient_light_energy;
}
float RendererEnvironmentStorage::environment_get_ambient_sky_contribution(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->ambient_sky_contribution;
}
RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_reflection_source(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_REFLECTION_SOURCE_BG);
return env->reflection_source;
}
void RendererEnvironmentStorage::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->camera_feed_id = p_camera_feed_id;
}
int RendererEnvironmentStorage::environment_get_camera_feed_id(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, -1);
return env->camera_feed_id;
}
// Tonemap
void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->exposure = p_exposure;
env->tone_mapper = p_tone_mapper;
env->white = p_white;
}
RS::EnvironmentToneMapper RendererEnvironmentStorage::environment_get_tone_mapper(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_TONE_MAPPER_LINEAR);
return env->tone_mapper;
}
float RendererEnvironmentStorage::environment_get_exposure(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->exposure;
}
float RendererEnvironmentStorage::environment_get_white(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->white;
}
// Fog
void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->fog_enabled = p_enable;
env->fog_mode = p_mode;
env->fog_light_color = p_light_color;
env->fog_light_energy = p_light_energy;
env->fog_sun_scatter = p_sun_scatter;
env->fog_density = p_density;
env->fog_height = p_height;
env->fog_height_density = p_height_density;
env->fog_aerial_perspective = p_fog_aerial_perspective;
env->fog_sky_affect = p_sky_affect;
}
bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->fog_enabled;
}
RS::EnvironmentFogMode RendererEnvironmentStorage::environment_get_fog_mode(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_FOG_MODE_EXPONENTIAL);
return env->fog_mode;
}
Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color(0.5, 0.6, 0.7));
return env->fog_light_color;
}
float RendererEnvironmentStorage::environment_get_fog_light_energy(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->fog_light_energy;
}
float RendererEnvironmentStorage::environment_get_fog_sun_scatter(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_sun_scatter;
}
float RendererEnvironmentStorage::environment_get_fog_density(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.001);
return env->fog_density;
}
float RendererEnvironmentStorage::environment_get_fog_height(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_height;
}
float RendererEnvironmentStorage::environment_get_fog_height_density(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_height_density;
}
float RendererEnvironmentStorage::environment_get_fog_aerial_perspective(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_aerial_perspective;
}
float RendererEnvironmentStorage::environment_get_fog_sky_affect(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_sky_affect;
}
// Depth Fog
void RendererEnvironmentStorage::environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->fog_depth_curve = p_curve;
env->fog_depth_begin = p_begin;
env->fog_depth_end = p_end;
}
float RendererEnvironmentStorage::environment_get_fog_depth_curve(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_depth_curve;
}
float RendererEnvironmentStorage::environment_get_fog_depth_begin(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_depth_begin;
}
float RendererEnvironmentStorage::environment_get_fog_depth_end(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->fog_depth_end;
}
// Volumetric Fog
void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() != "forward_plus" && p_enable) {
WARN_PRINT_ONCE_ED("Volumetric fog can only be enabled when using the Forward+ renderer.");
}
#endif
env->volumetric_fog_enabled = p_enable;
env->volumetric_fog_density = p_density;
env->volumetric_fog_scattering = p_albedo;
env->volumetric_fog_emission = p_emission;
env->volumetric_fog_emission_energy = p_emission_energy;
env->volumetric_fog_anisotropy = p_anisotropy;
env->volumetric_fog_length = p_length;
env->volumetric_fog_detail_spread = p_detail_spread;
env->volumetric_fog_gi_inject = p_gi_inject;
env->volumetric_fog_temporal_reprojection = p_temporal_reprojection;
env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
env->volumetric_fog_ambient_inject = p_ambient_inject;
env->volumetric_fog_sky_affect = p_sky_affect;
}
bool RendererEnvironmentStorage::environment_get_volumetric_fog_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->volumetric_fog_enabled;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_density(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.01);
return env->volumetric_fog_density;
}
Color RendererEnvironmentStorage::environment_get_volumetric_fog_scattering(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color(1, 1, 1));
return env->volumetric_fog_scattering;
}
Color RendererEnvironmentStorage::environment_get_volumetric_fog_emission(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color(0, 0, 0));
return env->volumetric_fog_emission;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_emission_energy(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->volumetric_fog_emission_energy;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_anisotropy(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.2);
return env->volumetric_fog_anisotropy;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_length(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 64.0);
return env->volumetric_fog_length;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_detail_spread(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 2.0);
return env->volumetric_fog_detail_spread;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_gi_inject(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->volumetric_fog_gi_inject;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_sky_affect(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->volumetric_fog_sky_affect;
}
bool RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, true);
return env->volumetric_fog_temporal_reprojection;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.9);
return env->volumetric_fog_temporal_reprojection_amount;
}
float RendererEnvironmentStorage::environment_get_volumetric_fog_ambient_inject(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->volumetric_fog_ambient_inject;
}
// GLOW
void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
env->glow_enabled = p_enable;
env->glow_levels = p_levels;
env->glow_intensity = p_intensity;
env->glow_strength = p_strength;
env->glow_mix = p_mix;
env->glow_bloom = p_bloom_threshold;
env->glow_blend_mode = p_blend_mode;
env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
env->glow_map_strength = p_glow_map_strength;
env->glow_map = p_glow_map;
}
bool RendererEnvironmentStorage::environment_get_glow_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->glow_enabled;
}
Vector<float> RendererEnvironmentStorage::environment_get_glow_levels(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Vector<float>());
return env->glow_levels;
}
float RendererEnvironmentStorage::environment_get_glow_intensity(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.8);
return env->glow_intensity;
}
float RendererEnvironmentStorage::environment_get_glow_strength(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->glow_strength;
}
float RendererEnvironmentStorage::environment_get_glow_bloom(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->glow_bloom;
}
float RendererEnvironmentStorage::environment_get_glow_mix(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.01);
return env->glow_mix;
}
RS::EnvironmentGlowBlendMode RendererEnvironmentStorage::environment_get_glow_blend_mode(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT);
return env->glow_blend_mode;
}
float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_threshold(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->glow_hdr_bleed_threshold;
}
float RendererEnvironmentStorage::environment_get_glow_hdr_luminance_cap(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 12.0);
return env->glow_hdr_luminance_cap;
}
float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_scale(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 2.0);
return env->glow_hdr_bleed_scale;
}
float RendererEnvironmentStorage::environment_get_glow_map_strength(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->glow_map_strength;
}
RID RendererEnvironmentStorage::environment_get_glow_map(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RID());
return env->glow_map;
}
// SSR
void RendererEnvironmentStorage::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() != "forward_plus" && p_enable) {
WARN_PRINT_ONCE_ED("Screen-space reflections (SSR) can only be enabled when using the Forward+ renderer.");
}
#endif
env->ssr_enabled = p_enable;
env->ssr_max_steps = p_max_steps;
env->ssr_fade_in = p_fade_int;
env->ssr_fade_out = p_fade_out;
env->ssr_depth_tolerance = p_depth_tolerance;
}
bool RendererEnvironmentStorage::environment_get_ssr_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->ssr_enabled;
}
int RendererEnvironmentStorage::environment_get_ssr_max_steps(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 64);
return env->ssr_max_steps;
}
float RendererEnvironmentStorage::environment_get_ssr_fade_in(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.15);
return env->ssr_fade_in;
}
float RendererEnvironmentStorage::environment_get_ssr_fade_out(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 2.0);
return env->ssr_fade_out;
}
float RendererEnvironmentStorage::environment_get_ssr_depth_tolerance(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.2);
return env->ssr_depth_tolerance;
}
// SSAO
void RendererEnvironmentStorage::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() != "forward_plus" && p_enable) {
WARN_PRINT_ONCE_ED("Screen-space ambient occlusion (SSAO) can only be enabled when using the Forward+ renderer.");
}
#endif
env->ssao_enabled = p_enable;
env->ssao_radius = p_radius;
env->ssao_intensity = p_intensity;
env->ssao_power = p_power;
env->ssao_detail = p_detail;
env->ssao_horizon = p_horizon;
env->ssao_sharpness = p_sharpness;
env->ssao_direct_light_affect = p_light_affect;
env->ssao_ao_channel_affect = p_ao_channel_affect;
}
bool RendererEnvironmentStorage::environment_get_ssao_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->ssao_enabled;
}
float RendererEnvironmentStorage::environment_get_ssao_radius(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->ssao_radius;
}
float RendererEnvironmentStorage::environment_get_ssao_intensity(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 2.0);
return env->ssao_intensity;
}
float RendererEnvironmentStorage::environment_get_ssao_power(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.5);
return env->ssao_power;
}
float RendererEnvironmentStorage::environment_get_ssao_detail(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.5);
return env->ssao_detail;
}
float RendererEnvironmentStorage::environment_get_ssao_horizon(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.06);
return env->ssao_horizon;
}
float RendererEnvironmentStorage::environment_get_ssao_sharpness(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.98);
return env->ssao_sharpness;
}
float RendererEnvironmentStorage::environment_get_ssao_direct_light_affect(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->ssao_direct_light_affect;
}
float RendererEnvironmentStorage::environment_get_ssao_ao_channel_affect(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.0);
return env->ssao_ao_channel_affect;
}
// SSIL
void RendererEnvironmentStorage::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() != "forward_plus" && p_enable) {
WARN_PRINT_ONCE_ED("Screen-space indirect lighting (SSIL) can only be enabled when using the Forward+ renderer.");
}
#endif
env->ssil_enabled = p_enable;
env->ssil_radius = p_radius;
env->ssil_intensity = p_intensity;
env->ssil_sharpness = p_sharpness;
env->ssil_normal_rejection = p_normal_rejection;
}
bool RendererEnvironmentStorage::environment_get_ssil_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->ssil_enabled;
}
float RendererEnvironmentStorage::environment_get_ssil_radius(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 5.0);
return env->ssil_radius;
}
float RendererEnvironmentStorage::environment_get_ssil_intensity(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->ssil_intensity;
}
float RendererEnvironmentStorage::environment_get_ssil_sharpness(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.98);
return env->ssil_sharpness;
}
float RendererEnvironmentStorage::environment_get_ssil_normal_rejection(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->ssil_normal_rejection;
}
// SDFGI
void RendererEnvironmentStorage::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
#ifdef DEBUG_ENABLED
if (OS::get_singleton()->get_current_rendering_method() != "forward_plus" && p_enable) {
WARN_PRINT_ONCE_ED("SDFGI can only be enabled when using the Forward+ renderer.");
}
#endif
env->sdfgi_enabled = p_enable;
env->sdfgi_cascades = p_cascades;
env->sdfgi_min_cell_size = p_min_cell_size;
env->sdfgi_use_occlusion = p_use_occlusion;
env->sdfgi_bounce_feedback = p_bounce_feedback;
env->sdfgi_read_sky_light = p_read_sky;
env->sdfgi_energy = p_energy;
env->sdfgi_normal_bias = p_normal_bias;
env->sdfgi_probe_bias = p_probe_bias;
env->sdfgi_y_scale = p_y_scale;
}
bool RendererEnvironmentStorage::environment_get_sdfgi_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->sdfgi_enabled;
}
int RendererEnvironmentStorage::environment_get_sdfgi_cascades(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 4);
return env->sdfgi_cascades;
}
float RendererEnvironmentStorage::environment_get_sdfgi_min_cell_size(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.2);
return env->sdfgi_min_cell_size;
}
bool RendererEnvironmentStorage::environment_get_sdfgi_use_occlusion(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->sdfgi_use_occlusion;
}
float RendererEnvironmentStorage::environment_get_sdfgi_bounce_feedback(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 0.5);
return env->sdfgi_bounce_feedback;
}
bool RendererEnvironmentStorage::environment_get_sdfgi_read_sky_light(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, true);
return env->sdfgi_read_sky_light;
}
float RendererEnvironmentStorage::environment_get_sdfgi_energy(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->sdfgi_energy;
}
float RendererEnvironmentStorage::environment_get_sdfgi_normal_bias(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.1);
return env->sdfgi_normal_bias;
}
float RendererEnvironmentStorage::environment_get_sdfgi_probe_bias(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.1);
return env->sdfgi_probe_bias;
}
RS::EnvironmentSDFGIYScale RendererEnvironmentStorage::environment_get_sdfgi_y_scale(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RS::ENV_SDFGI_Y_SCALE_75_PERCENT);
return env->sdfgi_y_scale;
}
// Adjustments
void RendererEnvironmentStorage::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->adjustments_enabled = p_enable;
env->adjustments_brightness = p_brightness;
env->adjustments_contrast = p_contrast;
env->adjustments_saturation = p_saturation;
env->use_1d_color_correction = p_use_1d_color_correction;
env->color_correction = p_color_correction;
}
bool RendererEnvironmentStorage::environment_get_adjustments_enabled(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->adjustments_enabled;
}
float RendererEnvironmentStorage::environment_get_adjustments_brightness(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->adjustments_brightness;
}
float RendererEnvironmentStorage::environment_get_adjustments_contrast(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->adjustments_contrast;
}
float RendererEnvironmentStorage::environment_get_adjustments_saturation(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, 1.0);
return env->adjustments_saturation;
}
bool RendererEnvironmentStorage::environment_get_use_1d_color_correction(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, false);
return env->use_1d_color_correction;
}
RID RendererEnvironmentStorage::environment_get_color_correction(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, RID());
return env->color_correction;
}

View File

@@ -0,0 +1,306 @@
/**************************************************************************/
/* environment_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/rid_owner.h"
#include "servers/rendering_server.h"
class RendererEnvironmentStorage {
private:
static RendererEnvironmentStorage *singleton;
// Environment
struct Environment {
// Note, we capture and store all environment parameters received from Godot here.
// Not all renderers support all effects and should just ignore the bits they don't support.
// Background
RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
RID sky;
float sky_custom_fov = 0.0;
Basis sky_orientation;
Color bg_color;
float bg_energy_multiplier = 1.0;
float bg_intensity = 1.0; // Measured in nits or candela/m^2. Default to 1.0 so this doesn't impact rendering when Physical Light Units disabled.
int canvas_max_layer = 0;
RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
Color ambient_light;
float ambient_light_energy = 1.0;
float ambient_sky_contribution = 1.0;
RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
int camera_feed_id = 0;
// Tonemap
RS::EnvironmentToneMapper tone_mapper;
float exposure = 1.0;
float white = 1.0;
// Fog
bool fog_enabled = false;
RS::EnvironmentFogMode fog_mode = RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL;
Color fog_light_color = Color(0.518, 0.553, 0.608);
float fog_light_energy = 1.0;
float fog_sun_scatter = 0.0;
float fog_density = 0.01;
float fog_sky_affect = 1.0;
float fog_height = 0.0;
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
// Depth Fog
float fog_depth_curve = 1.0;
float fog_depth_begin = 10.0;
float fog_depth_end = 100.0;
// Volumetric Fog
bool volumetric_fog_enabled = false;
float volumetric_fog_density = 0.01;
Color volumetric_fog_scattering = Color(1, 1, 1);
Color volumetric_fog_emission = Color(0, 0, 0);
float volumetric_fog_emission_energy = 0.0;
float volumetric_fog_anisotropy = 0.2;
float volumetric_fog_length = 64.0;
float volumetric_fog_detail_spread = 2.0;
float volumetric_fog_gi_inject = 1.0;
float volumetric_fog_ambient_inject = 0.0;
float volumetric_fog_sky_affect = 1.0;
bool volumetric_fog_temporal_reprojection = true;
float volumetric_fog_temporal_reprojection_amount = 0.9;
// Glow
bool glow_enabled = false;
Vector<float> glow_levels;
float glow_intensity = 0.8;
float glow_strength = 1.0;
float glow_bloom = 0.0;
float glow_mix = 0.01;
RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
float glow_hdr_bleed_threshold = 1.0;
float glow_hdr_luminance_cap = 12.0;
float glow_hdr_bleed_scale = 2.0;
float glow_map_strength = 0.0f; // 1.0f in GLES3 ??
RID glow_map;
// SSR
bool ssr_enabled = false;
int ssr_max_steps = 64;
float ssr_fade_in = 0.15;
float ssr_fade_out = 2.0;
float ssr_depth_tolerance = 0.2;
// SSAO
bool ssao_enabled = false;
float ssao_radius = 1.0;
float ssao_intensity = 2.0;
float ssao_power = 1.5;
float ssao_detail = 0.5;
float ssao_horizon = 0.06;
float ssao_sharpness = 0.98;
float ssao_direct_light_affect = 0.0;
float ssao_ao_channel_affect = 0.0;
// SSIL
bool ssil_enabled = false;
float ssil_radius = 5.0;
float ssil_intensity = 1.0;
float ssil_sharpness = 0.98;
float ssil_normal_rejection = 1.0;
// SDFGI
bool sdfgi_enabled = false;
int sdfgi_cascades = 4;
float sdfgi_min_cell_size = 0.2;
bool sdfgi_use_occlusion = false;
float sdfgi_bounce_feedback = 0.5;
bool sdfgi_read_sky_light = true;
float sdfgi_energy = 1.0;
float sdfgi_normal_bias = 1.1;
float sdfgi_probe_bias = 1.1;
RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT;
// Adjustments
bool adjustments_enabled = false;
float adjustments_brightness = 1.0f;
float adjustments_contrast = 1.0f;
float adjustments_saturation = 1.0f;
bool use_1d_color_correction = false;
RID color_correction;
};
mutable RID_Owner<Environment, true> environment_owner;
public:
static RendererEnvironmentStorage *get_singleton() { return singleton; }
RendererEnvironmentStorage();
virtual ~RendererEnvironmentStorage();
// Environment
RID environment_allocate();
void environment_initialize(RID p_rid);
void environment_free(RID p_rid);
bool is_environment(RID p_environment) const {
return environment_owner.owns(p_environment);
}
// Background
void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
void environment_set_sky(RID p_env, RID p_sky);
void environment_set_sky_custom_fov(RID p_env, float p_scale);
void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
void environment_set_bg_color(RID p_env, const Color &p_color);
void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value);
void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
int environment_get_camera_feed_id(RID p_env) const;
RS::EnvironmentBG environment_get_background(RID p_env) const;
RID environment_get_sky(RID p_env) const;
float environment_get_sky_custom_fov(RID p_env) const;
Basis environment_get_sky_orientation(RID p_env) const;
Color environment_get_bg_color(RID p_env) const;
float environment_get_bg_energy_multiplier(RID p_env) const;
float environment_get_bg_intensity(RID p_env) const;
int environment_get_canvas_max_layer(RID p_env) const;
RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
Color environment_get_ambient_light(RID p_env) const;
float environment_get_ambient_light_energy(RID p_env) const;
float environment_get_ambient_sky_contribution(RID p_env) const;
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
// Tonemap
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
float environment_get_exposure(RID p_env) const;
float environment_get_white(RID p_env) const;
// Fog
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode);
bool environment_get_fog_enabled(RID p_env) const;
RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
float environment_get_fog_sun_scatter(RID p_env) const;
float environment_get_fog_density(RID p_env) const;
float environment_get_fog_sky_affect(RID p_env) const;
float environment_get_fog_height(RID p_env) const;
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
// Depth Fog
void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end);
float environment_get_fog_depth_curve(RID p_env) const;
float environment_get_fog_depth_begin(RID p_env) const;
float environment_get_fog_depth_end(RID p_env) const;
// Volumetric Fog
void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect);
bool environment_get_volumetric_fog_enabled(RID p_env) const;
float environment_get_volumetric_fog_density(RID p_env) const;
Color environment_get_volumetric_fog_scattering(RID p_env) const;
Color environment_get_volumetric_fog_emission(RID p_env) const;
float environment_get_volumetric_fog_emission_energy(RID p_env) const;
float environment_get_volumetric_fog_anisotropy(RID p_env) const;
float environment_get_volumetric_fog_length(RID p_env) const;
float environment_get_volumetric_fog_detail_spread(RID p_env) const;
float environment_get_volumetric_fog_gi_inject(RID p_env) const;
float environment_get_volumetric_fog_sky_affect(RID p_env) const;
bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const;
float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const;
float environment_get_volumetric_fog_ambient_inject(RID p_env) const;
// GLOW
void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
bool environment_get_glow_enabled(RID p_env) const;
Vector<float> environment_get_glow_levels(RID p_env) const;
float environment_get_glow_intensity(RID p_env) const;
float environment_get_glow_strength(RID p_env) const;
float environment_get_glow_bloom(RID p_env) const;
float environment_get_glow_mix(RID p_env) const;
RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const;
float environment_get_glow_hdr_bleed_threshold(RID p_env) const;
float environment_get_glow_hdr_luminance_cap(RID p_env) const;
float environment_get_glow_hdr_bleed_scale(RID p_env) const;
float environment_get_glow_map_strength(RID p_env) const;
RID environment_get_glow_map(RID p_env) const;
// SSR
void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
bool environment_get_ssr_enabled(RID p_env) const;
int environment_get_ssr_max_steps(RID p_env) const;
float environment_get_ssr_fade_in(RID p_env) const;
float environment_get_ssr_fade_out(RID p_env) const;
float environment_get_ssr_depth_tolerance(RID p_env) const;
// SSAO
void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
bool environment_get_ssao_enabled(RID p_env) const;
float environment_get_ssao_radius(RID p_env) const;
float environment_get_ssao_intensity(RID p_env) const;
float environment_get_ssao_power(RID p_env) const;
float environment_get_ssao_detail(RID p_env) const;
float environment_get_ssao_horizon(RID p_env) const;
float environment_get_ssao_sharpness(RID p_env) const;
float environment_get_ssao_direct_light_affect(RID p_env) const;
float environment_get_ssao_ao_channel_affect(RID p_env) const;
// SSIL
void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection);
bool environment_get_ssil_enabled(RID p_env) const;
float environment_get_ssil_radius(RID p_env) const;
float environment_get_ssil_intensity(RID p_env) const;
float environment_get_ssil_sharpness(RID p_env) const;
float environment_get_ssil_normal_rejection(RID p_env) const;
// SDFGI
void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
bool environment_get_sdfgi_enabled(RID p_env) const;
int environment_get_sdfgi_cascades(RID p_env) const;
float environment_get_sdfgi_min_cell_size(RID p_env) const;
bool environment_get_sdfgi_use_occlusion(RID p_env) const;
float environment_get_sdfgi_bounce_feedback(RID p_env) const;
bool environment_get_sdfgi_read_sky_light(RID p_env) const;
float environment_get_sdfgi_energy(RID p_env) const;
float environment_get_sdfgi_normal_bias(RID p_env) const;
float environment_get_sdfgi_probe_bias(RID p_env) const;
RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const;
// Adjustment
void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
bool environment_get_adjustments_enabled(RID p_env) const;
float environment_get_adjustments_brightness(RID p_env) const;
float environment_get_adjustments_contrast(RID p_env) const;
float environment_get_adjustments_saturation(RID p_env) const;
bool environment_get_use_1d_color_correction(RID p_env) const;
RID environment_get_color_correction(RID p_env) const;
};

View File

@@ -0,0 +1,202 @@
/**************************************************************************/
/* light_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "render_scene_buffers.h"
#include "servers/rendering_server.h"
class RendererLightStorage {
public:
virtual ~RendererLightStorage() {}
/* Light API */
virtual RID directional_light_allocate() = 0;
virtual void directional_light_initialize(RID p_rid) = 0;
virtual RID omni_light_allocate() = 0;
virtual void omni_light_initialize(RID p_rid) = 0;
virtual RID spot_light_allocate() = 0;
virtual void spot_light_initialize(RID p_rid) = 0;
virtual void light_free(RID p_rid) = 0;
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
virtual void light_set_projector(RID p_light, RID p_texture) = 0;
virtual void light_set_negative(RID p_light, bool p_enable) = 0;
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0;
virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
virtual bool light_has_shadow(RID p_light) const = 0;
virtual bool light_has_projector(RID p_light) const = 0;
virtual RS::LightType light_get_type(RID p_light) const = 0;
virtual AABB light_get_aabb(RID p_light) const = 0;
virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
virtual Color light_get_color(RID p_light) = 0;
virtual bool light_get_reverse_cull_face_mode(RID p_light) const = 0;
virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
virtual uint64_t light_get_version(RID p_light) const = 0;
virtual uint32_t light_get_cull_mask(RID p_light) const = 0;
/* LIGHT INSTANCE API */
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_free(RID p_light_instance) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const {
return true;
}
virtual bool light_instance_is_shadow_visible_at_position(RID p_light, const Vector3 &p_position) const = 0;
/* PROBE API */
virtual RID reflection_probe_allocate() = 0;
virtual void reflection_probe_initialize(RID p_rid) = 0;
virtual void reflection_probe_free(RID p_rid) = 0;
virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
virtual void reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) = 0;
virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) = 0;
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
virtual void reflection_probe_set_reflection_mask(RID p_probe, uint32_t p_layers) = 0;
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
virtual uint32_t reflection_probe_get_reflection_mask(RID p_probe) const = 0;
virtual Vector3 reflection_probe_get_size(RID p_probe) const = 0;
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
/* REFLECTION ATLAS */
virtual RID reflection_atlas_create() = 0;
virtual void reflection_atlas_free(RID p_ref_atlas) = 0;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
/* REFLECTION PROBE INSTANCE */
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
virtual void reflection_probe_instance_free(RID p_instance) = 0;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual bool reflection_probe_has_atlas_index(RID p_instance) = 0;
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
/* LIGHTMAP */
virtual RID lightmap_allocate() = 0;
virtual void lightmap_initialize(RID p_rid) = 0;
virtual void lightmap_free(RID p_rid) = 0;
virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) = 0;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
virtual float lightmap_get_probe_capture_update_speed() const = 0;
virtual void lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) = 0;
virtual RS::ShadowmaskMode lightmap_get_shadowmask_mode(RID p_lightmap) = 0;
virtual void lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) = 0;
/* LIGHTMAP INSTANCE */
virtual RID lightmap_instance_create(RID p_lightmap) = 0;
virtual void lightmap_instance_free(RID p_lightmap) = 0;
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0;
/* SHADOW ATLAS */
virtual RID shadow_atlas_create() = 0;
virtual void shadow_atlas_free(RID p_atlas) = 0;
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) = 0;
virtual void shadow_atlas_update(RID p_atlas) = 0;
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
virtual int get_directional_light_shadow_size(RID p_light_instance) = 0;
virtual void set_directional_shadow_count(int p_count) = 0;
};

View File

@@ -0,0 +1,103 @@
/**************************************************************************/
/* material_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering_server.h"
#include "utilities.h"
class RendererMaterialStorage {
public:
virtual ~RendererMaterialStorage() {}
/* GLOBAL SHADER UNIFORM API */
virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) = 0;
virtual void global_shader_parameter_remove(const StringName &p_name) = 0;
virtual Vector<StringName> global_shader_parameter_get_list() const = 0;
virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) = 0;
virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) = 0;
virtual Variant global_shader_parameter_get(const StringName &p_name) const = 0;
virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const = 0;
virtual void global_shader_parameters_load_settings(bool p_load_textures = true) = 0;
virtual void global_shader_parameters_clear() = 0;
virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) = 0;
virtual void global_shader_parameters_instance_free(RID p_instance) = 0;
virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) = 0;
/* SHADER API */
virtual RID shader_allocate() = 0;
virtual void shader_initialize(RID p_rid, bool p_embedded = true) = 0;
virtual void shader_free(RID p_rid) = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const = 0;
virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const = 0;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
virtual void shader_embedded_set_lock() = 0;
virtual const HashSet<RID> &shader_embedded_set_get() const = 0;
virtual void shader_embedded_set_unlock() = 0;
/* MATERIAL API */
virtual RID material_allocate() = 0;
virtual void material_initialize(RID p_rid) = 0;
virtual void material_free(RID p_rid) = 0;
virtual void material_set_render_priority(RID p_material, int priority) = 0;
virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0;
virtual bool material_is_animated(RID p_material) = 0;
virtual bool material_casts_shadows(RID p_material) = 0;
virtual RS::CullMode material_get_cull_mode(RID p_material) const = 0;
struct InstanceShaderParam {
PropertyInfo info;
int index;
Variant default_value;
};
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
};

View File

@@ -0,0 +1,509 @@
/**************************************************************************/
/* mesh_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "mesh_storage.h"
#include "core/math/transform_interpolator.h"
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
#include "core/config/project_settings.h"
#endif
RID RendererMeshStorage::multimesh_allocate() {
return _multimesh_allocate();
}
void RendererMeshStorage::multimesh_initialize(RID p_rid) {
_multimesh_initialize(p_rid);
}
void RendererMeshStorage::multimesh_free(RID p_rid) {
_multimesh_free(p_rid);
}
void RendererMeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data, bool p_use_indirect) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
mmi->_transform_format = p_transform_format;
mmi->_use_colors = p_use_colors;
mmi->_use_custom_data = p_use_custom_data;
mmi->_num_instances = p_instances;
mmi->_vf_size_xform = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
mmi->_vf_size_color = p_use_colors ? 4 : 0;
mmi->_vf_size_data = p_use_custom_data ? 4 : 0;
mmi->_stride = mmi->_vf_size_xform + mmi->_vf_size_color + mmi->_vf_size_data;
int size_in_floats = p_instances * mmi->_stride;
mmi->_data_curr.resize_initialized(size_in_floats);
mmi->_data_prev.resize_initialized(size_in_floats);
mmi->_data_interpolated.resize_initialized(size_in_floats);
}
_multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data, p_use_indirect);
}
int RendererMeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
return _multimesh_get_instance_count(p_multimesh);
}
void RendererMeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
_multimesh_set_mesh(p_multimesh, p_mesh);
}
void RendererMeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi && mmi->interpolated) {
ERR_FAIL_COND(p_index >= mmi->_num_instances);
ERR_FAIL_COND(mmi->_vf_size_xform != 12);
int start = p_index * mmi->_stride;
float *ptr = mmi->_data_curr.ptrw();
ptr += start;
const Transform3D &t = p_transform;
ptr[0] = t.basis.rows[0][0];
ptr[1] = t.basis.rows[0][1];
ptr[2] = t.basis.rows[0][2];
ptr[3] = t.origin.x;
ptr[4] = t.basis.rows[1][0];
ptr[5] = t.basis.rows[1][1];
ptr[6] = t.basis.rows[1][2];
ptr[7] = t.origin.y;
ptr[8] = t.basis.rows[2][0];
ptr[9] = t.basis.rows[2][1];
ptr[10] = t.basis.rows[2][2];
ptr[11] = t.origin.z;
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
}
#endif
return;
}
_multimesh_instance_set_transform(p_multimesh, p_index, p_transform);
}
void RendererMeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
_multimesh_instance_set_transform_2d(p_multimesh, p_index, p_transform);
}
void RendererMeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi && mmi->interpolated) {
ERR_FAIL_COND(p_index >= mmi->_num_instances);
ERR_FAIL_COND(mmi->_vf_size_color == 0);
int start = (p_index * mmi->_stride) + mmi->_vf_size_xform;
float *ptr = mmi->_data_curr.ptrw();
ptr += start;
if (mmi->_vf_size_color == 4) {
for (int n = 0; n < 4; n++) {
ptr[n] = p_color.components[n];
}
} else {
#ifdef DEV_ENABLED
// The options are currently 4 or zero, but just in case this changes in future...
ERR_FAIL_COND(mmi->_vf_size_color != 0);
#endif
}
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
return;
}
_multimesh_instance_set_color(p_multimesh, p_index, p_color);
}
void RendererMeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi && mmi->interpolated) {
ERR_FAIL_COND(p_index >= mmi->_num_instances);
ERR_FAIL_COND(mmi->_vf_size_data == 0);
int start = (p_index * mmi->_stride) + mmi->_vf_size_xform + mmi->_vf_size_color;
float *ptr = mmi->_data_curr.ptrw();
ptr += start;
if (mmi->_vf_size_data == 4) {
for (int n = 0; n < 4; n++) {
ptr[n] = p_color.components[n];
}
} else {
#ifdef DEV_ENABLED
// The options are currently 4 or zero, but just in case this changes in future...
ERR_FAIL_COND(mmi->_vf_size_data != 0);
#endif
}
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
return;
}
_multimesh_instance_set_custom_data(p_multimesh, p_index, p_color);
}
void RendererMeshStorage::multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
_multimesh_set_custom_aabb(p_multimesh, p_aabb);
}
AABB RendererMeshStorage::multimesh_get_custom_aabb(RID p_multimesh) const {
return _multimesh_get_custom_aabb(p_multimesh);
}
RID RendererMeshStorage::multimesh_get_mesh(RID p_multimesh) const {
return _multimesh_get_mesh(p_multimesh);
}
Transform3D RendererMeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
return _multimesh_instance_get_transform(p_multimesh, p_index);
}
Transform2D RendererMeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
return _multimesh_instance_get_transform_2d(p_multimesh, p_index);
}
Color RendererMeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
return _multimesh_instance_get_color(p_multimesh, p_index);
}
Color RendererMeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
return _multimesh_instance_get_custom_data(p_multimesh, p_index);
}
void RendererMeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi && mmi->interpolated) {
ERR_FAIL_COND_MSG(p_buffer.size() != mmi->_data_curr.size(), vformat("Buffer should have %d elements, got %d instead.", mmi->_data_curr.size(), p_buffer.size()));
mmi->_data_curr = p_buffer;
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
}
#endif
return;
}
_multimesh_set_buffer(p_multimesh, p_buffer);
}
RID RendererMeshStorage::multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
return _multimesh_get_command_buffer_rd_rid(p_multimesh);
}
RID RendererMeshStorage::multimesh_get_buffer_rd_rid(RID p_multimesh) const {
return _multimesh_get_buffer_rd_rid(p_multimesh);
}
Vector<float> RendererMeshStorage::multimesh_get_buffer(RID p_multimesh) const {
return _multimesh_get_buffer(p_multimesh);
}
void RendererMeshStorage::multimesh_set_buffer_interpolated(RID p_multimesh, const Vector<float> &p_buffer, const Vector<float> &p_buffer_prev) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
ERR_FAIL_COND_MSG(p_buffer.size() != mmi->_data_curr.size(), vformat("Buffer for current frame should have %d elements, got %d instead.", mmi->_data_curr.size(), p_buffer.size()));
ERR_FAIL_COND_MSG(p_buffer_prev.size() != mmi->_data_prev.size(), vformat("Buffer for previous frame should have %d elements, got %d instead.", mmi->_data_prev.size(), p_buffer_prev.size()));
// We are assuming that mmi->interpolated is the case. (Can possibly assert this?)
// Even if this flag hasn't been set - just calling this function suggests interpolation is desired.
mmi->_data_prev = p_buffer_prev;
mmi->_data_curr = p_buffer;
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
}
#endif
}
}
void RendererMeshStorage::multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
if (p_interpolated == mmi->interpolated) {
return;
}
mmi->interpolated = p_interpolated;
// If we are turning on physics interpolation, as a convenience,
// we want to get the current buffer data from the backend,
// and reset all the instances.
if (p_interpolated) {
mmi->_data_curr = _multimesh_get_buffer(p_multimesh);
mmi->_data_prev = mmi->_data_curr;
mmi->_data_interpolated = mmi->_data_curr;
}
}
}
void RendererMeshStorage::multimesh_set_physics_interpolation_quality(RID p_multimesh, RS::MultimeshPhysicsInterpolationQuality p_quality) {
ERR_FAIL_COND((p_quality < 0) || (p_quality > 1));
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
mmi->quality = (int)p_quality;
}
}
void RendererMeshStorage::multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
ERR_FAIL_INDEX(p_index, mmi->_num_instances);
float *w = mmi->_data_prev.ptrw();
const float *r = mmi->_data_curr.ptr();
int start = p_index * mmi->_stride;
for (int n = 0; n < mmi->_stride; n++) {
w[start + n] = r[start + n];
}
}
}
void RendererMeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
return _multimesh_set_visible_instances(p_multimesh, p_visible);
}
int RendererMeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
return _multimesh_get_visible_instances(p_multimesh);
}
AABB RendererMeshStorage::multimesh_get_aabb(RID p_multimesh) {
return _multimesh_get_aabb(p_multimesh);
}
void RendererMeshStorage::_multimesh_add_to_interpolation_lists(RID p_multimesh, MultiMeshInterpolator &r_mmi) {
if (!r_mmi.on_interpolate_update_list) {
r_mmi.on_interpolate_update_list = true;
_interpolation_data.multimesh_interpolate_update_list.push_back(p_multimesh);
}
if (!r_mmi.on_transform_update_list) {
r_mmi.on_transform_update_list = true;
_interpolation_data.multimesh_transform_update_list_curr->push_back(p_multimesh);
}
}
void RendererMeshStorage::InterpolationData::notify_free_multimesh(RID p_rid) {
// If the instance was on any of the lists, remove.
multimesh_interpolate_update_list.erase_multiple_unordered(p_rid);
multimesh_transform_update_lists[0].erase_multiple_unordered(p_rid);
multimesh_transform_update_lists[1].erase_multiple_unordered(p_rid);
}
void RendererMeshStorage::update_interpolation_tick(bool p_process) {
// Detect any that were on the previous transform list that are no longer active,
// we should remove them from the interpolate list.
for (unsigned int n = 0; n < _interpolation_data.multimesh_transform_update_list_prev->size(); n++) {
const RID &rid = (*_interpolation_data.multimesh_transform_update_list_prev)[n];
bool active = true;
// No longer active? (Either the instance deleted or no longer being transformed.)
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
if (mmi && !mmi->on_transform_update_list) {
active = false;
mmi->on_interpolate_update_list = false;
// Make sure the most recent transform is set...
mmi->_data_interpolated = mmi->_data_curr; // TODO: Copy data rather than use Packed = function?
// ... and that both prev and current are the same, just in case of any interpolations.
mmi->_data_prev = mmi->_data_curr;
// Update the actual stable buffer to the backend.
_multimesh_set_buffer(rid, mmi->_data_interpolated);
}
if (!mmi) {
active = false;
}
if (!active) {
_interpolation_data.multimesh_interpolate_update_list.erase(rid);
}
}
if (p_process) {
for (unsigned int i = 0; i < _interpolation_data.multimesh_transform_update_list_curr->size(); i++) {
const RID &rid = (*_interpolation_data.multimesh_transform_update_list_curr)[i];
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
if (mmi) {
// Reset for next tick.
mmi->on_transform_update_list = false;
mmi->_data_prev = mmi->_data_curr;
}
}
}
// If any have left the transform list, remove from the interpolate list.
// We maintain a mirror list for the transform updates, so we can detect when an instance
// is no longer being transformed, and remove it from the interpolate list.
SWAP(_interpolation_data.multimesh_transform_update_list_curr, _interpolation_data.multimesh_transform_update_list_prev);
// Prepare for the next iteration.
_interpolation_data.multimesh_transform_update_list_curr->clear();
}
void RendererMeshStorage::update_interpolation_frame(bool p_process) {
if (p_process) {
// Only need 32 bits for interpolation, don't use real_t.
float f = Engine::get_singleton()->get_physics_interpolation_fraction();
for (unsigned int c = 0; c < _interpolation_data.multimesh_interpolate_update_list.size(); c++) {
const RID &rid = _interpolation_data.multimesh_interpolate_update_list[c];
// We could use the TransformInterpolator here to slerp transforms, but that might be too expensive,
// so just using a Basis lerp for now.
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
if (mmi) {
// Make sure arrays are the correct size.
DEV_ASSERT(mmi->_data_prev.size() == mmi->_data_curr.size());
if (mmi->_data_interpolated.size() < mmi->_data_curr.size()) {
mmi->_data_interpolated.resize(mmi->_data_curr.size());
}
DEV_ASSERT(mmi->_data_interpolated.size() >= mmi->_data_curr.size());
DEV_ASSERT((mmi->_data_curr.size() % mmi->_stride) == 0);
int num = mmi->_data_curr.size() / mmi->_stride;
const float *pf_prev = mmi->_data_prev.ptr();
const float *pf_curr = mmi->_data_curr.ptr();
float *pf_int = mmi->_data_interpolated.ptrw();
bool use_lerp = mmi->quality == 0;
// Temporary transform (needed for swizzling).
Transform3D tp, tc, tr; // (transform prev, curr and result)
// Test for cache friendliness versus doing branchless.
for (int n = 0; n < num; n++) {
// Transform.
if (use_lerp) {
for (int i = 0; i < mmi->_vf_size_xform; i++) {
pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
}
} else {
// Silly swizzling, this will slow things down.
// No idea why it is using this format...
// ... maybe due to the shader.
tp.basis.rows[0][0] = pf_prev[0];
tp.basis.rows[0][1] = pf_prev[1];
tp.basis.rows[0][2] = pf_prev[2];
tp.basis.rows[1][0] = pf_prev[4];
tp.basis.rows[1][1] = pf_prev[5];
tp.basis.rows[1][2] = pf_prev[6];
tp.basis.rows[2][0] = pf_prev[8];
tp.basis.rows[2][1] = pf_prev[9];
tp.basis.rows[2][2] = pf_prev[10];
tp.origin.x = pf_prev[3];
tp.origin.y = pf_prev[7];
tp.origin.z = pf_prev[11];
tc.basis.rows[0][0] = pf_curr[0];
tc.basis.rows[0][1] = pf_curr[1];
tc.basis.rows[0][2] = pf_curr[2];
tc.basis.rows[1][0] = pf_curr[4];
tc.basis.rows[1][1] = pf_curr[5];
tc.basis.rows[1][2] = pf_curr[6];
tc.basis.rows[2][0] = pf_curr[8];
tc.basis.rows[2][1] = pf_curr[9];
tc.basis.rows[2][2] = pf_curr[10];
tc.origin.x = pf_curr[3];
tc.origin.y = pf_curr[7];
tc.origin.z = pf_curr[11];
TransformInterpolator::interpolate_transform_3d(tp, tc, tr, f);
pf_int[0] = tr.basis.rows[0][0];
pf_int[1] = tr.basis.rows[0][1];
pf_int[2] = tr.basis.rows[0][2];
pf_int[4] = tr.basis.rows[1][0];
pf_int[5] = tr.basis.rows[1][1];
pf_int[6] = tr.basis.rows[1][2];
pf_int[8] = tr.basis.rows[2][0];
pf_int[9] = tr.basis.rows[2][1];
pf_int[10] = tr.basis.rows[2][2];
pf_int[3] = tr.origin.x;
pf_int[7] = tr.origin.y;
pf_int[11] = tr.origin.z;
}
pf_prev += mmi->_vf_size_xform;
pf_curr += mmi->_vf_size_xform;
pf_int += mmi->_vf_size_xform;
// Color.
if (mmi->_vf_size_color == 4) {
for (int i = 0; i < 4; i++) {
pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
}
pf_prev += 4;
pf_curr += 4;
pf_int += 4;
}
// Custom data.
if (mmi->_vf_size_data == 4) {
for (int i = 0; i < 4; i++) {
pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
}
pf_prev += 4;
pf_curr += 4;
pf_int += 4;
}
}
_multimesh_set_buffer(rid, mmi->_data_interpolated);
// TODO: Make sure AABBs are constantly up to date through the interpolation?
// NYI.
}
}
}
}

View File

@@ -0,0 +1,231 @@
/**************************************************************************/
/* mesh_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering_server.h"
#include "utilities.h"
class RendererMeshStorage {
public:
virtual ~RendererMeshStorage() {}
/* MESH API */
virtual RID mesh_allocate() = 0;
virtual void mesh_initialize(RID p_rid) = 0;
virtual void mesh_free(RID p_rid) = 0;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
/// Returns stride
virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_update_index_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
virtual int mesh_get_surface_count(RID p_mesh) const = 0;
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
virtual void mesh_set_path(RID p_mesh, const String &p_path) = 0;
virtual String mesh_get_path(RID p_mesh) const = 0;
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
virtual void mesh_surface_remove(RID p_mesh, int p_surface) = 0;
virtual void mesh_clear(RID p_mesh) = 0;
virtual void mesh_debug_usage(List<RS::MeshInfo> *r_info) = 0;
virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
/* MESH INSTANCE */
virtual RID mesh_instance_create(RID p_base) = 0;
virtual void mesh_instance_free(RID p_rid) = 0;
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) = 0;
virtual void update_mesh_instances() = 0;
/* MULTIMESH API */
struct MultiMeshInterpolator {
RS::MultimeshTransformFormat _transform_format = RS::MULTIMESH_TRANSFORM_3D;
bool _use_colors = false;
bool _use_custom_data = false;
// The stride of the buffer in floats.
int _stride = 0;
// Vertex format sizes in floats.
int _vf_size_xform = 0;
int _vf_size_color = 0;
int _vf_size_data = 0;
// Set by allocate, can be used to prevent indexing out of range.
int _num_instances = 0;
// Quality determines whether to use lerp or slerp etc.
int quality = 0;
bool interpolated = false;
bool on_interpolate_update_list = false;
bool on_transform_update_list = false;
Vector<float> _data_prev;
Vector<float> _data_curr;
Vector<float> _data_interpolated;
};
virtual RID multimesh_allocate();
virtual void multimesh_initialize(RID p_rid);
virtual void multimesh_free(RID p_rid);
virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false);
virtual int multimesh_get_instance_count(RID p_multimesh) const;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform);
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
virtual void multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb);
virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const;
virtual RID multimesh_get_mesh(RID p_multimesh) const;
virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer);
virtual RID multimesh_get_command_buffer_rd_rid(RID p_multimesh) const;
virtual RID multimesh_get_buffer_rd_rid(RID p_multimesh) const;
virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const;
virtual void multimesh_set_buffer_interpolated(RID p_multimesh, const Vector<float> &p_buffer, const Vector<float> &p_buffer_prev);
virtual void multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated);
virtual void multimesh_set_physics_interpolation_quality(RID p_multimesh, RS::MultimeshPhysicsInterpolationQuality p_quality);
virtual void multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index);
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
virtual AABB multimesh_get_aabb(RID p_multimesh);
virtual RID _multimesh_allocate() = 0;
virtual void _multimesh_initialize(RID p_rid) = 0;
virtual void _multimesh_free(RID p_rid) = 0;
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) = 0;
virtual int _multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
virtual void _multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
virtual void _multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
virtual void _multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual void _multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) = 0;
virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const = 0;
virtual RID _multimesh_get_mesh(RID p_multimesh) const = 0;
virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0;
virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const = 0;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const = 0;
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const = 0;
virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int _multimesh_get_visible_instances(RID p_multimesh) const = 0;
virtual AABB _multimesh_get_aabb(RID p_multimesh) = 0;
// Multimesh is responsible for allocating / destroying a MultiMeshInterpolator object.
// This allows shared functionality for interpolation across backends.
virtual MultiMeshInterpolator *_multimesh_get_interpolator(RID p_multimesh) const = 0;
private:
void _multimesh_add_to_interpolation_lists(RID p_multimesh, MultiMeshInterpolator &r_mmi);
public:
/* SKELETON API */
virtual RID skeleton_allocate() = 0;
virtual void skeleton_initialize(RID p_rid) = 0;
virtual void skeleton_free(RID p_rid) = 0;
virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* INTERPOLATION */
struct InterpolationData {
void notify_free_multimesh(RID p_rid);
LocalVector<RID> multimesh_interpolate_update_list;
LocalVector<RID> multimesh_transform_update_lists[2];
LocalVector<RID> *multimesh_transform_update_list_curr = &multimesh_transform_update_lists[0];
LocalVector<RID> *multimesh_transform_update_list_prev = &multimesh_transform_update_lists[1];
} _interpolation_data;
void update_interpolation_tick(bool p_process = true);
void update_interpolation_frame(bool p_process = true);
};

View File

@@ -0,0 +1,131 @@
/**************************************************************************/
/* particles_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering_server.h"
class RendererParticlesStorage {
public:
virtual ~RendererParticlesStorage() {}
/* PARTICLES */
virtual RID particles_allocate() = 0;
virtual void particles_initialize(RID p_rid) = 0;
virtual void particles_free(RID p_rid) = 0;
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) = 0;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
virtual RID particles_get_process_material(RID p_particles) const = 0;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) = 0;
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
virtual void particles_restart(RID p_particles) = 0;
virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
virtual bool particles_is_inactive(RID p_particles) const = 0;
virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0;
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
virtual void particles_request_process(RID p_particles) = 0;
virtual AABB particles_get_current_aabb(RID p_particles) = 0;
virtual AABB particles_get_aabb(RID p_particles) const = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) = 0;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) = 0;
virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0;
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void update_particles() = 0;
/* PARTICLES COLLISION */
virtual RID particles_collision_allocate() = 0;
virtual void particles_collision_initialize(RID p_rid) = 0;
virtual void particles_collision_free(RID p_rid) = 0;
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const = 0;
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) = 0;
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const = 0;
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
virtual void particles_collision_instance_free(RID p_rid) = 0;
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
};

View File

@@ -0,0 +1,69 @@
/**************************************************************************/
/* render_data.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "render_data.h"
void RenderData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_scene_buffers"), &RenderData::get_render_scene_buffers);
ClassDB::bind_method(D_METHOD("get_render_scene_data"), &RenderData::get_render_scene_data);
ClassDB::bind_method(D_METHOD("get_environment"), &RenderData::get_environment);
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &RenderData::get_camera_attributes);
}
void RenderDataExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_render_scene_buffers);
GDVIRTUAL_BIND(_get_render_scene_data)
GDVIRTUAL_BIND(_get_environment)
GDVIRTUAL_BIND(_get_camera_attributes)
}
Ref<RenderSceneBuffers> RenderDataExtension::get_render_scene_buffers() const {
Ref<RenderSceneBuffers> ret;
GDVIRTUAL_CALL(_get_render_scene_buffers, ret);
return ret;
}
RenderSceneData *RenderDataExtension::get_render_scene_data() const {
RenderSceneData *ret = nullptr;
GDVIRTUAL_CALL(_get_render_scene_data, ret);
return ret;
}
RID RenderDataExtension::get_environment() const {
RID ret;
GDVIRTUAL_CALL(_get_environment, ret);
return ret;
}
RID RenderDataExtension::get_camera_attributes() const {
RID ret;
GDVIRTUAL_CALL(_get_camera_attributes, ret);
return ret;
}

View File

@@ -0,0 +1,67 @@
/**************************************************************************/
/* render_data.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/object.h"
#include "render_scene_buffers.h"
#include "render_scene_data.h"
class RenderData : public Object {
GDCLASS(RenderData, Object);
protected:
static void _bind_methods();
public:
virtual Ref<RenderSceneBuffers> get_render_scene_buffers() const = 0;
virtual RenderSceneData *get_render_scene_data() const = 0;
virtual RID get_environment() const = 0;
virtual RID get_camera_attributes() const = 0;
};
class RenderDataExtension : public RenderData {
GDCLASS(RenderDataExtension, RenderData);
protected:
static void _bind_methods();
virtual Ref<RenderSceneBuffers> get_render_scene_buffers() const override;
virtual RenderSceneData *get_render_scene_data() const override;
virtual RID get_environment() const override;
virtual RID get_camera_attributes() const override;
GDVIRTUAL0RC(Ref<RenderSceneBuffers>, _get_render_scene_buffers)
GDVIRTUAL0RC(RenderSceneData *, _get_render_scene_data)
GDVIRTUAL0RC(RID, _get_environment)
GDVIRTUAL0RC(RID, _get_camera_attributes)
};

View File

@@ -0,0 +1,105 @@
/**************************************************************************/
/* render_scene_buffers.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "render_scene_buffers.h"
void RenderSceneBuffersConfiguration::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_target"), &RenderSceneBuffersConfiguration::get_render_target);
ClassDB::bind_method(D_METHOD("set_render_target", "render_target"), &RenderSceneBuffersConfiguration::set_render_target);
ADD_PROPERTY(PropertyInfo(Variant::RID, "render_target"), "set_render_target", "get_render_target");
ClassDB::bind_method(D_METHOD("get_internal_size"), &RenderSceneBuffersConfiguration::get_internal_size);
ClassDB::bind_method(D_METHOD("set_internal_size", "internal_size"), &RenderSceneBuffersConfiguration::set_internal_size);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "internal_size"), "set_internal_size", "get_internal_size");
ClassDB::bind_method(D_METHOD("get_target_size"), &RenderSceneBuffersConfiguration::get_target_size);
ClassDB::bind_method(D_METHOD("set_target_size", "target_size"), &RenderSceneBuffersConfiguration::set_target_size);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "target_size"), "set_target_size", "get_target_size");
ClassDB::bind_method(D_METHOD("get_view_count"), &RenderSceneBuffersConfiguration::get_view_count);
ClassDB::bind_method(D_METHOD("set_view_count", "view_count"), &RenderSceneBuffersConfiguration::set_view_count);
ADD_PROPERTY(PropertyInfo(Variant::INT, "view_count"), "set_view_count", "get_view_count");
ClassDB::bind_method(D_METHOD("get_scaling_3d_mode"), &RenderSceneBuffersConfiguration::get_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("set_scaling_3d_mode", "scaling_3d_mode"), &RenderSceneBuffersConfiguration::set_scaling_3d_mode);
ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast),FSR 2.2 (Slow),MetalFX (Spatial),MetalFX (Temporal)"), "set_scaling_3d_mode", "get_scaling_3d_mode"); // TODO VIEWPORT_SCALING_3D_MODE_OFF is possible here too, but we can't specify an enum string for it.
ClassDB::bind_method(D_METHOD("get_msaa_3d"), &RenderSceneBuffersConfiguration::get_msaa_3d);
ClassDB::bind_method(D_METHOD("set_msaa_3d", "msaa_3d"), &RenderSceneBuffersConfiguration::set_msaa_3d);
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa_3d", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x"), "set_msaa_3d", "get_msaa_3d");
ClassDB::bind_method(D_METHOD("get_screen_space_aa"), &RenderSceneBuffersConfiguration::get_screen_space_aa);
ClassDB::bind_method(D_METHOD("set_screen_space_aa", "screen_space_aa"), &RenderSceneBuffersConfiguration::set_screen_space_aa);
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA,SMAA"), "set_screen_space_aa", "get_screen_space_aa");
ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &RenderSceneBuffersConfiguration::get_fsr_sharpness);
ClassDB::bind_method(D_METHOD("set_fsr_sharpness", "fsr_sharpness"), &RenderSceneBuffersConfiguration::set_fsr_sharpness);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fsr_sharpness"), "set_fsr_sharpness", "get_fsr_sharpness");
ClassDB::bind_method(D_METHOD("get_texture_mipmap_bias"), &RenderSceneBuffersConfiguration::get_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("set_texture_mipmap_bias", "texture_mipmap_bias"), &RenderSceneBuffersConfiguration::set_texture_mipmap_bias);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "texture_mipmap_bias"), "set_texture_mipmap_bias", "get_texture_mipmap_bias");
ClassDB::bind_method(D_METHOD("get_anisotropic_filtering_level"), &RenderSceneBuffersConfiguration::get_anisotropic_filtering_level);
ClassDB::bind_method(D_METHOD("set_anisotropic_filtering_level", "anisotropic_filtering_level"), &RenderSceneBuffersConfiguration::set_anisotropic_filtering_level);
ADD_PROPERTY(PropertyInfo(Variant::INT, "anisotropic_filtering_level"), "set_anisotropic_filtering_level", "get_anisotropic_filtering_level");
}
void RenderSceneBuffers::_bind_methods() {
ClassDB::bind_method(D_METHOD("configure", "config"), &RenderSceneBuffers::configure);
}
void RenderSceneBuffersExtension::_bind_methods() {
GDVIRTUAL_BIND(_configure, "config");
GDVIRTUAL_BIND(_set_fsr_sharpness, "fsr_sharpness");
GDVIRTUAL_BIND(_set_texture_mipmap_bias, "texture_mipmap_bias");
GDVIRTUAL_BIND(_set_anisotropic_filtering_level, "anisotropic_filtering_level");
GDVIRTUAL_BIND(_set_use_debanding, "use_debanding");
}
void RenderSceneBuffersExtension::configure(const RenderSceneBuffersConfiguration *p_config) {
GDVIRTUAL_CALL(_configure, p_config);
}
void RenderSceneBuffersExtension::set_fsr_sharpness(float p_fsr_sharpness) {
GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);
}
void RenderSceneBuffersExtension::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias);
}
void RenderSceneBuffersExtension::set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) {
GDVIRTUAL_CALL(_set_anisotropic_filtering_level, p_anisotropic_filtering_level);
}
void RenderSceneBuffersExtension::set_use_debanding(bool p_use_debanding) {
GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding);
}

View File

@@ -0,0 +1,140 @@
/**************************************************************************/
/* render_scene_buffers.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/ref_counted.h"
#include "servers/rendering_server.h"
class RenderSceneBuffersConfiguration : public RefCounted {
GDCLASS(RenderSceneBuffersConfiguration, RefCounted);
private:
RID render_target;
Size2i internal_size;
Size2i target_size;
uint32_t view_count = 1;
RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
RS::ViewportAnisotropicFiltering anisotropic_filtering_level = RS::VIEWPORT_ANISOTROPY_4X;
float fsr_sharpness = 0.0;
float texture_mipmap_bias = 0.0;
bool use_taa = false;
bool use_debanding = false;
protected:
static void _bind_methods();
public:
RID get_render_target() const { return render_target; }
void set_render_target(RID p_render_target) { render_target = p_render_target; }
Size2i get_internal_size() const { return internal_size; }
void set_internal_size(Size2i p_internal_size) { internal_size = p_internal_size; }
Size2i get_target_size() const { return target_size; }
void set_target_size(Size2i p_target_size) { target_size = p_target_size; }
uint32_t get_view_count() const { return view_count; }
void set_view_count(uint32_t p_view_count) { view_count = p_view_count; }
RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
void set_scaling_3d_mode(RS::ViewportScaling3DMode p_scaling_3d_mode) { scaling_3d_mode = p_scaling_3d_mode; }
RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
void set_msaa_3d(RS::ViewportMSAA p_msaa_3d) { msaa_3d = p_msaa_3d; }
RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
void set_screen_space_aa(RS::ViewportScreenSpaceAA p_screen_space_aa) { screen_space_aa = p_screen_space_aa; }
float get_fsr_sharpness() const { return fsr_sharpness; }
void set_fsr_sharpness(float p_fsr_sharpness) { fsr_sharpness = p_fsr_sharpness; }
float get_texture_mipmap_bias() const { return texture_mipmap_bias; }
void set_texture_mipmap_bias(float p_texture_mipmap_bias) { texture_mipmap_bias = p_texture_mipmap_bias; }
RS::ViewportAnisotropicFiltering get_anisotropic_filtering_level() const { return anisotropic_filtering_level; }
void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) { anisotropic_filtering_level = p_anisotropic_filtering_level; }
bool get_use_taa() const { return use_taa; }
void set_use_taa(bool p_use_taa) { use_taa = p_use_taa; }
bool get_use_debanding() const { return use_debanding; }
void set_use_debanding(bool p_use_debanding) { use_debanding = p_use_debanding; }
RenderSceneBuffersConfiguration() {}
virtual ~RenderSceneBuffersConfiguration() {}
};
class RenderSceneBuffers : public RefCounted {
GDCLASS(RenderSceneBuffers, RefCounted);
protected:
static void _bind_methods();
public:
RenderSceneBuffers() {}
virtual ~RenderSceneBuffers() {}
virtual void configure(const RenderSceneBuffersConfiguration *p_config) = 0;
// for those settings that are unlikely to require buffers to be recreated, we'll add setters
virtual void set_fsr_sharpness(float p_fsr_sharpness) = 0;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) = 0;
virtual void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) = 0;
virtual void set_use_debanding(bool p_use_debanding) = 0;
};
class RenderSceneBuffersExtension : public RenderSceneBuffers {
GDCLASS(RenderSceneBuffersExtension, RenderSceneBuffers);
protected:
static void _bind_methods();
GDVIRTUAL1(_configure, const RenderSceneBuffersConfiguration *)
GDVIRTUAL1(_set_fsr_sharpness, float)
GDVIRTUAL1(_set_texture_mipmap_bias, float)
GDVIRTUAL1(_set_anisotropic_filtering_level, int)
GDVIRTUAL1(_set_use_debanding, bool)
public:
virtual ~RenderSceneBuffersExtension() {}
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
virtual void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) override;
virtual void set_use_debanding(bool p_use_debanding) override;
};

View File

@@ -0,0 +1,88 @@
/**************************************************************************/
/* render_scene_data.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "render_scene_data.h"
void RenderSceneData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cam_transform"), &RenderSceneData::get_cam_transform);
ClassDB::bind_method(D_METHOD("get_cam_projection"), &RenderSceneData::get_cam_projection);
ClassDB::bind_method(D_METHOD("get_view_count"), &RenderSceneData::get_view_count);
ClassDB::bind_method(D_METHOD("get_view_eye_offset", "view"), &RenderSceneData::get_view_eye_offset);
ClassDB::bind_method(D_METHOD("get_view_projection", "view"), &RenderSceneData::get_view_projection);
ClassDB::bind_method(D_METHOD("get_uniform_buffer"), &RenderSceneData::get_uniform_buffer);
}
void RenderSceneDataExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_cam_transform);
GDVIRTUAL_BIND(_get_cam_projection);
GDVIRTUAL_BIND(_get_view_count);
GDVIRTUAL_BIND(_get_view_eye_offset, "view");
GDVIRTUAL_BIND(_get_view_projection, "view");
GDVIRTUAL_BIND(_get_uniform_buffer);
}
Transform3D RenderSceneDataExtension::get_cam_transform() const {
Transform3D ret;
GDVIRTUAL_CALL(_get_cam_transform, ret);
return ret;
}
Projection RenderSceneDataExtension::get_cam_projection() const {
Projection ret;
GDVIRTUAL_CALL(_get_cam_projection, ret);
return ret;
}
uint32_t RenderSceneDataExtension::get_view_count() const {
uint32_t ret = 0;
GDVIRTUAL_CALL(_get_view_count, ret);
return ret;
}
Vector3 RenderSceneDataExtension::get_view_eye_offset(uint32_t p_view) const {
Vector3 ret;
GDVIRTUAL_CALL(_get_view_eye_offset, p_view, ret);
return ret;
}
Projection RenderSceneDataExtension::get_view_projection(uint32_t p_view) const {
Projection ret;
GDVIRTUAL_CALL(_get_view_projection, p_view, ret);
return ret;
}
RID RenderSceneDataExtension::get_uniform_buffer() const {
RID ret;
GDVIRTUAL_CALL(_get_uniform_buffer, ret);
return ret;
}

View File

@@ -0,0 +1,79 @@
/**************************************************************************/
/* render_scene_data.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/class_db.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/object.h"
#include "core/object/script_language.h"
class RenderSceneData : public Object {
GDCLASS(RenderSceneData, Object);
protected:
static void _bind_methods();
public:
virtual Transform3D get_cam_transform() const = 0;
virtual Projection get_cam_projection() const = 0;
virtual uint32_t get_view_count() const = 0;
virtual Vector3 get_view_eye_offset(uint32_t p_view) const = 0;
virtual Projection get_view_projection(uint32_t p_view) const = 0;
virtual RID get_uniform_buffer() const = 0;
};
class RenderSceneDataExtension : public RenderSceneData {
GDCLASS(RenderSceneDataExtension, RenderSceneData);
protected:
static void _bind_methods();
public:
virtual Transform3D get_cam_transform() const override;
virtual Projection get_cam_projection() const override;
virtual uint32_t get_view_count() const override;
virtual Vector3 get_view_eye_offset(uint32_t p_view) const override;
virtual Projection get_view_projection(uint32_t p_view) const override;
virtual RID get_uniform_buffer() const override;
GDVIRTUAL0RC(Transform3D, _get_cam_transform)
GDVIRTUAL0RC(Projection, _get_cam_projection)
GDVIRTUAL0RC(uint32_t, _get_view_count)
GDVIRTUAL1RC(Vector3, _get_view_eye_offset, uint32_t)
GDVIRTUAL1RC(Projection, _get_view_projection, uint32_t)
GDVIRTUAL0RC(RID, _get_uniform_buffer)
};

View File

@@ -0,0 +1,197 @@
/**************************************************************************/
/* texture_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering_server.h"
class RendererTextureStorage {
private:
Color default_clear_color;
public:
void set_default_clear_color(const Color &p_color) {
default_clear_color = p_color;
}
Color get_default_clear_color() const {
return default_clear_color;
}
/* Canvas Texture API */
virtual RID canvas_texture_allocate() = 0;
virtual void canvas_texture_initialize(RID p_rid) = 0;
virtual void canvas_texture_free(RID p_rid) = 0;
virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0;
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0;
/* Texture API */
virtual ~RendererTextureStorage() {}
virtual RID texture_allocate() = 0;
virtual void texture_free(RID p_rid) = 0;
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) = 0;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_external_update(RID p_proxy, int p_width, int p_height, uint64_t p_external_buffer) = 0;
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
//these two APIs can be used together or in combination with the others.
virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
virtual void texture_3d_placeholder_initialize(RID p_texture) = 0;
virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0;
virtual void texture_replace(RID p_texture, RID p_by_texture) = 0;
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
virtual Image::Format texture_get_format(RID p_texture) const = 0;
virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0;
virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0;
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0;
virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const = 0;
virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const = 0;
/* Decal API */
virtual RID decal_allocate() = 0;
virtual void decal_initialize(RID p_rid) = 0;
virtual void decal_free(RID p_rid) = 0;
virtual void decal_set_size(RID p_decal, const Vector3 &p_size) = 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;
virtual uint32_t decal_get_cull_mask(RID p_decal) const = 0;
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
/* DECAL INSTANCE */
virtual RID decal_instance_create(RID p_decal) = 0;
virtual void decal_instance_free(RID p_decal_instance) = 0;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0;
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) = 0;
/* RENDER TARGET */
virtual RID render_target_create() = 0;
virtual void render_target_free(RID p_rid) = 0;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; // Q change input to const Point2i &p_position ?
virtual Point2i render_target_get_position(RID p_render_target) const = 0;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; // Q change input to const Size2i &p_size ?
virtual Size2i render_target_get_size(RID p_render_target) const = 0;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) = 0;
virtual bool render_target_get_transparent(RID p_render_target) const = 0;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 0;
virtual bool render_target_get_direct_to_screen(RID p_render_target) const = 0;
virtual bool render_target_was_used(RID p_render_target) const = 0;
virtual void render_target_set_as_unused(RID p_render_target) = 0;
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 0;
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const = 0;
virtual void render_target_set_msaa_needs_resolve(RID p_render_target, bool p_needs_resolve) = 0;
virtual bool render_target_get_msaa_needs_resolve(RID p_render_target) const = 0;
virtual void render_target_do_msaa_resolve(RID p_render_target) = 0;
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) = 0;
virtual bool render_target_is_using_hdr(RID p_render_target) const = 0;
virtual void render_target_set_use_debanding(RID p_render_target, bool p_use_debanding) = 0;
virtual bool render_target_is_using_debanding(RID p_render_target) const = 0;
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
virtual Color render_target_get_clear_request_color(RID p_render_target) = 0;
virtual void render_target_disable_clear_request(RID p_render_target) = 0;
virtual void render_target_do_clear_request(RID p_render_target) = 0;
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0;
virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) = 0;
virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const = 0;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
// override color, depth and velocity buffers (depth and velocity only for 3D)
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) = 0;
virtual RID render_target_get_override_color(RID p_render_target) const = 0;
virtual RID render_target_get_override_depth(RID p_render_target) const = 0;
virtual RID render_target_get_override_velocity(RID p_render_target) const = 0;
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const = 0;
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) = 0;
virtual Rect2i render_target_get_render_region(RID p_render_target) const = 0;
// get textures
virtual RID render_target_get_texture(RID p_render_target) = 0;
// Motion vectors
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) = 0;
virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const = 0;
};

View File

@@ -0,0 +1,62 @@
/**************************************************************************/
/* utilities.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "utilities.h"
void Dependency::changed_notify(DependencyChangedNotification p_notification) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->changed_callback) {
E.key->changed_callback(p_notification, E.key);
}
}
}
void Dependency::deleted_notify(const RID &p_rid) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->deleted_callback) {
E.key->deleted_callback(p_rid, E.key);
}
}
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
E.key->dependencies.erase(this);
}
instances.clear();
}
Dependency::~Dependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
E.key->dependencies.erase(this);
}
}
#endif
}

View File

@@ -0,0 +1,189 @@
/**************************************************************************/
/* utilities.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering_server.h"
class DependencyTracker;
class Dependency {
public:
enum DependencyChangedNotification {
DEPENDENCY_CHANGED_AABB,
DEPENDENCY_CHANGED_MATERIAL,
DEPENDENCY_CHANGED_MESH,
DEPENDENCY_CHANGED_MULTIMESH,
DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES,
DEPENDENCY_CHANGED_PARTICLES,
DEPENDENCY_CHANGED_PARTICLES_INSTANCES,
DEPENDENCY_CHANGED_DECAL,
DEPENDENCY_CHANGED_SKELETON_DATA,
DEPENDENCY_CHANGED_SKELETON_BONES,
DEPENDENCY_CHANGED_LIGHT,
DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
DEPENDENCY_CHANGED_REFLECTION_PROBE,
DEPENDENCY_CHANGED_CULL_MASK,
};
void changed_notify(DependencyChangedNotification p_notification);
void deleted_notify(const RID &p_rid);
~Dependency();
private:
friend class DependencyTracker;
HashMap<DependencyTracker *, uint32_t> instances;
};
class DependencyTracker {
public:
void *userdata = nullptr;
typedef void (*ChangedCallback)(Dependency::DependencyChangedNotification, DependencyTracker *);
typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
ChangedCallback changed_callback = nullptr;
DeletedCallback deleted_callback = nullptr;
void update_begin() { // call before updating dependencies
instance_version++;
}
void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
dependencies.insert(p_dependency);
p_dependency->instances[this] = instance_version;
}
void update_end() { //call after updating dependencies
List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
for (Dependency *E : dependencies) {
Dependency *dep = E;
HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
ERR_CONTINUE(!F);
if (F->value != instance_version) {
Pair<Dependency *, DependencyTracker *> p;
p.first = dep;
p.second = F->key;
to_clean_up.push_back(p);
}
}
while (to_clean_up.size()) {
to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
dependencies.erase(to_clean_up.front()->get().first);
to_clean_up.pop_front();
}
}
void clear() { // clear all dependencies
for (Dependency *E : dependencies) {
Dependency *dep = E;
dep->instances.erase(this);
}
dependencies.clear();
}
~DependencyTracker() { clear(); }
private:
friend class Dependency;
uint32_t instance_version = 0;
HashSet<Dependency *> dependencies;
};
class RendererUtilities {
public:
virtual ~RendererUtilities() {}
/* INSTANCES */
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
virtual bool free(RID p_rid) = 0;
/* DEPENDENCIES */
virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* VISIBILITY NOTIFIER */
virtual RID visibility_notifier_allocate() = 0;
virtual void visibility_notifier_initialize(RID p_notifier) = 0;
virtual void visibility_notifier_free(RID p_notifier) = 0;
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
/* TIMING */
bool capturing_timestamps = false;
#define TIMESTAMP_BEGIN() \
{ \
if (RSG::utilities->capturing_timestamps) \
RSG::utilities->capture_timestamps_begin(); \
}
#define RENDER_TIMESTAMP(m_text) \
{ \
if (RSG::utilities->capturing_timestamps) \
RSG::utilities->capture_timestamp(m_text); \
}
virtual void capture_timestamps_begin() = 0;
virtual void capture_timestamp(const String &p_name) = 0;
virtual uint32_t get_captured_timestamps_count() const = 0;
virtual uint64_t get_captured_timestamps_frame() const = 0;
virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0;
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0;
virtual String get_captured_timestamp_name(uint32_t p_index) const = 0;
/* MISC */
virtual void update_dirty_resources() = 0;
virtual void set_debug_generate_wireframes(bool p_generate) = 0;
virtual bool has_os_feature(const String &p_feature) const = 0;
virtual void update_memory_info() = 0;
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
virtual String get_video_adapter_api_version() const = 0;
virtual Size2i get_maximum_viewport_size() const = 0;
virtual uint32_t get_maximum_shader_varyings() const = 0;
virtual uint64_t get_maximum_uniform_buffer_size() const = 0;
};

View File

@@ -0,0 +1,320 @@
/**************************************************************************/
/* variant_converters.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/error/error_macros.h"
#include "core/variant/array.h"
#include "core/variant/variant.h"
#include <initializer_list>
#include <type_traits>
template <typename T>
struct VariantConverterStd140 {
// Generic base template for all Vector2/3/4(i) classes.
static constexpr int Elements = T::AXIS_COUNT;
template <typename P>
static void convert(const T &p_v, P *p_write, bool p_compact) {
for (int i = 0; i < Elements; i++) {
p_write[i] = p_v[i];
}
}
};
template <>
struct VariantConverterStd140<float> {
static constexpr int Elements = 1;
template <typename P>
static void convert(float p_v, P *p_write, bool p_compact) {
p_write[0] = p_v;
}
};
template <>
struct VariantConverterStd140<int32_t> {
static constexpr int Elements = 1;
template <typename P>
static void convert(int32_t p_v, P *p_write, bool p_compact) {
p_write[0] = p_v;
}
};
template <>
struct VariantConverterStd140<uint32_t> {
static constexpr int Elements = 1;
template <typename P>
static void convert(uint32_t p_v, P *p_write, bool p_compact) {
p_write[0] = p_v;
}
};
template <>
struct VariantConverterStd140<Basis> {
static constexpr int Elements = 9;
template <typename P>
static void convert(const Basis &p_v, P *p_write, bool p_compact) {
// Basis can have compact 9 floats or std140 layout 12 floats.
int i = 0;
p_write[i++] = p_v.rows[0][0];
p_write[i++] = p_v.rows[1][0];
p_write[i++] = p_v.rows[2][0];
if (!p_compact) {
p_write[i++] = 0;
}
p_write[i++] = p_v.rows[0][1];
p_write[i++] = p_v.rows[1][1];
p_write[i++] = p_v.rows[2][1];
if (!p_compact) {
p_write[i++] = 0;
}
p_write[i++] = p_v.rows[0][2];
p_write[i++] = p_v.rows[1][2];
p_write[i++] = p_v.rows[2][2];
if (!p_compact) {
p_write[i++] = 0;
}
}
};
template <>
struct VariantConverterStd140<Transform2D> {
static constexpr int Elements = 12;
template <typename P>
static void convert(const Transform2D &p_v, P *p_write, bool p_compact) {
p_write[0] = p_v.columns[0][0];
p_write[1] = p_v.columns[0][1];
p_write[2] = 0;
p_write[3] = 0;
p_write[4] = p_v.columns[1][0];
p_write[5] = p_v.columns[1][1];
p_write[6] = 0;
p_write[7] = 0;
p_write[8] = p_v.columns[2][0];
p_write[9] = p_v.columns[2][1];
p_write[10] = 1;
p_write[11] = 0;
}
};
template <>
struct VariantConverterStd140<Transform3D> {
static constexpr int Elements = 16;
template <typename P>
static void convert(const Transform3D &p_v, P *p_write, bool p_compact) {
p_write[0] = p_v.basis.rows[0][0];
p_write[1] = p_v.basis.rows[1][0];
p_write[2] = p_v.basis.rows[2][0];
p_write[3] = 0;
p_write[4] = p_v.basis.rows[0][1];
p_write[5] = p_v.basis.rows[1][1];
p_write[6] = p_v.basis.rows[2][1];
p_write[7] = 0;
p_write[8] = p_v.basis.rows[0][2];
p_write[9] = p_v.basis.rows[1][2];
p_write[10] = p_v.basis.rows[2][2];
p_write[11] = 0;
p_write[12] = p_v.origin.x;
p_write[13] = p_v.origin.y;
p_write[14] = p_v.origin.z;
p_write[15] = 1;
}
};
template <>
struct VariantConverterStd140<Projection> {
static constexpr int Elements = 16;
template <typename P>
static void convert(const Projection &p_v, P *p_write, bool p_compact) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
p_write[i * 4 + j] = p_v.columns[i][j];
}
}
}
};
template <typename T, typename P>
T construct_vector(const std::initializer_list<P> &values) {
T vector{};
int index = 0;
for (P v : values) {
vector[index++] = v;
if (index >= T::AXIS_COUNT) {
break;
}
}
return vector;
}
// Compatibility converter, tries to convert certain Variant types into a Vector2/3/4(i).
template <typename T>
T convert_to_vector(const Variant &p_variant, bool p_linear_color = false) {
const Variant::Type type = p_variant.get_type();
if (type == Variant::QUATERNION) {
Quaternion quat = p_variant;
return construct_vector<T>({ quat.x, quat.y, quat.z, quat.w });
} else if (type == Variant::PLANE) {
Plane p = p_variant;
return construct_vector<T>({ p.normal.x, p.normal.y, p.normal.z, p.d });
} else if (type == Variant::RECT2 || type == Variant::RECT2I) {
Rect2 r = p_variant;
return construct_vector<T>({ r.position.x, r.position.y, r.size.x, r.size.y });
} else if (type == Variant::COLOR) {
Color c = p_variant;
if (p_linear_color) {
c = c.srgb_to_linear();
}
return construct_vector<T>({ c.r, c.g, c.b, c.a });
} else if (p_variant.is_array()) {
const Array &array = p_variant;
const int size = MIN(array.size(), T::AXIS_COUNT);
T vector{};
for (int i = 0; i < size; i++) {
vector[i] = array.get(i);
}
return vector;
}
return p_variant; // Default Variant conversion, covers all Vector2/3/4(i) types.
}
inline bool is_number_array(const Array &p_array) {
const int size = p_array.size();
for (int i = 0; i < size; i++) {
if (!p_array.get(i).is_num()) {
return false;
}
}
return true;
}
inline bool is_convertible_array(Variant::Type type) {
return type == Variant::ARRAY ||
type == Variant::PACKED_VECTOR2_ARRAY ||
type == Variant::PACKED_VECTOR3_ARRAY ||
type == Variant::PACKED_COLOR_ARRAY ||
type == Variant::PACKED_VECTOR4_ARRAY;
}
template <typename, typename = void>
inline constexpr bool is_vector_type_v = false;
template <typename T>
inline constexpr bool is_vector_type_v<T, std::void_t<decltype(T::AXIS_COUNT)>> = true;
template <typename T, typename P>
void convert_item_std140(const T &p_item, P *p_write, bool p_compact = false) {
VariantConverterStd140<T>::template convert<P>(p_item, p_write, p_compact);
}
template <typename T, typename P>
Vector<P> convert_array_std140(const Variant &p_variant, [[maybe_unused]] bool p_linear_color = false) {
if (is_convertible_array(p_variant.get_type())) {
// Slow path, convert Variant arrays and some packed arrays manually into primitive types.
const Array &array = p_variant;
if (is_number_array(array)) {
// Already flattened and converted (or empty) array, usually coming from saved resources.
return p_variant;
}
const int items = array.size();
constexpr int elements = VariantConverterStd140<T>::Elements;
Vector<P> result;
result.resize(items * elements);
P *write = result.ptrw();
for (int i = 0; i < items; i++) {
const Variant &item = array.get(i);
P *offset = write + (i * elements);
if constexpr (is_vector_type_v<T>) {
const T &vec = convert_to_vector<T>(item, p_linear_color);
convert_item_std140<T, P>(vec, offset, true);
} else {
convert_item_std140<T, P>(item.operator T(), offset, true);
}
}
return result;
} else if (p_variant.is_array()) {
// Fast path, return the packed array directly.
return p_variant;
}
// Not an array type. Usually happens with uninitialized null shader resource parameters.
// Just return an empty array, uniforms will be default initialized later.
return Vector<P>();
}
template <typename T, typename From, typename To>
void write_array_std140(const Vector<From> &p_values, To *p_write, int p_array_size, int p_stride) {
constexpr int elements = VariantConverterStd140<T>::Elements;
const int src_count = p_values.size();
const int dst_count = elements * p_array_size;
const int stride_count = p_stride * p_array_size;
const From *read = p_values.ptr();
const T default_value{};
memset(p_write, 0, sizeof(To) * stride_count);
for (int i = 0, j = 0; i < dst_count; i += elements, j += p_stride) {
if (i + elements - 1 < src_count) {
// Only copy full items with all elements, no partial or missing data.
for (int e = 0; e < elements; e++) {
DEV_ASSERT(j + e < stride_count && i + e < src_count);
p_write[j + e] = read[i + e];
}
} else {
// If not enough source data was passed in, write default values.
convert_item_std140(default_value, p_write + j);
}
}
}