1/**************************************************************************/
2/* fog_volume.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "fog_volume.h"
32#include "scene/resources/environment.h"
33
34///////////////////////////
35
36void FogVolume::_bind_methods() {
37 ClassDB::bind_method(D_METHOD("set_size", "size"), &FogVolume::set_size);
38 ClassDB::bind_method(D_METHOD("get_size"), &FogVolume::get_size);
39 ClassDB::bind_method(D_METHOD("set_shape", "shape"), &FogVolume::set_shape);
40 ClassDB::bind_method(D_METHOD("get_shape"), &FogVolume::get_shape);
41 ClassDB::bind_method(D_METHOD("set_material", "material"), &FogVolume::set_material);
42 ClassDB::bind_method(D_METHOD("get_material"), &FogVolume::get_material);
43
44 ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size");
45 ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Ellipsoid (Local),Cone (Local),Cylinder (Local),Box (Local),World (Global)"), "set_shape", "get_shape");
46 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "FogMaterial,ShaderMaterial"), "set_material", "get_material");
47}
48
49void FogVolume::_validate_property(PropertyInfo &p_property) const {
50 if (p_property.name == "size" && shape == RS::FOG_VOLUME_SHAPE_WORLD) {
51 p_property.usage = PROPERTY_USAGE_NONE;
52 return;
53 }
54}
55
56#ifndef DISABLE_DEPRECATED
57bool FogVolume::_set(const StringName &p_name, const Variant &p_value) {
58 if (p_name == "extents") { // Compatibility with Godot 3.x.
59 set_size((Vector3)p_value * 2);
60 return true;
61 }
62 return false;
63}
64
65bool FogVolume::_get(const StringName &p_name, Variant &r_property) const {
66 if (p_name == "extents") { // Compatibility with Godot 3.x.
67 r_property = size / 2;
68 return true;
69 }
70 return false;
71}
72#endif // DISABLE_DEPRECATED
73
74void FogVolume::set_size(const Vector3 &p_size) {
75 size = p_size;
76 size.x = MAX(0.0, size.x);
77 size.y = MAX(0.0, size.y);
78 size.z = MAX(0.0, size.z);
79 RS::get_singleton()->fog_volume_set_size(_get_volume(), size);
80 update_gizmos();
81}
82
83Vector3 FogVolume::get_size() const {
84 return size;
85}
86
87void FogVolume::set_shape(RS::FogVolumeShape p_type) {
88 shape = p_type;
89 RS::get_singleton()->fog_volume_set_shape(_get_volume(), shape);
90 RS::get_singleton()->instance_set_ignore_culling(get_instance(), shape == RS::FOG_VOLUME_SHAPE_WORLD);
91 update_gizmos();
92 notify_property_list_changed();
93}
94
95RS::FogVolumeShape FogVolume::get_shape() const {
96 return shape;
97}
98
99void FogVolume::set_material(const Ref<Material> &p_material) {
100 material = p_material;
101 RID material_rid;
102 if (material.is_valid()) {
103 material_rid = material->get_rid();
104 }
105 RS::get_singleton()->fog_volume_set_material(_get_volume(), material_rid);
106 update_gizmos();
107}
108
109Ref<Material> FogVolume::get_material() const {
110 return material;
111}
112
113AABB FogVolume::get_aabb() const {
114 if (shape != RS::FOG_VOLUME_SHAPE_WORLD) {
115 return AABB(-size / 2, size);
116 }
117 return AABB();
118}
119
120PackedStringArray FogVolume::get_configuration_warnings() const {
121 PackedStringArray warnings = Node::get_configuration_warnings();
122
123 Ref<Environment> environment = get_viewport()->find_world_3d()->get_environment();
124
125 if (OS::get_singleton()->get_current_rendering_method() != "forward_plus") {
126 warnings.push_back(RTR("Fog Volumes are only visible when using the Forward+ backend."));
127 return warnings;
128 }
129
130 if (environment.is_valid() && !environment->is_volumetric_fog_enabled()) {
131 warnings.push_back(RTR("Fog Volumes need volumetric fog to be enabled in the scene's Environment in order to be visible."));
132 }
133
134 return warnings;
135}
136
137FogVolume::FogVolume() {
138 volume = RS::get_singleton()->fog_volume_create();
139 RS::get_singleton()->fog_volume_set_shape(volume, RS::FOG_VOLUME_SHAPE_BOX);
140 set_base(volume);
141}
142
143FogVolume::~FogVolume() {
144 ERR_FAIL_NULL(RenderingServer::get_singleton());
145 RS::get_singleton()->free(volume);
146}
147