Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/3d/decal.cpp
20851 views
1
/**************************************************************************/
2
/* decal.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 "decal.h"
32
33
void Decal::set_size(const Vector3 &p_size) {
34
size = p_size.maxf(0.001);
35
RS::get_singleton()->decal_set_size(decal, size);
36
update_gizmos();
37
}
38
39
Vector3 Decal::get_size() const {
40
return size;
41
}
42
43
void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) {
44
ERR_FAIL_INDEX(p_type, TEXTURE_MAX);
45
textures[p_type] = p_texture;
46
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
47
48
#ifdef DEBUG_ENABLED
49
if (p_texture.is_valid() &&
50
(p_texture->is_class("AnimatedTexture") ||
51
p_texture->is_class("AtlasTexture") ||
52
p_texture->is_class("CameraTexture") ||
53
p_texture->is_class("CanvasTexture") ||
54
p_texture->is_class("MeshTexture") ||
55
p_texture->is_class("Texture2DRD") ||
56
p_texture->is_class("ViewportTexture"))) {
57
WARN_PRINT(vformat("%s cannot be used as a Decal texture (%s). As a workaround, assign the value returned by %s's `get_image()` instead.", p_texture->get_class(), get_path(), p_texture->get_class()));
58
}
59
#endif
60
61
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
62
update_configuration_warnings();
63
}
64
65
Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
66
ERR_FAIL_INDEX_V(p_type, TEXTURE_MAX, Ref<Texture2D>());
67
return textures[p_type];
68
}
69
70
void Decal::set_emission_energy(real_t p_energy) {
71
emission_energy = p_energy;
72
RS::get_singleton()->decal_set_emission_energy(decal, emission_energy);
73
}
74
75
real_t Decal::get_emission_energy() const {
76
return emission_energy;
77
}
78
79
void Decal::set_albedo_mix(real_t p_mix) {
80
albedo_mix = p_mix;
81
RS::get_singleton()->decal_set_albedo_mix(decal, albedo_mix);
82
}
83
84
real_t Decal::get_albedo_mix() const {
85
return albedo_mix;
86
}
87
88
void Decal::set_upper_fade(real_t p_fade) {
89
upper_fade = MAX(p_fade, 0.0);
90
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
91
}
92
93
real_t Decal::get_upper_fade() const {
94
return upper_fade;
95
}
96
97
void Decal::set_lower_fade(real_t p_fade) {
98
lower_fade = MAX(p_fade, 0.0);
99
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
100
}
101
102
real_t Decal::get_lower_fade() const {
103
return lower_fade;
104
}
105
106
void Decal::set_normal_fade(real_t p_fade) {
107
normal_fade = p_fade;
108
RS::get_singleton()->decal_set_normal_fade(decal, normal_fade);
109
}
110
111
real_t Decal::get_normal_fade() const {
112
return normal_fade;
113
}
114
115
void Decal::set_modulate(Color p_modulate) {
116
modulate = p_modulate;
117
RS::get_singleton()->decal_set_modulate(decal, p_modulate);
118
}
119
120
Color Decal::get_modulate() const {
121
return modulate;
122
}
123
124
void Decal::set_enable_distance_fade(bool p_enable) {
125
distance_fade_enabled = p_enable;
126
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
127
notify_property_list_changed();
128
}
129
130
bool Decal::is_distance_fade_enabled() const {
131
return distance_fade_enabled;
132
}
133
134
void Decal::set_distance_fade_begin(real_t p_distance) {
135
distance_fade_begin = p_distance;
136
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
137
}
138
139
real_t Decal::get_distance_fade_begin() const {
140
return distance_fade_begin;
141
}
142
143
void Decal::set_distance_fade_length(real_t p_length) {
144
distance_fade_length = p_length;
145
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
146
}
147
148
real_t Decal::get_distance_fade_length() const {
149
return distance_fade_length;
150
}
151
152
void Decal::set_cull_mask(uint32_t p_layers) {
153
cull_mask = p_layers;
154
RS::get_singleton()->decal_set_cull_mask(decal, cull_mask);
155
update_configuration_warnings();
156
}
157
158
uint32_t Decal::get_cull_mask() const {
159
return cull_mask;
160
}
161
162
AABB Decal::get_aabb() const {
163
AABB aabb;
164
aabb.position = -size / 2;
165
aabb.size = size;
166
return aabb;
167
}
168
169
void Decal::_validate_property(PropertyInfo &p_property) const {
170
if (p_property.name == "sorting_offset") {
171
p_property.usage = PROPERTY_USAGE_DEFAULT;
172
}
173
}
174
175
PackedStringArray Decal::get_configuration_warnings() const {
176
PackedStringArray warnings = VisualInstance3D::get_configuration_warnings();
177
178
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "dummy") {
179
warnings.push_back(RTR("Decals are only available when using the Forward+ or Mobile renderer."));
180
return warnings;
181
}
182
183
if (textures[TEXTURE_ALBEDO].is_null() && textures[TEXTURE_NORMAL].is_null() && textures[TEXTURE_ORM].is_null() && textures[TEXTURE_EMISSION].is_null()) {
184
warnings.push_back(RTR("The decal has no textures loaded into any of its texture properties, and will therefore not be visible."));
185
}
186
187
if ((textures[TEXTURE_NORMAL].is_valid() || textures[TEXTURE_ORM].is_valid()) && textures[TEXTURE_ALBEDO].is_null()) {
188
warnings.push_back(RTR("The decal has a Normal and/or ORM texture, but no Albedo texture is set.\nAn Albedo texture with an alpha channel is required to blend the normal/ORM maps onto the underlying surface.\nIf you don't want the Albedo texture to be visible, set Albedo Mix to 0."));
189
}
190
191
if (cull_mask == 0) {
192
warnings.push_back(RTR("The decal's Cull Mask has no bits enabled, which means the decal will not paint objects on any layer.\nTo resolve this, enable at least one bit in the Cull Mask property."));
193
}
194
195
return warnings;
196
}
197
198
void Decal::_bind_methods() {
199
ClassDB::bind_method(D_METHOD("set_size", "size"), &Decal::set_size);
200
ClassDB::bind_method(D_METHOD("get_size"), &Decal::get_size);
201
202
ClassDB::bind_method(D_METHOD("set_texture", "type", "texture"), &Decal::set_texture);
203
ClassDB::bind_method(D_METHOD("get_texture", "type"), &Decal::get_texture);
204
205
ClassDB::bind_method(D_METHOD("set_emission_energy", "energy"), &Decal::set_emission_energy);
206
ClassDB::bind_method(D_METHOD("get_emission_energy"), &Decal::get_emission_energy);
207
208
ClassDB::bind_method(D_METHOD("set_albedo_mix", "energy"), &Decal::set_albedo_mix);
209
ClassDB::bind_method(D_METHOD("get_albedo_mix"), &Decal::get_albedo_mix);
210
211
ClassDB::bind_method(D_METHOD("set_modulate", "color"), &Decal::set_modulate);
212
ClassDB::bind_method(D_METHOD("get_modulate"), &Decal::get_modulate);
213
214
ClassDB::bind_method(D_METHOD("set_upper_fade", "fade"), &Decal::set_upper_fade);
215
ClassDB::bind_method(D_METHOD("get_upper_fade"), &Decal::get_upper_fade);
216
217
ClassDB::bind_method(D_METHOD("set_lower_fade", "fade"), &Decal::set_lower_fade);
218
ClassDB::bind_method(D_METHOD("get_lower_fade"), &Decal::get_lower_fade);
219
220
ClassDB::bind_method(D_METHOD("set_normal_fade", "fade"), &Decal::set_normal_fade);
221
ClassDB::bind_method(D_METHOD("get_normal_fade"), &Decal::get_normal_fade);
222
223
ClassDB::bind_method(D_METHOD("set_enable_distance_fade", "enable"), &Decal::set_enable_distance_fade);
224
ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &Decal::is_distance_fade_enabled);
225
226
ClassDB::bind_method(D_METHOD("set_distance_fade_begin", "distance"), &Decal::set_distance_fade_begin);
227
ClassDB::bind_method(D_METHOD("get_distance_fade_begin"), &Decal::get_distance_fade_begin);
228
229
ClassDB::bind_method(D_METHOD("set_distance_fade_length", "distance"), &Decal::set_distance_fade_length);
230
ClassDB::bind_method(D_METHOD("get_distance_fade_length"), &Decal::get_distance_fade_length);
231
232
ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Decal::set_cull_mask);
233
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask);
234
235
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_size", "get_size");
236
237
ADD_GROUP("Textures", "texture_");
238
// Only allow texture types that display correctly.
239
const String texture_hint = "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture";
240
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ALBEDO);
241
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_NORMAL);
242
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ORM);
243
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_EMISSION);
244
245
ADD_GROUP("Parameters", "");
246
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy");
247
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
248
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix");
249
// A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface.
250
// Due to this, limit Normal Fade to 0.999.
251
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade");
252
253
ADD_GROUP("Vertical Fade", "");
254
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
255
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
256
257
ADD_GROUP("Distance Fade", "distance_fade_");
258
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_enable_distance_fade", "is_distance_fade_enabled");
259
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin");
260
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length");
261
262
ADD_GROUP("Cull Mask", "");
263
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
264
265
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
266
BIND_ENUM_CONSTANT(TEXTURE_NORMAL);
267
BIND_ENUM_CONSTANT(TEXTURE_ORM);
268
BIND_ENUM_CONSTANT(TEXTURE_EMISSION);
269
BIND_ENUM_CONSTANT(TEXTURE_MAX);
270
}
271
272
#ifndef DISABLE_DEPRECATED
273
bool Decal::_set(const StringName &p_name, const Variant &p_value) {
274
if (p_name == "extents") { // Compatibility with Godot 3.x.
275
set_size((Vector3)p_value * 2);
276
return true;
277
}
278
return false;
279
}
280
281
bool Decal::_get(const StringName &p_name, Variant &r_property) const {
282
if (p_name == "extents") { // Compatibility with Godot 3.x.
283
r_property = size / 2;
284
return true;
285
}
286
return false;
287
}
288
#endif // DISABLE_DEPRECATED
289
290
Decal::Decal() {
291
decal = RenderingServer::get_singleton()->decal_create();
292
RS::get_singleton()->instance_set_base(get_instance(), decal);
293
}
294
295
Decal::~Decal() {
296
ERR_FAIL_NULL(RenderingServer::get_singleton());
297
RS::get_singleton()->free_rid(decal);
298
}
299
300