mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-30 21:09:19 +01:00
Added back GIProbes.
This commit is contained in:
parent
85cddb07b4
commit
efccdca45f
86
doc/classes/GIProbe.xml
Normal file
86
doc/classes/GIProbe.xml
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="GIProbe" inherits="VisualInstance" version="3.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Real-time global illumination (GI) probe.
|
||||
</brief_description>
|
||||
<description>
|
||||
[GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked.
|
||||
Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/quality/voxel_cone_tracing/high_quality].
|
||||
[b]Procedural generation:[/b] [GIProbe] can be baked in an exported project, which makes it suitable for procedurally generated or user-built levels as long as all the geometry is generated in advance.
|
||||
[b]Performance:[/b] [GIProbe] is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [BakedLightmap] instead). To provide a fallback for low-end hardware, consider adding an option to disable [GIProbe] in your project's options menus. A [GIProbe] node can be disabled by hiding it.
|
||||
[b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. To further prevent light leaks, you can also strategically place temporary [MeshInstance] nodes with [member GeometryInstance.use_in_baked_light] enabled. These temporary nodes can then be hidden after baking the [GIProbe] node.
|
||||
[b]Note:[/b] Due to a renderer limitation, emissive [ShaderMaterial]s cannot emit light when used in a [GIProbe]. Only emissive [SpatialMaterial]s can emit light in a [GIProbe].
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="GI probes">$DOCS_URL/tutorials/3d/gi_probes.html</link>
|
||||
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="bake">
|
||||
<return type="void" />
|
||||
<argument index="0" name="from_node" type="Node" default="null" />
|
||||
<argument index="1" name="create_visual_debug" type="bool" default="false" />
|
||||
<description>
|
||||
Bakes the effect from all [GeometryInstance]s marked with [member GeometryInstance.use_in_baked_light] and [Light]s marked with either [constant Light.BAKE_INDIRECT] or [constant Light.BAKE_ALL]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring.
|
||||
[b]Note:[/b] [method bake] works from the editor and in exported projects. This makes it suitable for procedurally generated or user-built levels. Baking a [GIProbe] generally takes from 5 to 20 seconds in most scenes. Reducing [member subdiv] can speed up baking.
|
||||
[b]Note:[/b] [GeometryInstance]s and [Light]s must be fully ready before [method bake] is called. If you are procedurally creating those and some meshes or lights are missing from your baked [GIProbe], use [code]call_deferred("bake")[/code] instead of calling [method bake] directly.
|
||||
</description>
|
||||
</method>
|
||||
<method name="debug_bake">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Calls [method bake] with [code]create_visual_debug[/code] enabled.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="1.5">
|
||||
Offsets the lookup of the light contribution from the [GIProbe]. This can be used to avoid self-shadowing, but may introduce light leaking at higher values. This and [member normal_bias] should be played around with to minimize self-shadowing and light leaking.
|
||||
[b]Note:[/b] [code]bias[/code] should usually be above 1.0 as that is the size of the voxels.
|
||||
</member>
|
||||
<member name="compress" type="bool" setter="set_compress" getter="is_compressed" default="false">
|
||||
[i]Deprecated.[/i] This property has been deprecated due to known bugs and no longer has any effect when enabled.
|
||||
</member>
|
||||
<member name="data" type="GIProbeData" setter="set_probe_data" getter="get_probe_data">
|
||||
The [GIProbeData] resource that holds the data for this [GIProbe].
|
||||
</member>
|
||||
<member name="dynamic_range" type="int" setter="set_dynamic_range" getter="get_dynamic_range" default="4">
|
||||
The maximum brightness that the [GIProbe] will recognize. Brightness will be scaled within this range.
|
||||
</member>
|
||||
<member name="energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
|
||||
Energy multiplier. Makes the lighting contribution from the [GIProbe] brighter.
|
||||
</member>
|
||||
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 10, 10, 10 )">
|
||||
The size of the area covered by the [GIProbe]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting.
|
||||
</member>
|
||||
<member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
|
||||
If [code]true[/code], ignores the sky contribution when calculating lighting.
|
||||
</member>
|
||||
<member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0">
|
||||
Offsets the lookup into the [GIProbe] based on the object's normal direction. Can be used to reduce some self-shadowing artifacts.
|
||||
</member>
|
||||
<member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7">
|
||||
How much light propagates through the probe internally. A higher value allows light to spread further.
|
||||
</member>
|
||||
<member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" enum="GIProbe.Subdiv" default="1">
|
||||
Number of times to subdivide the grid that the [GIProbe] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="SUBDIV_64" value="0" enum="Subdiv">
|
||||
Use 64 subdivisions. This is the lowest quality setting, but the fastest. Use it if you can, but especially use it on lower-end hardware.
|
||||
</constant>
|
||||
<constant name="SUBDIV_128" value="1" enum="Subdiv">
|
||||
Use 128 subdivisions. This is the default quality setting.
|
||||
</constant>
|
||||
<constant name="SUBDIV_256" value="2" enum="Subdiv">
|
||||
Use 256 subdivisions.
|
||||
</constant>
|
||||
<constant name="SUBDIV_512" value="3" enum="Subdiv">
|
||||
Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware, this could cause the GPU to stall.
|
||||
</constant>
|
||||
<constant name="SUBDIV_MAX" value="4" enum="Subdiv">
|
||||
Represents the size of the [enum Subdiv] enum.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
38
doc/classes/GIProbeData.xml
Normal file
38
doc/classes/GIProbeData.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="GIProbeData" inherits="Resource" version="3.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.4">
|
||||
</member>
|
||||
<member name="bounds" type="AABB" setter="set_bounds" getter="get_bounds" default="AABB( 0, 0, 0, 1, 1, 1 )">
|
||||
</member>
|
||||
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="1.0">
|
||||
</member>
|
||||
<member name="compress" type="bool" setter="set_compress" getter="is_compressed" default="false">
|
||||
</member>
|
||||
<member name="dynamic_data" type="PoolIntArray" setter="set_dynamic_data" getter="get_dynamic_data" default="PoolIntArray( )">
|
||||
</member>
|
||||
<member name="dynamic_range" type="int" setter="set_dynamic_range" getter="get_dynamic_range" default="1">
|
||||
</member>
|
||||
<member name="energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
|
||||
</member>
|
||||
<member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
|
||||
</member>
|
||||
<member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.4">
|
||||
</member>
|
||||
<member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="1.0">
|
||||
</member>
|
||||
<member name="to_cell_xform" type="Transform" setter="set_to_cell_xform" getter="get_to_cell_xform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -101,6 +101,11 @@ public:
|
||||
bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
|
||||
bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
|
||||
|
||||
RID gi_probe_instance_create() { return RID(); }
|
||||
void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
|
||||
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {}
|
||||
void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {}
|
||||
|
||||
void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {}
|
||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
|
||||
|
||||
@ -589,6 +594,51 @@ public:
|
||||
|
||||
virtual bool particles_is_inactive(RID p_particles) const { return false; }
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
RID gi_probe_create() { return RID(); }
|
||||
|
||||
void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {}
|
||||
AABB gi_probe_get_bounds(RID p_probe) const { return AABB(); }
|
||||
|
||||
void gi_probe_set_cell_size(RID p_probe, float p_range) {}
|
||||
float gi_probe_get_cell_size(RID p_probe) const { return 0.0; }
|
||||
|
||||
void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) {}
|
||||
Transform gi_probe_get_to_cell_xform(RID p_probe) const { return Transform(); }
|
||||
|
||||
void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) {}
|
||||
PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const {
|
||||
PoolVector<int> p;
|
||||
return p;
|
||||
}
|
||||
|
||||
void gi_probe_set_dynamic_range(RID p_probe, int p_range) {}
|
||||
int gi_probe_get_dynamic_range(RID p_probe) const { return 0; }
|
||||
|
||||
void gi_probe_set_energy(RID p_probe, float p_range) {}
|
||||
float gi_probe_get_energy(RID p_probe) const { return 0.0; }
|
||||
|
||||
void gi_probe_set_bias(RID p_probe, float p_range) {}
|
||||
float gi_probe_get_bias(RID p_probe) const { return 0.0; }
|
||||
|
||||
void gi_probe_set_normal_bias(RID p_probe, float p_range) {}
|
||||
float gi_probe_get_normal_bias(RID p_probe) const { return 0.0; }
|
||||
|
||||
void gi_probe_set_propagation(RID p_probe, float p_range) {}
|
||||
float gi_probe_get_propagation(RID p_probe) const { return 0.0; }
|
||||
|
||||
void gi_probe_set_interior(RID p_probe, bool p_enable) {}
|
||||
bool gi_probe_is_interior(RID p_probe) const { return false; }
|
||||
|
||||
void gi_probe_set_compress(RID p_probe, bool p_enable) {}
|
||||
bool gi_probe_is_compressed(RID p_probe) const { return false; }
|
||||
|
||||
uint32_t gi_probe_get_version(RID p_probe) { return 0; }
|
||||
|
||||
RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { return RID(); }
|
||||
void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {}
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
struct Instantiable : public RID_Data {
|
||||
SelfList<RasterizerScene::InstanceBase>::List instance_list;
|
||||
|
@ -976,6 +976,22 @@ void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) {
|
||||
light_instance->last_scene_pass = scene_pass;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
||||
RID RasterizerSceneGLES2::gi_probe_instance_create() {
|
||||
return RID();
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {
|
||||
}
|
||||
void RasterizerSceneGLES2::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////
|
||||
////////////////////////////
|
||||
////////////////////////////
|
||||
|
@ -553,6 +553,15 @@ public:
|
||||
int render_directional_lights;
|
||||
int render_light_instance_count;
|
||||
|
||||
/* REFLECTION INSTANCE */
|
||||
|
||||
virtual RID gi_probe_instance_create();
|
||||
virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data);
|
||||
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
|
||||
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds);
|
||||
|
||||
|
||||
|
||||
/* RENDER LIST */
|
||||
|
||||
enum LightMode {
|
||||
|
@ -4759,6 +4759,99 @@ bool RasterizerStorageGLES2::particles_is_inactive(RID p_particles) const {
|
||||
|
||||
///////
|
||||
|
||||
RID RasterizerStorageGLES2::gi_probe_create() {
|
||||
return RID();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {
|
||||
}
|
||||
|
||||
AABB RasterizerStorageGLES2::gi_probe_get_bounds(RID p_probe) const {
|
||||
return AABB();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_cell_size(RID p_probe, float p_size) {
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES2::gi_probe_get_cell_size(RID p_probe) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) {
|
||||
}
|
||||
|
||||
Transform RasterizerStorageGLES2::gi_probe_get_to_cell_xform(RID p_probe) const {
|
||||
return Transform();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) {
|
||||
}
|
||||
|
||||
PoolVector<int> RasterizerStorageGLES2::gi_probe_get_dynamic_data(RID p_probe) const {
|
||||
return PoolVector<int>();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_dynamic_range(RID p_probe, int p_range) {
|
||||
}
|
||||
|
||||
int RasterizerStorageGLES2::gi_probe_get_dynamic_range(RID p_probe) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_energy(RID p_probe, float p_range) {
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_bias(RID p_probe, float p_range) {
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_normal_bias(RID p_probe, float p_range) {
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_propagation(RID p_probe, float p_range) {
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_interior(RID p_probe, bool p_enable) {
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES2::gi_probe_is_interior(RID p_probe) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_set_compress(RID p_probe, bool p_enable) {
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES2::gi_probe_is_compressed(RID p_probe) const {
|
||||
return false;
|
||||
}
|
||||
float RasterizerStorageGLES2::gi_probe_get_energy(RID p_probe) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES2::gi_probe_get_bias(RID p_probe) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES2::gi_probe_get_normal_bias(RID p_probe) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES2::gi_probe_get_propagation(RID p_probe) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t RasterizerStorageGLES2::gi_probe_get_version(RID p_probe) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES2::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {
|
||||
}
|
||||
|
||||
///////
|
||||
|
||||
RID RasterizerStorageGLES2::lightmap_capture_create() {
|
||||
LightmapCapture *capture = memnew(LightmapCapture);
|
||||
return lightmap_capture_data_owner.make_rid(capture);
|
||||
|
@ -1091,6 +1091,48 @@ public:
|
||||
|
||||
virtual bool particles_is_inactive(RID p_particles) const;
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
virtual RID gi_probe_create();
|
||||
|
||||
virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds);
|
||||
virtual AABB gi_probe_get_bounds(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_cell_size(RID p_probe, float p_size);
|
||||
virtual float gi_probe_get_cell_size(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform);
|
||||
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data);
|
||||
virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range);
|
||||
virtual int gi_probe_get_dynamic_range(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_energy(RID p_probe, float p_range);
|
||||
virtual float gi_probe_get_energy(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_bias(RID p_probe, float p_range);
|
||||
virtual float gi_probe_get_bias(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_normal_bias(RID p_probe, float p_range);
|
||||
virtual float gi_probe_get_normal_bias(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_propagation(RID p_probe, float p_range);
|
||||
virtual float gi_probe_get_propagation(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_interior(RID p_probe, bool p_enable);
|
||||
virtual bool gi_probe_is_interior(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_compress(RID p_probe, bool p_enable);
|
||||
virtual bool gi_probe_is_compressed(RID p_probe) const;
|
||||
|
||||
virtual uint32_t gi_probe_get_version(RID p_probe);
|
||||
|
||||
virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression);
|
||||
virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data);
|
||||
|
||||
/* LIGHTMAP */
|
||||
|
||||
struct LightmapCapture : public Instantiable {
|
||||
|
@ -120,6 +120,7 @@
|
||||
#include "editor/plugins/cpu_particles_editor_plugin.h"
|
||||
#include "editor/plugins/curve_editor_plugin.h"
|
||||
#include "editor/plugins/editor_preview_plugins.h"
|
||||
#include "editor/plugins/gi_probe_editor_plugin.h"
|
||||
#include "editor/plugins/gradient_editor_plugin.h"
|
||||
#include "editor/plugins/gradient_texture_2d_editor_plugin.h"
|
||||
#include "editor/plugins/item_list_editor_plugin.h"
|
||||
@ -7169,6 +7170,7 @@ EditorNode::EditorNode() {
|
||||
add_editor_plugin(memnew(GPUParticlesEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(CPUParticles2DEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(CPUParticlesEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(GIProbeEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
|
||||
|
103
editor/plugins/gi_probe_editor_plugin.cpp
Normal file
103
editor/plugins/gi_probe_editor_plugin.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/**************************************************************************/
|
||||
/* gi_probe_editor_plugin.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 "gi_probe_editor_plugin.h"
|
||||
|
||||
#include "editor/editor_node.h"
|
||||
#include "scene/3d/gi_probe.h"
|
||||
#include "scene/gui/tool_button.h"
|
||||
|
||||
void GIProbeEditorPlugin::_bake() {
|
||||
if (gi_probe) {
|
||||
gi_probe->bake();
|
||||
}
|
||||
}
|
||||
|
||||
void GIProbeEditorPlugin::edit(Object *p_object) {
|
||||
GIProbe *s = Object::cast_to<GIProbe>(p_object);
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
gi_probe = s;
|
||||
}
|
||||
|
||||
bool GIProbeEditorPlugin::handles(Object *p_object) const {
|
||||
return p_object->is_class("GIProbe");
|
||||
}
|
||||
|
||||
void GIProbeEditorPlugin::make_visible(bool p_visible) {
|
||||
if (p_visible) {
|
||||
bake->show();
|
||||
} else {
|
||||
bake->hide();
|
||||
}
|
||||
}
|
||||
|
||||
EditorProgress *GIProbeEditorPlugin::tmp_progress = nullptr;
|
||||
|
||||
void GIProbeEditorPlugin::bake_func_begin(int p_steps) {
|
||||
ERR_FAIL_COND(tmp_progress != nullptr);
|
||||
|
||||
tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps));
|
||||
}
|
||||
|
||||
void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) {
|
||||
ERR_FAIL_COND(tmp_progress == nullptr);
|
||||
tmp_progress->step(p_description, p_step, false);
|
||||
}
|
||||
|
||||
void GIProbeEditorPlugin::bake_func_end() {
|
||||
ERR_FAIL_COND(tmp_progress == nullptr);
|
||||
memdelete(tmp_progress);
|
||||
tmp_progress = nullptr;
|
||||
}
|
||||
|
||||
void GIProbeEditorPlugin::_bind_methods() {
|
||||
ClassDB::bind_method("_bake", &GIProbeEditorPlugin::_bake);
|
||||
}
|
||||
|
||||
GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) {
|
||||
editor = p_node;
|
||||
bake = memnew(ToolButton);
|
||||
bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
|
||||
bake->set_text(TTR("Bake GI Probe"));
|
||||
bake->hide();
|
||||
bake->connect("pressed", this, "_bake");
|
||||
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake);
|
||||
gi_probe = nullptr;
|
||||
|
||||
GIProbe::bake_begin_function = bake_func_begin;
|
||||
GIProbe::bake_step_function = bake_func_step;
|
||||
GIProbe::bake_end_function = bake_func_end;
|
||||
}
|
||||
|
||||
GIProbeEditorPlugin::~GIProbeEditorPlugin() {
|
||||
}
|
70
editor/plugins/gi_probe_editor_plugin.h
Normal file
70
editor/plugins/gi_probe_editor_plugin.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**************************************************************************/
|
||||
/* gi_probe_editor_plugin.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GI_PROBE_EDITOR_PLUGIN_H
|
||||
#define GI_PROBE_EDITOR_PLUGIN_H
|
||||
|
||||
#include "editor/editor_plugin.h"
|
||||
|
||||
class ToolBoutton;
|
||||
class GIProbe;
|
||||
class EditorNode;
|
||||
class EditorProgress;
|
||||
|
||||
class GIProbeEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(GIProbeEditorPlugin, EditorPlugin);
|
||||
|
||||
GIProbe *gi_probe;
|
||||
|
||||
ToolButton *bake;
|
||||
EditorNode *editor;
|
||||
|
||||
static EditorProgress *tmp_progress;
|
||||
static void bake_func_begin(int p_steps);
|
||||
static void bake_func_step(int p_step, const String &p_description);
|
||||
static void bake_func_end();
|
||||
|
||||
void _bake();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "GIProbe"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
GIProbeEditorPlugin(EditorNode *p_node);
|
||||
~GIProbeEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // GI_PROBE_EDITOR_PLUGIN_H
|
@ -7189,6 +7189,7 @@ void SpatialEditor::_register_all_gizmos() {
|
||||
add_gizmo_plugin(Ref<GPUParticlesGizmoPlugin>(memnew(GPUParticlesGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<CPUParticlesGizmoPlugin>(memnew(CPUParticlesGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<CollisionObjectGizmoPlugin>(memnew(CollisionObjectGizmoPlugin)));
|
||||
add_gizmo_plugin(Ref<CollisionShapeSpatialGizmoPlugin>(memnew(CollisionShapeSpatialGizmoPlugin)));
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "scene/3d/collision_polygon.h"
|
||||
#include "scene/3d/collision_shape.h"
|
||||
#include "scene/3d/cpu_particles.h"
|
||||
#include "scene/3d/gi_probe.h"
|
||||
#include "scene/3d/label_3d.h"
|
||||
#include "scene/3d/light.h"
|
||||
#include "scene/3d/listener.h"
|
||||
@ -3011,6 +3012,179 @@ void ReflectionProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
|
||||
p_gizmo->add_handles(handles, get_material("handles"));
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
GIProbeGizmoPlugin::GIProbeGizmoPlugin() {
|
||||
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6));
|
||||
|
||||
create_material("gi_probe_material", gizmo_color);
|
||||
|
||||
gizmo_color.a = 0.5;
|
||||
create_material("gi_probe_internal_material", gizmo_color);
|
||||
|
||||
gizmo_color.a = 0.1;
|
||||
create_material("gi_probe_solid_material", gizmo_color);
|
||||
|
||||
create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons"));
|
||||
create_handle_material("handles");
|
||||
}
|
||||
|
||||
bool GIProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) {
|
||||
return Object::cast_to<GIProbe>(p_spatial) != nullptr;
|
||||
}
|
||||
|
||||
String GIProbeGizmoPlugin::get_gizmo_name() const {
|
||||
return "GIProbe";
|
||||
}
|
||||
|
||||
int GIProbeGizmoPlugin::get_priority() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
String GIProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondar) const {
|
||||
switch (p_id) {
|
||||
case 0:
|
||||
return "Extents X";
|
||||
case 1:
|
||||
return "Extents Y";
|
||||
case 2:
|
||||
return "Extents Z";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
Variant GIProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondar) const {
|
||||
GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
|
||||
return probe->get_extents();
|
||||
}
|
||||
void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondar, Camera *p_camera, const Point2 &p_point) {
|
||||
GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
|
||||
|
||||
Transform gt = probe->get_global_transform();
|
||||
Transform gi = gt.affine_inverse();
|
||||
|
||||
Vector3 extents = probe->get_extents();
|
||||
|
||||
Vector3 ray_from = p_camera->project_ray_origin(p_point);
|
||||
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
|
||||
|
||||
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
|
||||
|
||||
Vector3 axis;
|
||||
axis[p_id] = 1.0;
|
||||
|
||||
Vector3 ra, rb;
|
||||
Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
|
||||
float d = ra[p_id];
|
||||
if (SpatialEditor::get_singleton()->is_snap_enabled()) {
|
||||
d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
|
||||
}
|
||||
|
||||
if (d < 0.001) {
|
||||
d = 0.001;
|
||||
}
|
||||
|
||||
extents[p_id] = d;
|
||||
probe->set_extents(extents);
|
||||
}
|
||||
|
||||
void GIProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondar, const Variant &p_restore, bool p_cancel) {
|
||||
GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
|
||||
|
||||
Vector3 restore = p_restore;
|
||||
|
||||
if (p_cancel) {
|
||||
probe->set_extents(restore);
|
||||
return;
|
||||
}
|
||||
|
||||
UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
|
||||
ur->create_action(TTR("Change Probe Extents"));
|
||||
ur->add_do_method(probe, "set_extents", probe->get_extents());
|
||||
ur->add_undo_method(probe, "set_extents", restore);
|
||||
ur->commit_action();
|
||||
}
|
||||
|
||||
void GIProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
|
||||
GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
|
||||
|
||||
Ref<Material> material = get_material("gi_probe_material", p_gizmo);
|
||||
Ref<Material> icon = get_material("gi_probe_icon", p_gizmo);
|
||||
Ref<Material> material_internal = get_material("gi_probe_internal_material", p_gizmo);
|
||||
|
||||
p_gizmo->clear();
|
||||
|
||||
Vector<Vector3> lines;
|
||||
Vector3 extents = probe->get_extents();
|
||||
|
||||
static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 };
|
||||
|
||||
AABB aabb = AABB(-extents, extents * 2);
|
||||
int subdiv = subdivs[probe->get_subdiv()];
|
||||
float cell_size = aabb.get_longest_axis_size() / subdiv;
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
Vector3 a, b;
|
||||
aabb.get_edge(i, a, b);
|
||||
lines.push_back(a);
|
||||
lines.push_back(b);
|
||||
}
|
||||
|
||||
p_gizmo->add_lines(lines, material);
|
||||
|
||||
lines.clear();
|
||||
|
||||
for (int i = 1; i < subdiv; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (cell_size * i > aabb.size[j]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int j_n1 = (j + 1) % 3;
|
||||
int j_n2 = (j + 2) % 3;
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
Vector3 from = aabb.position, to = aabb.position;
|
||||
from[j] += cell_size * i;
|
||||
to[j] += cell_size * i;
|
||||
|
||||
if (k & 1) {
|
||||
to[j_n1] += aabb.size[j_n1];
|
||||
} else {
|
||||
to[j_n2] += aabb.size[j_n2];
|
||||
}
|
||||
|
||||
if (k & 2) {
|
||||
from[j_n1] += aabb.size[j_n1];
|
||||
from[j_n2] += aabb.size[j_n2];
|
||||
}
|
||||
|
||||
lines.push_back(from);
|
||||
lines.push_back(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_gizmo->add_lines(lines, material_internal);
|
||||
|
||||
Vector<Vector3> handles;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Vector3 ax;
|
||||
ax[i] = aabb.position[i] + aabb.size[i];
|
||||
handles.push_back(ax);
|
||||
}
|
||||
|
||||
if (p_gizmo->is_selected()) {
|
||||
Ref<Material> solid_material = get_material("gi_probe_solid_material", p_gizmo);
|
||||
p_gizmo->add_solid_box(solid_material, aabb.get_size());
|
||||
}
|
||||
|
||||
p_gizmo->add_unscaled_billboard(icon, 0.05);
|
||||
p_gizmo->add_handles(handles, get_material("handles"));
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
|
||||
BakedIndirectLightGizmoPlugin::BakedIndirectLightGizmoPlugin() {
|
||||
|
@ -471,6 +471,23 @@ public:
|
||||
ReflectionProbeGizmoPlugin();
|
||||
};
|
||||
|
||||
class GIProbeGizmoPlugin : public EditorSpatialGizmoPlugin {
|
||||
GDCLASS(GIProbeGizmoPlugin, EditorSpatialGizmoPlugin);
|
||||
|
||||
public:
|
||||
bool has_gizmo(Spatial *p_spatial);
|
||||
String get_gizmo_name() const;
|
||||
int get_priority() const;
|
||||
void redraw(EditorSpatialGizmo *p_gizmo);
|
||||
|
||||
String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const;
|
||||
Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const;
|
||||
void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, Camera *p_camera, const Point2 &p_point);
|
||||
void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false);
|
||||
|
||||
GIProbeGizmoPlugin();
|
||||
};
|
||||
|
||||
class BakedIndirectLightGizmoPlugin : public EditorSpatialGizmoPlugin {
|
||||
GDCLASS(BakedIndirectLightGizmoPlugin, EditorSpatialGizmoPlugin);
|
||||
|
||||
|
535
scene/3d/gi_probe.cpp
Normal file
535
scene/3d/gi_probe.cpp
Normal file
@ -0,0 +1,535 @@
|
||||
/**************************************************************************/
|
||||
/* gi_probe.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 "gi_probe.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include "mesh_instance.h"
|
||||
#include "voxel_light_baker.h"
|
||||
|
||||
void GIProbeData::set_bounds(const AABB &p_bounds) {
|
||||
RS::get_singleton()->gi_probe_set_bounds(probe, p_bounds);
|
||||
}
|
||||
|
||||
AABB GIProbeData::get_bounds() const {
|
||||
return RS::get_singleton()->gi_probe_get_bounds(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_cell_size(float p_size) {
|
||||
RS::get_singleton()->gi_probe_set_cell_size(probe, p_size);
|
||||
}
|
||||
|
||||
float GIProbeData::get_cell_size() const {
|
||||
return RS::get_singleton()->gi_probe_get_cell_size(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_to_cell_xform(const Transform &p_xform) {
|
||||
RS::get_singleton()->gi_probe_set_to_cell_xform(probe, p_xform);
|
||||
}
|
||||
|
||||
Transform GIProbeData::get_to_cell_xform() const {
|
||||
return RS::get_singleton()->gi_probe_get_to_cell_xform(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_dynamic_data(const PoolVector<int> &p_data) {
|
||||
RS::get_singleton()->gi_probe_set_dynamic_data(probe, p_data);
|
||||
}
|
||||
PoolVector<int> GIProbeData::get_dynamic_data() const {
|
||||
return RS::get_singleton()->gi_probe_get_dynamic_data(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_dynamic_range(int p_range) {
|
||||
RS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range);
|
||||
}
|
||||
|
||||
void GIProbeData::set_energy(float p_range) {
|
||||
RS::get_singleton()->gi_probe_set_energy(probe, p_range);
|
||||
}
|
||||
|
||||
float GIProbeData::get_energy() const {
|
||||
return RS::get_singleton()->gi_probe_get_energy(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_bias(float p_range) {
|
||||
RS::get_singleton()->gi_probe_set_bias(probe, p_range);
|
||||
}
|
||||
|
||||
float GIProbeData::get_bias() const {
|
||||
return RS::get_singleton()->gi_probe_get_bias(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_normal_bias(float p_range) {
|
||||
RS::get_singleton()->gi_probe_set_normal_bias(probe, p_range);
|
||||
}
|
||||
|
||||
float GIProbeData::get_normal_bias() const {
|
||||
return RS::get_singleton()->gi_probe_get_normal_bias(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_propagation(float p_range) {
|
||||
RS::get_singleton()->gi_probe_set_propagation(probe, p_range);
|
||||
}
|
||||
|
||||
float GIProbeData::get_propagation() const {
|
||||
return RS::get_singleton()->gi_probe_get_propagation(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_interior(bool p_enable) {
|
||||
RS::get_singleton()->gi_probe_set_interior(probe, p_enable);
|
||||
}
|
||||
|
||||
bool GIProbeData::is_interior() const {
|
||||
return RS::get_singleton()->gi_probe_is_interior(probe);
|
||||
}
|
||||
|
||||
bool GIProbeData::is_compressed() const {
|
||||
return RS::get_singleton()->gi_probe_is_compressed(probe);
|
||||
}
|
||||
|
||||
void GIProbeData::set_compress(bool p_enable) {
|
||||
RS::get_singleton()->gi_probe_set_compress(probe, p_enable);
|
||||
}
|
||||
|
||||
int GIProbeData::get_dynamic_range() const {
|
||||
return RS::get_singleton()->gi_probe_get_dynamic_range(probe);
|
||||
}
|
||||
|
||||
RID GIProbeData::get_rid() const {
|
||||
return probe;
|
||||
}
|
||||
|
||||
void GIProbeData::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &GIProbeData::set_bounds);
|
||||
ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &GIProbeData::set_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_size"), &GIProbeData::get_cell_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_to_cell_xform", "to_cell_xform"), &GIProbeData::set_to_cell_xform);
|
||||
ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_dynamic_data", "dynamic_data"), &GIProbeData::set_dynamic_data);
|
||||
ClassDB::bind_method(D_METHOD("get_dynamic_data"), &GIProbeData::get_dynamic_data);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range);
|
||||
ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_energy", "energy"), &GIProbeData::set_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_energy"), &GIProbeData::get_energy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation);
|
||||
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior);
|
||||
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress);
|
||||
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "dynamic_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_data", "get_dynamic_data");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed");
|
||||
}
|
||||
|
||||
GIProbeData::GIProbeData() {
|
||||
probe = RID_PRIME(RS::get_singleton()->gi_probe_create());
|
||||
}
|
||||
|
||||
GIProbeData::~GIProbeData() {
|
||||
if (probe.is_valid()) {
|
||||
RS::get_singleton()->free(probe);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
//////////////////////
|
||||
|
||||
void GIProbe::set_probe_data(const Ref<GIProbeData> &p_data) {
|
||||
if (p_data.is_valid()) {
|
||||
RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->instance_set_base(get_instance(), RID());
|
||||
}
|
||||
|
||||
probe_data = p_data;
|
||||
}
|
||||
|
||||
Ref<GIProbeData> GIProbe::get_probe_data() const {
|
||||
return probe_data;
|
||||
}
|
||||
|
||||
void GIProbe::set_subdiv(Subdiv p_subdiv) {
|
||||
ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
|
||||
subdiv = p_subdiv;
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
GIProbe::Subdiv GIProbe::get_subdiv() const {
|
||||
return subdiv;
|
||||
}
|
||||
|
||||
void GIProbe::set_extents(const Vector3 &p_extents) {
|
||||
extents = p_extents;
|
||||
update_gizmos();
|
||||
_change_notify("extents");
|
||||
}
|
||||
|
||||
Vector3 GIProbe::get_extents() const {
|
||||
return extents;
|
||||
}
|
||||
|
||||
void GIProbe::set_dynamic_range(int p_dynamic_range) {
|
||||
dynamic_range = p_dynamic_range;
|
||||
}
|
||||
int GIProbe::get_dynamic_range() const {
|
||||
return dynamic_range;
|
||||
}
|
||||
|
||||
void GIProbe::set_energy(float p_energy) {
|
||||
energy = p_energy;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_energy(energy);
|
||||
}
|
||||
}
|
||||
float GIProbe::get_energy() const {
|
||||
return energy;
|
||||
}
|
||||
|
||||
void GIProbe::set_bias(float p_bias) {
|
||||
bias = p_bias;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_bias(bias);
|
||||
}
|
||||
}
|
||||
float GIProbe::get_bias() const {
|
||||
return bias;
|
||||
}
|
||||
|
||||
void GIProbe::set_normal_bias(float p_normal_bias) {
|
||||
normal_bias = p_normal_bias;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_normal_bias(normal_bias);
|
||||
}
|
||||
}
|
||||
float GIProbe::get_normal_bias() const {
|
||||
return normal_bias;
|
||||
}
|
||||
|
||||
void GIProbe::set_propagation(float p_propagation) {
|
||||
propagation = p_propagation;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_propagation(propagation);
|
||||
}
|
||||
}
|
||||
float GIProbe::get_propagation() const {
|
||||
return propagation;
|
||||
}
|
||||
|
||||
void GIProbe::set_interior(bool p_enable) {
|
||||
interior = p_enable;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_interior(p_enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool GIProbe::is_interior() const {
|
||||
return interior;
|
||||
}
|
||||
|
||||
void GIProbe::set_compress(bool p_enable) {
|
||||
compress = p_enable;
|
||||
if (probe_data.is_valid()) {
|
||||
probe_data->set_compress(p_enable);
|
||||
}
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
bool GIProbe::is_compressed() const {
|
||||
return compress;
|
||||
}
|
||||
|
||||
void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
|
||||
MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
|
||||
if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
|
||||
Ref<Mesh> mesh = mi->get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
AABB aabb = mesh->get_aabb();
|
||||
|
||||
Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
|
||||
|
||||
if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
|
||||
PlotMesh pm;
|
||||
pm.local_xform = xf;
|
||||
pm.mesh = mesh;
|
||||
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
||||
pm.instance_materials.push_back(mi->get_surface_material(i));
|
||||
}
|
||||
pm.override_material = mi->get_material_override();
|
||||
plot_meshes.push_back(pm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spatial *s = Object::cast_to<Spatial>(p_at_node);
|
||||
if (s) {
|
||||
if (s->is_visible_in_tree()) {
|
||||
Array meshes = p_at_node->call("get_meshes");
|
||||
for (int i = 0; i < meshes.size(); i += 2) {
|
||||
Transform mxf = meshes[i];
|
||||
Ref<Mesh> mesh = meshes[i + 1];
|
||||
if (!mesh.is_valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AABB aabb = mesh->get_aabb();
|
||||
|
||||
Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
|
||||
|
||||
if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
|
||||
PlotMesh pm;
|
||||
pm.local_xform = xf;
|
||||
pm.mesh = mesh;
|
||||
plot_meshes.push_back(pm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_at_node->get_child_count(); i++) {
|
||||
Node *child = p_at_node->get_child(i);
|
||||
_find_meshes(child, plot_meshes);
|
||||
}
|
||||
}
|
||||
|
||||
GIProbe::BakeBeginFunc GIProbe::bake_begin_function = nullptr;
|
||||
GIProbe::BakeStepFunc GIProbe::bake_step_function = nullptr;
|
||||
GIProbe::BakeEndFunc GIProbe::bake_end_function = nullptr;
|
||||
|
||||
void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
|
||||
static const int subdiv_value[SUBDIV_MAX] = { 7, 8, 9, 10 };
|
||||
|
||||
p_from_node = p_from_node ? p_from_node : get_parent();
|
||||
ERR_FAIL_NULL(p_from_node);
|
||||
|
||||
VoxelLightBaker baker;
|
||||
|
||||
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
|
||||
|
||||
List<PlotMesh> mesh_list;
|
||||
|
||||
_find_meshes(p_from_node, mesh_list);
|
||||
|
||||
if (bake_begin_function) {
|
||||
bake_begin_function(mesh_list.size() + 1);
|
||||
}
|
||||
|
||||
int pmc = 0;
|
||||
|
||||
for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
|
||||
if (bake_step_function) {
|
||||
bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size()));
|
||||
}
|
||||
|
||||
pmc++;
|
||||
|
||||
baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material);
|
||||
}
|
||||
if (bake_step_function) {
|
||||
bake_step_function(pmc++, RTR("Finishing Plot"));
|
||||
}
|
||||
|
||||
baker.end_bake();
|
||||
|
||||
//create the data for visual server
|
||||
|
||||
PoolVector<int> data = baker.create_gi_probe_data();
|
||||
|
||||
if (p_create_visual_debug) {
|
||||
MultiMeshInstance *mmi = memnew(MultiMeshInstance);
|
||||
mmi->set_multimesh(baker.create_debug_multimesh());
|
||||
add_child(mmi);
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) {
|
||||
mmi->set_owner(this);
|
||||
} else {
|
||||
mmi->set_owner(get_owner());
|
||||
}
|
||||
#else
|
||||
mmi->set_owner(get_owner());
|
||||
#endif
|
||||
|
||||
} else {
|
||||
Ref<GIProbeData> probe_data = get_probe_data();
|
||||
|
||||
if (probe_data.is_null()) {
|
||||
probe_data.instance();
|
||||
}
|
||||
|
||||
probe_data->set_bounds(AABB(-extents, extents * 2.0));
|
||||
probe_data->set_cell_size(baker.get_cell_size());
|
||||
probe_data->set_dynamic_data(data);
|
||||
probe_data->set_dynamic_range(dynamic_range);
|
||||
probe_data->set_energy(energy);
|
||||
probe_data->set_bias(bias);
|
||||
probe_data->set_normal_bias(normal_bias);
|
||||
probe_data->set_propagation(propagation);
|
||||
probe_data->set_interior(interior);
|
||||
probe_data->set_compress(compress);
|
||||
probe_data->set_to_cell_xform(baker.get_to_cell_space_xform());
|
||||
|
||||
set_probe_data(probe_data);
|
||||
}
|
||||
|
||||
if (bake_end_function) {
|
||||
bake_end_function();
|
||||
}
|
||||
}
|
||||
|
||||
void GIProbe::_debug_bake() {
|
||||
bake(nullptr, true);
|
||||
}
|
||||
|
||||
AABB GIProbe::get_aabb() const {
|
||||
return AABB(-extents, extents * 2);
|
||||
}
|
||||
|
||||
PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
String GIProbe::get_configuration_warning() const {
|
||||
String warning = VisualInstance::get_configuration_warning();
|
||||
if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
|
||||
}
|
||||
|
||||
if (is_compressed()) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("The GIProbe Compress property has been deprecated due to known bugs and no longer has any effect.\nTo remove this warning, disable the GIProbe's Compress property.");
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
void GIProbe::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data);
|
||||
ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &GIProbe::set_subdiv);
|
||||
ClassDB::bind_method(D_METHOD("get_subdiv"), &GIProbe::get_subdiv);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents);
|
||||
ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_dynamic_range", "max"), &GIProbe::set_dynamic_range);
|
||||
ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbe::get_dynamic_range);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_energy", "max"), &GIProbe::set_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_energy"), &GIProbe::get_energy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation);
|
||||
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior", "enable"), &GIProbe::set_interior);
|
||||
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbe::is_interior);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_compress", "enable"), &GIProbe::set_compress);
|
||||
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbe::is_compressed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake);
|
||||
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "1,16,1"), "set_dynamic_range", "get_dynamic_range");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
|
||||
|
||||
BIND_ENUM_CONSTANT(SUBDIV_64);
|
||||
BIND_ENUM_CONSTANT(SUBDIV_128);
|
||||
BIND_ENUM_CONSTANT(SUBDIV_256);
|
||||
BIND_ENUM_CONSTANT(SUBDIV_512);
|
||||
BIND_ENUM_CONSTANT(SUBDIV_MAX);
|
||||
}
|
||||
|
||||
GIProbe::GIProbe() {
|
||||
subdiv = SUBDIV_128;
|
||||
dynamic_range = 4;
|
||||
energy = 1.0;
|
||||
bias = 1.5;
|
||||
normal_bias = 0.0;
|
||||
propagation = 0.7;
|
||||
extents = Vector3(10, 10, 10);
|
||||
interior = false;
|
||||
compress = false;
|
||||
|
||||
gi_probe = RID_PRIME(RS::get_singleton()->gi_probe_create());
|
||||
set_disable_scale(true);
|
||||
}
|
||||
|
||||
GIProbe::~GIProbe() {
|
||||
if (gi_probe.is_valid()) {
|
||||
RS::get_singleton()->free(gi_probe);
|
||||
}
|
||||
}
|
178
scene/3d/gi_probe.h
Normal file
178
scene/3d/gi_probe.h
Normal file
@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* gi_probe.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GI_PROBE_H
|
||||
#define GI_PROBE_H
|
||||
|
||||
#include "multimesh_instance.h"
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
class GIProbeData : public Resource {
|
||||
GDCLASS(GIProbeData, Resource);
|
||||
|
||||
RID probe;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_bounds(const AABB &p_bounds);
|
||||
AABB get_bounds() const;
|
||||
|
||||
void set_cell_size(float p_size);
|
||||
float get_cell_size() const;
|
||||
|
||||
void set_to_cell_xform(const Transform &p_xform);
|
||||
Transform get_to_cell_xform() const;
|
||||
|
||||
void set_dynamic_data(const PoolVector<int> &p_data);
|
||||
PoolVector<int> get_dynamic_data() const;
|
||||
|
||||
void set_dynamic_range(int p_range);
|
||||
int get_dynamic_range() const;
|
||||
|
||||
void set_propagation(float p_range);
|
||||
float get_propagation() const;
|
||||
|
||||
void set_energy(float p_range);
|
||||
float get_energy() const;
|
||||
|
||||
void set_bias(float p_range);
|
||||
float get_bias() const;
|
||||
|
||||
void set_normal_bias(float p_range);
|
||||
float get_normal_bias() const;
|
||||
|
||||
void set_interior(bool p_enable);
|
||||
bool is_interior() const;
|
||||
|
||||
void set_compress(bool p_enable);
|
||||
bool is_compressed() const;
|
||||
|
||||
virtual RID get_rid() const;
|
||||
|
||||
GIProbeData();
|
||||
~GIProbeData();
|
||||
};
|
||||
|
||||
class GIProbe : public VisualInstance {
|
||||
GDCLASS(GIProbe, VisualInstance);
|
||||
|
||||
public:
|
||||
enum Subdiv {
|
||||
SUBDIV_64,
|
||||
SUBDIV_128,
|
||||
SUBDIV_256,
|
||||
SUBDIV_512,
|
||||
SUBDIV_MAX
|
||||
|
||||
};
|
||||
|
||||
typedef void (*BakeBeginFunc)(int);
|
||||
typedef void (*BakeStepFunc)(int, const String &);
|
||||
typedef void (*BakeEndFunc)();
|
||||
|
||||
private:
|
||||
Ref<GIProbeData> probe_data;
|
||||
|
||||
RID gi_probe;
|
||||
|
||||
Subdiv subdiv;
|
||||
Vector3 extents;
|
||||
int dynamic_range;
|
||||
float energy;
|
||||
float bias;
|
||||
float normal_bias;
|
||||
float propagation;
|
||||
bool interior;
|
||||
bool compress;
|
||||
|
||||
struct PlotMesh {
|
||||
Ref<Material> override_material;
|
||||
Vector<Ref<Material>> instance_materials;
|
||||
Ref<Mesh> mesh;
|
||||
Transform local_xform;
|
||||
};
|
||||
|
||||
void _find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes);
|
||||
void _debug_bake();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static BakeBeginFunc bake_begin_function;
|
||||
static BakeStepFunc bake_step_function;
|
||||
static BakeEndFunc bake_end_function;
|
||||
|
||||
void set_probe_data(const Ref<GIProbeData> &p_data);
|
||||
Ref<GIProbeData> get_probe_data() const;
|
||||
|
||||
void set_subdiv(Subdiv p_subdiv);
|
||||
Subdiv get_subdiv() const;
|
||||
|
||||
void set_extents(const Vector3 &p_extents);
|
||||
Vector3 get_extents() const;
|
||||
|
||||
void set_dynamic_range(int p_dynamic_range);
|
||||
int get_dynamic_range() const;
|
||||
|
||||
void set_energy(float p_energy);
|
||||
float get_energy() const;
|
||||
|
||||
void set_bias(float p_bias);
|
||||
float get_bias() const;
|
||||
|
||||
void set_normal_bias(float p_normal_bias);
|
||||
float get_normal_bias() const;
|
||||
|
||||
void set_propagation(float p_propagation);
|
||||
float get_propagation() const;
|
||||
|
||||
void set_interior(bool p_enable);
|
||||
bool is_interior() const;
|
||||
|
||||
void set_compress(bool p_enable);
|
||||
bool is_compressed() const;
|
||||
|
||||
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
GIProbe();
|
||||
~GIProbe();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(GIProbe::Subdiv)
|
||||
|
||||
#endif // GI_PROBE_H
|
@ -198,6 +198,7 @@
|
||||
#include "scene/3d/collision_polygon.h"
|
||||
#include "scene/3d/collision_shape.h"
|
||||
#include "scene/3d/cpu_particles.h"
|
||||
#include "scene/3d/gi_probe.h"
|
||||
#include "scene/3d/immediate_geometry.h"
|
||||
#include "scene/3d/interpolated_camera.h"
|
||||
#include "scene/3d/light.h"
|
||||
@ -462,6 +463,8 @@ void register_scene_types() {
|
||||
ClassDB::register_class<OmniLight>();
|
||||
ClassDB::register_class<SpotLight>();
|
||||
ClassDB::register_class<ReflectionProbe>();
|
||||
ClassDB::register_class<GIProbe>();
|
||||
ClassDB::register_class<GIProbeData>();
|
||||
ClassDB::register_class<GPUParticles>();
|
||||
ClassDB::register_class<BakedLightmap>();
|
||||
ClassDB::register_class<BakedLightmapData>();
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
Vector<RID> materials;
|
||||
Vector<RID> light_instances;
|
||||
Vector<RID> reflection_probe_instances;
|
||||
Vector<RID> gi_probe_instances;
|
||||
|
||||
PoolVector<float> blend_values;
|
||||
|
||||
@ -183,6 +184,11 @@ public:
|
||||
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
|
||||
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
|
||||
|
||||
virtual RID gi_probe_instance_create() = 0;
|
||||
virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) = 0;
|
||||
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
|
||||
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0;
|
||||
|
||||
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
|
||||
@ -555,6 +561,54 @@ public:
|
||||
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;
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
virtual RID gi_probe_create() = 0;
|
||||
|
||||
virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
|
||||
virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0;
|
||||
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) = 0;
|
||||
virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0;
|
||||
virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_energy(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_bias(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_normal_bias(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_propagation(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0;
|
||||
virtual bool gi_probe_is_interior(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0;
|
||||
virtual bool gi_probe_is_compressed(RID p_probe) const = 0;
|
||||
|
||||
virtual uint32_t gi_probe_get_version(RID p_probe) = 0;
|
||||
|
||||
enum GIProbeCompression {
|
||||
GI_PROBE_UNCOMPRESSED,
|
||||
GI_PROBE_S3TC,
|
||||
GI_PROBE_ETC2
|
||||
};
|
||||
|
||||
virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) = 0;
|
||||
virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) = 0;
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
struct LightmapCaptureOctree {
|
||||
|
@ -113,6 +113,7 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
|
||||
RSG::scene->update_dirty_instances(); //update scene stuff
|
||||
|
||||
RSG::viewport->draw_viewports();
|
||||
RSG::scene->render_probes();
|
||||
_draw_margins();
|
||||
RSG::rasterizer->end_frame(p_swap_buffers);
|
||||
|
||||
|
@ -390,6 +390,43 @@ public:
|
||||
BIND1R(AABB, particles_get_current_aabb, RID)
|
||||
BIND2(particles_set_emission_transform, RID, const Transform &)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
BIND0R(RID, gi_probe_create)
|
||||
|
||||
BIND2(gi_probe_set_bounds, RID, const AABB &)
|
||||
BIND1RC(AABB, gi_probe_get_bounds, RID)
|
||||
|
||||
BIND2(gi_probe_set_cell_size, RID, float)
|
||||
BIND1RC(float, gi_probe_get_cell_size, RID)
|
||||
|
||||
BIND2(gi_probe_set_to_cell_xform, RID, const Transform &)
|
||||
BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
|
||||
|
||||
BIND2(gi_probe_set_dynamic_range, RID, int)
|
||||
BIND1RC(int, gi_probe_get_dynamic_range, RID)
|
||||
|
||||
BIND2(gi_probe_set_energy, RID, float)
|
||||
BIND1RC(float, gi_probe_get_energy, RID)
|
||||
|
||||
BIND2(gi_probe_set_bias, RID, float)
|
||||
BIND1RC(float, gi_probe_get_bias, RID)
|
||||
|
||||
BIND2(gi_probe_set_normal_bias, RID, float)
|
||||
BIND1RC(float, gi_probe_get_normal_bias, RID)
|
||||
|
||||
BIND2(gi_probe_set_propagation, RID, float)
|
||||
BIND1RC(float, gi_probe_get_propagation, RID)
|
||||
|
||||
BIND2(gi_probe_set_interior, RID, bool)
|
||||
BIND1RC(bool, gi_probe_is_interior, RID)
|
||||
|
||||
BIND2(gi_probe_set_compress, RID, bool)
|
||||
BIND1RC(bool, gi_probe_is_compressed, RID)
|
||||
|
||||
BIND2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &)
|
||||
BIND1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID)
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
BIND0R(RID, lightmap_capture_create)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -418,6 +418,9 @@ public:
|
||||
List<Instance *> reflection_probes;
|
||||
bool reflection_dirty;
|
||||
|
||||
List<Instance *> gi_probes;
|
||||
bool gi_probes_dirty;
|
||||
|
||||
List<Instance *> lightmap_captures;
|
||||
|
||||
InstanceGeometryData() {
|
||||
@ -425,6 +428,7 @@ public:
|
||||
reflection_dirty = true;
|
||||
can_cast_shadows = true;
|
||||
material_is_animated = true;
|
||||
gi_probes_dirty = true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -525,6 +529,108 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct InstanceGIProbeData : public InstanceBaseData {
|
||||
Instance *owner;
|
||||
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //gi probe iterator in geometry
|
||||
Instance *geometry;
|
||||
};
|
||||
|
||||
List<PairInfo> geometries;
|
||||
|
||||
RBSet<Instance *> lights;
|
||||
|
||||
struct LightCache {
|
||||
RS::LightType type;
|
||||
Transform transform;
|
||||
Color color;
|
||||
float energy;
|
||||
float radius;
|
||||
float attenuation;
|
||||
float spot_angle;
|
||||
float spot_attenuation;
|
||||
bool visible;
|
||||
|
||||
bool operator==(const LightCache &p_cache) {
|
||||
return (type == p_cache.type &&
|
||||
transform == p_cache.transform &&
|
||||
color == p_cache.color &&
|
||||
energy == p_cache.energy &&
|
||||
radius == p_cache.radius &&
|
||||
attenuation == p_cache.attenuation &&
|
||||
spot_angle == p_cache.spot_angle &&
|
||||
spot_attenuation == p_cache.spot_attenuation &&
|
||||
visible == p_cache.visible);
|
||||
}
|
||||
|
||||
bool operator!=(const LightCache &p_cache) {
|
||||
return !operator==(p_cache);
|
||||
}
|
||||
|
||||
LightCache() {
|
||||
type = RS::LIGHT_DIRECTIONAL;
|
||||
energy = 1.0;
|
||||
radius = 1.0;
|
||||
attenuation = 1.0;
|
||||
spot_angle = 1.0;
|
||||
spot_attenuation = 1.0;
|
||||
visible = true;
|
||||
}
|
||||
};
|
||||
|
||||
struct LocalData {
|
||||
uint16_t pos[3];
|
||||
uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights
|
||||
};
|
||||
|
||||
struct CompBlockS3TC {
|
||||
uint32_t offset; //offset in mipmap
|
||||
uint32_t source_count; //sources
|
||||
uint32_t sources[16]; //id for each source
|
||||
uint8_t alpha[8]; //alpha block is pre-computed
|
||||
};
|
||||
|
||||
struct Dynamic {
|
||||
RBMap<RID, LightCache> light_cache;
|
||||
RBMap<RID, LightCache> light_cache_changes;
|
||||
PoolVector<int> light_data;
|
||||
PoolVector<LocalData> local_data;
|
||||
Vector<Vector<uint32_t>> level_cell_lists;
|
||||
RID probe_data;
|
||||
bool enabled;
|
||||
int bake_dynamic_range;
|
||||
RasterizerStorage::GIProbeCompression compression;
|
||||
|
||||
Vector<PoolVector<uint8_t>> mipmaps_3d;
|
||||
Vector<PoolVector<CompBlockS3TC>> mipmaps_s3tc; //for s3tc
|
||||
|
||||
int updating_stage;
|
||||
float propagate;
|
||||
|
||||
int grid_size[3];
|
||||
|
||||
Transform light_to_cell_xform;
|
||||
|
||||
} dynamic;
|
||||
|
||||
RID probe_instance;
|
||||
|
||||
bool invalid;
|
||||
uint32_t base_version;
|
||||
|
||||
SelfList<InstanceGIProbeData> update_element;
|
||||
|
||||
InstanceGIProbeData() :
|
||||
update_element(this) {
|
||||
invalid = true;
|
||||
base_version = 0;
|
||||
dynamic.updating_stage = GI_UPDATE_STAGE_CHECK;
|
||||
}
|
||||
};
|
||||
|
||||
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
|
||||
|
||||
struct InstanceLightmapCaptureData : public InstanceBaseData {
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //iterator in geometry
|
||||
@ -786,6 +892,52 @@ public:
|
||||
void update_interpolation_tick(bool p_process = true);
|
||||
void update_interpolation_frame(bool p_process = true);
|
||||
|
||||
//probes
|
||||
struct GIProbeDataHeader {
|
||||
uint32_t version;
|
||||
uint32_t cell_subdiv;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
uint32_t cell_count;
|
||||
uint32_t leaf_cell_count;
|
||||
};
|
||||
|
||||
struct GIProbeDataCell {
|
||||
uint32_t children[8];
|
||||
uint32_t albedo;
|
||||
uint32_t emission;
|
||||
uint32_t normal;
|
||||
uint32_t level_alpha;
|
||||
};
|
||||
|
||||
enum {
|
||||
GI_UPDATE_STAGE_CHECK,
|
||||
GI_UPDATE_STAGE_LIGHTING,
|
||||
GI_UPDATE_STAGE_UPLOADING,
|
||||
};
|
||||
|
||||
void _gi_probe_bake_thread();
|
||||
static void _gi_probe_bake_threads(void *);
|
||||
|
||||
bool probe_bake_thread_exit;
|
||||
Thread probe_bake_thread;
|
||||
Semaphore probe_bake_sem;
|
||||
Mutex probe_bake_mutex;
|
||||
List<Instance *> probe_bake_list;
|
||||
|
||||
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
||||
void _gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell *p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell);
|
||||
|
||||
_FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells, int x, int y, int z, int p_cell_subdiv);
|
||||
void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell *p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate);
|
||||
void _bake_gi_probe_light(const GIProbeDataHeader *header, const GIProbeDataCell *cells, InstanceGIProbeData::LocalData *local_data, const uint32_t *leaves, int p_leaf_count, const InstanceGIProbeData::LightCache &light_cache, int p_sign);
|
||||
void _bake_gi_probe(Instance *p_gi_probe);
|
||||
bool _check_gi_probe(Instance *p_gi_probe);
|
||||
void _setup_gi_probe(Instance *p_instance);
|
||||
|
||||
void render_probes();
|
||||
|
||||
bool free(RID p_rid);
|
||||
|
||||
private:
|
||||
|
@ -153,6 +153,7 @@ void RenderingServerWrapMT::finish() {
|
||||
omni_light_free_cached_ids();
|
||||
spot_light_free_cached_ids();
|
||||
reflection_probe_free_cached_ids();
|
||||
gi_probe_free_cached_ids();
|
||||
particles_free_cached_ids();
|
||||
lightmap_capture_free_cached_ids();
|
||||
camera_free_cached_ids();
|
||||
|
@ -314,6 +314,43 @@ public:
|
||||
|
||||
FUNC1R(AABB, particles_get_current_aabb, RID)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
FUNCRID(gi_probe)
|
||||
|
||||
FUNC2(gi_probe_set_bounds, RID, const AABB &)
|
||||
FUNC1RC(AABB, gi_probe_get_bounds, RID)
|
||||
|
||||
FUNC2(gi_probe_set_cell_size, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_cell_size, RID)
|
||||
|
||||
FUNC2(gi_probe_set_to_cell_xform, RID, const Transform &)
|
||||
FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
|
||||
|
||||
FUNC2(gi_probe_set_dynamic_range, RID, int)
|
||||
FUNC1RC(int, gi_probe_get_dynamic_range, RID)
|
||||
|
||||
FUNC2(gi_probe_set_energy, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_energy, RID)
|
||||
|
||||
FUNC2(gi_probe_set_bias, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_bias, RID)
|
||||
|
||||
FUNC2(gi_probe_set_normal_bias, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_normal_bias, RID)
|
||||
|
||||
FUNC2(gi_probe_set_propagation, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_propagation, RID)
|
||||
|
||||
FUNC2(gi_probe_set_interior, RID, bool)
|
||||
FUNC1RC(bool, gi_probe_is_interior, RID)
|
||||
|
||||
FUNC2(gi_probe_set_compress, RID, bool)
|
||||
FUNC1RC(bool, gi_probe_is_compressed, RID)
|
||||
|
||||
FUNC2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &)
|
||||
FUNC1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID)
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
FUNCRID(lightmap_capture)
|
||||
|
@ -2024,6 +2024,30 @@ void RenderingServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows);
|
||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_create"), &RenderingServer::gi_probe_create);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &RenderingServer::gi_probe_set_bounds);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &RenderingServer::gi_probe_get_bounds);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &RenderingServer::gi_probe_set_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &RenderingServer::gi_probe_get_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &RenderingServer::gi_probe_set_to_cell_xform);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &RenderingServer::gi_probe_get_to_cell_xform);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &RenderingServer::gi_probe_set_dynamic_data);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &RenderingServer::gi_probe_get_dynamic_data);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &RenderingServer::gi_probe_set_dynamic_range);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &RenderingServer::gi_probe_get_dynamic_range);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &RenderingServer::gi_probe_set_energy);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &RenderingServer::gi_probe_get_energy);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &RenderingServer::gi_probe_set_bias);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &RenderingServer::gi_probe_get_bias);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &RenderingServer::gi_probe_set_normal_bias);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &RenderingServer::gi_probe_get_normal_bias);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &RenderingServer::gi_probe_set_propagation);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &RenderingServer::gi_probe_get_propagation);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &RenderingServer::gi_probe_set_interior);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &RenderingServer::gi_probe_is_interior);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &RenderingServer::gi_probe_set_compress);
|
||||
ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &RenderingServer::gi_probe_is_compressed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &RenderingServer::lightmap_capture_create);
|
||||
ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &RenderingServer::lightmap_capture_set_bounds);
|
||||
ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &RenderingServer::lightmap_capture_get_bounds);
|
||||
@ -2448,6 +2472,7 @@ void RenderingServer::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(INSTANCE_PARTICLES);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_MAX);
|
||||
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
|
||||
|
@ -535,6 +535,43 @@ public:
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
virtual RID gi_probe_create() = 0;
|
||||
|
||||
virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
|
||||
virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0;
|
||||
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) = 0;
|
||||
virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0;
|
||||
virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_energy(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_bias(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_normal_bias(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0;
|
||||
virtual float gi_probe_get_propagation(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0;
|
||||
virtual bool gi_probe_is_interior(RID p_probe) const = 0;
|
||||
|
||||
virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0;
|
||||
virtual bool gi_probe_is_compressed(RID p_probe) const = 0;
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
virtual RID lightmap_capture_create() = 0;
|
||||
@ -820,6 +857,7 @@ public:
|
||||
INSTANCE_PARTICLES,
|
||||
INSTANCE_LIGHT,
|
||||
INSTANCE_REFLECTION_PROBE,
|
||||
INSTANCE_GI_PROBE,
|
||||
INSTANCE_LIGHTMAP_CAPTURE,
|
||||
INSTANCE_MAX,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user