Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/3d/decal.cpp
9896 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 (Engine::get_singleton()->is_editor_hint() && !distance_fade_enabled && (p_property.name == "distance_fade_begin" || p_property.name == "distance_fade_length")) {
171
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
172
}
173
174
if (p_property.name == "sorting_offset") {
175
p_property.usage = PROPERTY_USAGE_DEFAULT;
176
}
177
}
178
179
PackedStringArray Decal::get_configuration_warnings() const {
180
PackedStringArray warnings = VisualInstance3D::get_configuration_warnings();
181
182
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "dummy") {
183
warnings.push_back(RTR("Decals are only available when using the Forward+ or Mobile renderers."));
184
return warnings;
185
}
186
187
if (textures[TEXTURE_ALBEDO].is_null() && textures[TEXTURE_NORMAL].is_null() && textures[TEXTURE_ORM].is_null() && textures[TEXTURE_EMISSION].is_null()) {
188
warnings.push_back(RTR("The decal has no textures loaded into any of its texture properties, and will therefore not be visible."));
189
}
190
191
if ((textures[TEXTURE_NORMAL].is_valid() || textures[TEXTURE_ORM].is_valid()) && textures[TEXTURE_ALBEDO].is_null()) {
192
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."));
193
}
194
195
if (cull_mask == 0) {
196
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."));
197
}
198
199
return warnings;
200
}
201
202
void Decal::_bind_methods() {
203
ClassDB::bind_method(D_METHOD("set_size", "size"), &Decal::set_size);
204
ClassDB::bind_method(D_METHOD("get_size"), &Decal::get_size);
205
206
ClassDB::bind_method(D_METHOD("set_texture", "type", "texture"), &Decal::set_texture);
207
ClassDB::bind_method(D_METHOD("get_texture", "type"), &Decal::get_texture);
208
209
ClassDB::bind_method(D_METHOD("set_emission_energy", "energy"), &Decal::set_emission_energy);
210
ClassDB::bind_method(D_METHOD("get_emission_energy"), &Decal::get_emission_energy);
211
212
ClassDB::bind_method(D_METHOD("set_albedo_mix", "energy"), &Decal::set_albedo_mix);
213
ClassDB::bind_method(D_METHOD("get_albedo_mix"), &Decal::get_albedo_mix);
214
215
ClassDB::bind_method(D_METHOD("set_modulate", "color"), &Decal::set_modulate);
216
ClassDB::bind_method(D_METHOD("get_modulate"), &Decal::get_modulate);
217
218
ClassDB::bind_method(D_METHOD("set_upper_fade", "fade"), &Decal::set_upper_fade);
219
ClassDB::bind_method(D_METHOD("get_upper_fade"), &Decal::get_upper_fade);
220
221
ClassDB::bind_method(D_METHOD("set_lower_fade", "fade"), &Decal::set_lower_fade);
222
ClassDB::bind_method(D_METHOD("get_lower_fade"), &Decal::get_lower_fade);
223
224
ClassDB::bind_method(D_METHOD("set_normal_fade", "fade"), &Decal::set_normal_fade);
225
ClassDB::bind_method(D_METHOD("get_normal_fade"), &Decal::get_normal_fade);
226
227
ClassDB::bind_method(D_METHOD("set_enable_distance_fade", "enable"), &Decal::set_enable_distance_fade);
228
ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &Decal::is_distance_fade_enabled);
229
230
ClassDB::bind_method(D_METHOD("set_distance_fade_begin", "distance"), &Decal::set_distance_fade_begin);
231
ClassDB::bind_method(D_METHOD("get_distance_fade_begin"), &Decal::get_distance_fade_begin);
232
233
ClassDB::bind_method(D_METHOD("set_distance_fade_length", "distance"), &Decal::set_distance_fade_length);
234
ClassDB::bind_method(D_METHOD("get_distance_fade_length"), &Decal::get_distance_fade_length);
235
236
ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Decal::set_cull_mask);
237
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask);
238
239
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_size", "get_size");
240
241
ADD_GROUP("Textures", "texture_");
242
// Only allow texture types that display correctly.
243
const String texture_hint = "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture";
244
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ALBEDO);
245
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_NORMAL);
246
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ORM);
247
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_EMISSION);
248
249
ADD_GROUP("Parameters", "");
250
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy");
251
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
252
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix");
253
// A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface.
254
// Due to this, limit Normal Fade to 0.999.
255
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade");
256
257
ADD_GROUP("Vertical Fade", "");
258
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
259
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
260
261
ADD_GROUP("Distance Fade", "distance_fade_");
262
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
263
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");
264
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");
265
266
ADD_GROUP("Cull Mask", "");
267
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
268
269
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
270
BIND_ENUM_CONSTANT(TEXTURE_NORMAL);
271
BIND_ENUM_CONSTANT(TEXTURE_ORM);
272
BIND_ENUM_CONSTANT(TEXTURE_EMISSION);
273
BIND_ENUM_CONSTANT(TEXTURE_MAX);
274
}
275
276
#ifndef DISABLE_DEPRECATED
277
bool Decal::_set(const StringName &p_name, const Variant &p_value) {
278
if (p_name == "extents") { // Compatibility with Godot 3.x.
279
set_size((Vector3)p_value * 2);
280
return true;
281
}
282
return false;
283
}
284
285
bool Decal::_get(const StringName &p_name, Variant &r_property) const {
286
if (p_name == "extents") { // Compatibility with Godot 3.x.
287
r_property = size / 2;
288
return true;
289
}
290
return false;
291
}
292
#endif // DISABLE_DEPRECATED
293
294
Decal::Decal() {
295
decal = RenderingServer::get_singleton()->decal_create();
296
RS::get_singleton()->instance_set_base(get_instance(), decal);
297
}
298
299
Decal::~Decal() {
300
ERR_FAIL_NULL(RenderingServer::get_singleton());
301
RS::get_singleton()->free(decal);
302
}
303
304