1 /*************************************************************************/
2 /*  sky.cpp                                                              */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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 "sky.h"
32 
33 #include "core/io/image_loader.h"
34 
set_radiance_size(RadianceSize p_size)35 void Sky::set_radiance_size(RadianceSize p_size) {
36 	ERR_FAIL_INDEX(p_size, RADIANCE_SIZE_MAX);
37 
38 	radiance_size = p_size;
39 	_radiance_changed();
40 }
41 
get_radiance_size() const42 Sky::RadianceSize Sky::get_radiance_size() const {
43 
44 	return radiance_size;
45 }
46 
_bind_methods()47 void Sky::_bind_methods() {
48 
49 	ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size);
50 	ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size);
51 
52 	ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size");
53 
54 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_32);
55 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_64);
56 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_128);
57 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_256);
58 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_512);
59 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_1024);
60 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_2048);
61 	BIND_ENUM_CONSTANT(RADIANCE_SIZE_MAX);
62 }
63 
Sky()64 Sky::Sky() {
65 	radiance_size = RADIANCE_SIZE_128;
66 }
67 
68 /////////////////////////////////////////
69 
_radiance_changed()70 void PanoramaSky::_radiance_changed() {
71 
72 	if (panorama.is_valid()) {
73 		static const int size[RADIANCE_SIZE_MAX] = {
74 			32, 64, 128, 256, 512, 1024, 2048
75 		};
76 		VS::get_singleton()->sky_set_texture(sky, panorama->get_rid(), size[get_radiance_size()]);
77 	}
78 }
79 
set_panorama(const Ref<Texture> & p_panorama)80 void PanoramaSky::set_panorama(const Ref<Texture> &p_panorama) {
81 
82 	panorama = p_panorama;
83 
84 	if (panorama.is_valid()) {
85 
86 		_radiance_changed();
87 
88 	} else {
89 		VS::get_singleton()->sky_set_texture(sky, RID(), 0);
90 	}
91 }
92 
get_panorama() const93 Ref<Texture> PanoramaSky::get_panorama() const {
94 
95 	return panorama;
96 }
97 
get_rid() const98 RID PanoramaSky::get_rid() const {
99 
100 	return sky;
101 }
102 
_bind_methods()103 void PanoramaSky::_bind_methods() {
104 
105 	ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama);
106 	ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSky::get_panorama);
107 
108 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_panorama", "get_panorama");
109 }
110 
PanoramaSky()111 PanoramaSky::PanoramaSky() {
112 
113 	sky = VS::get_singleton()->sky_create();
114 }
115 
~PanoramaSky()116 PanoramaSky::~PanoramaSky() {
117 
118 	VS::get_singleton()->free(sky);
119 }
120 //////////////////////////////////
121 
_radiance_changed()122 void ProceduralSky::_radiance_changed() {
123 
124 	if (update_queued)
125 		return; //do nothing yet
126 
127 	static const int size[RADIANCE_SIZE_MAX] = {
128 		32, 64, 128, 256, 512, 1024, 2048
129 	};
130 	VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]);
131 }
132 
_generate_sky()133 Ref<Image> ProceduralSky::_generate_sky() {
134 
135 	update_queued = false;
136 
137 	PoolVector<uint8_t> imgdata;
138 
139 	static const int size[TEXTURE_SIZE_MAX] = {
140 		256, 512, 1024, 2048, 4096
141 	};
142 
143 	int w = size[texture_size];
144 	int h = w / 2;
145 
146 	imgdata.resize(w * h * 4); //RGBE
147 
148 	{
149 		PoolVector<uint8_t>::Write dataw = imgdata.write();
150 
151 		uint32_t *ptr = (uint32_t *)dataw.ptr();
152 
153 		Color sky_top_linear = sky_top_color.to_linear();
154 		Color sky_horizon_linear = sky_horizon_color.to_linear();
155 
156 		Color ground_bottom_linear = ground_bottom_color.to_linear();
157 		Color ground_horizon_linear = ground_horizon_color.to_linear();
158 
159 		Color sun_linear;
160 		sun_linear.r = sun_color.r * sun_energy;
161 		sun_linear.g = sun_color.g * sun_energy;
162 		sun_linear.b = sun_color.b * sun_energy;
163 
164 		Vector3 sun(0, 0, -1);
165 
166 		sun = Basis(Vector3(1, 0, 0), Math::deg2rad(sun_latitude)).xform(sun);
167 		sun = Basis(Vector3(0, 1, 0), Math::deg2rad(sun_longitude)).xform(sun);
168 
169 		sun.normalize();
170 
171 		for (int i = 0; i < w; i++) {
172 
173 			float u = float(i) / (w - 1);
174 			float phi = u * 2.0 * Math_PI;
175 
176 			for (int j = 0; j < h; j++) {
177 
178 				float v = float(j) / (h - 1);
179 				float theta = v * Math_PI;
180 
181 				Vector3 normal(
182 						Math::sin(phi) * Math::sin(theta) * -1.0,
183 						Math::cos(theta),
184 						Math::cos(phi) * Math::sin(theta) * -1.0);
185 
186 				normal.normalize();
187 
188 				float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0));
189 
190 				Color color;
191 
192 				if (normal.y < 0) {
193 					//ground
194 
195 					float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5);
196 					color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve));
197 					color.r *= ground_energy;
198 					color.g *= ground_energy;
199 					color.b *= ground_energy;
200 				} else {
201 					float c = v_angle / (Math_PI * 0.5);
202 					color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve));
203 					color.r *= sky_energy;
204 					color.g *= sky_energy;
205 					color.b *= sky_energy;
206 
207 					float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
208 
209 					if (sun_angle < sun_angle_min) {
210 						color = color.blend(sun_linear);
211 					} else if (sun_angle < sun_angle_max) {
212 
213 						float c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);
214 						c2 = Math::ease(c2, sun_curve);
215 
216 						color = color.blend(sun_linear).linear_interpolate(color, c2);
217 					}
218 				}
219 
220 				ptr[j * w + i] = color.to_rgbe9995();
221 			}
222 		}
223 	}
224 
225 	Ref<Image> image;
226 	image.instance();
227 	image->create(w, h, false, Image::FORMAT_RGBE9995, imgdata);
228 
229 	return image;
230 }
231 
set_sky_top_color(const Color & p_sky_top)232 void ProceduralSky::set_sky_top_color(const Color &p_sky_top) {
233 
234 	sky_top_color = p_sky_top;
235 	_queue_update();
236 }
237 
get_sky_top_color() const238 Color ProceduralSky::get_sky_top_color() const {
239 
240 	return sky_top_color;
241 }
242 
set_sky_horizon_color(const Color & p_sky_horizon)243 void ProceduralSky::set_sky_horizon_color(const Color &p_sky_horizon) {
244 
245 	sky_horizon_color = p_sky_horizon;
246 	_queue_update();
247 }
get_sky_horizon_color() const248 Color ProceduralSky::get_sky_horizon_color() const {
249 
250 	return sky_horizon_color;
251 }
252 
set_sky_curve(float p_curve)253 void ProceduralSky::set_sky_curve(float p_curve) {
254 
255 	sky_curve = p_curve;
256 	_queue_update();
257 }
get_sky_curve() const258 float ProceduralSky::get_sky_curve() const {
259 
260 	return sky_curve;
261 }
262 
set_sky_energy(float p_energy)263 void ProceduralSky::set_sky_energy(float p_energy) {
264 
265 	sky_energy = p_energy;
266 	_queue_update();
267 }
get_sky_energy() const268 float ProceduralSky::get_sky_energy() const {
269 
270 	return sky_energy;
271 }
272 
set_ground_bottom_color(const Color & p_ground_bottom)273 void ProceduralSky::set_ground_bottom_color(const Color &p_ground_bottom) {
274 
275 	ground_bottom_color = p_ground_bottom;
276 	_queue_update();
277 }
get_ground_bottom_color() const278 Color ProceduralSky::get_ground_bottom_color() const {
279 
280 	return ground_bottom_color;
281 }
282 
set_ground_horizon_color(const Color & p_ground_horizon)283 void ProceduralSky::set_ground_horizon_color(const Color &p_ground_horizon) {
284 
285 	ground_horizon_color = p_ground_horizon;
286 	_queue_update();
287 }
get_ground_horizon_color() const288 Color ProceduralSky::get_ground_horizon_color() const {
289 
290 	return ground_horizon_color;
291 }
292 
set_ground_curve(float p_curve)293 void ProceduralSky::set_ground_curve(float p_curve) {
294 
295 	ground_curve = p_curve;
296 	_queue_update();
297 }
get_ground_curve() const298 float ProceduralSky::get_ground_curve() const {
299 
300 	return ground_curve;
301 }
302 
set_ground_energy(float p_energy)303 void ProceduralSky::set_ground_energy(float p_energy) {
304 
305 	ground_energy = p_energy;
306 	_queue_update();
307 }
get_ground_energy() const308 float ProceduralSky::get_ground_energy() const {
309 
310 	return ground_energy;
311 }
312 
set_sun_color(const Color & p_sun)313 void ProceduralSky::set_sun_color(const Color &p_sun) {
314 
315 	sun_color = p_sun;
316 	_queue_update();
317 }
get_sun_color() const318 Color ProceduralSky::get_sun_color() const {
319 
320 	return sun_color;
321 }
322 
set_sun_latitude(float p_angle)323 void ProceduralSky::set_sun_latitude(float p_angle) {
324 
325 	sun_latitude = p_angle;
326 	_queue_update();
327 }
get_sun_latitude() const328 float ProceduralSky::get_sun_latitude() const {
329 
330 	return sun_latitude;
331 }
332 
set_sun_longitude(float p_angle)333 void ProceduralSky::set_sun_longitude(float p_angle) {
334 
335 	sun_longitude = p_angle;
336 	_queue_update();
337 }
get_sun_longitude() const338 float ProceduralSky::get_sun_longitude() const {
339 
340 	return sun_longitude;
341 }
342 
set_sun_angle_min(float p_angle)343 void ProceduralSky::set_sun_angle_min(float p_angle) {
344 
345 	sun_angle_min = p_angle;
346 	_queue_update();
347 }
get_sun_angle_min() const348 float ProceduralSky::get_sun_angle_min() const {
349 
350 	return sun_angle_min;
351 }
352 
set_sun_angle_max(float p_angle)353 void ProceduralSky::set_sun_angle_max(float p_angle) {
354 
355 	sun_angle_max = p_angle;
356 	_queue_update();
357 }
get_sun_angle_max() const358 float ProceduralSky::get_sun_angle_max() const {
359 
360 	return sun_angle_max;
361 }
362 
set_sun_curve(float p_curve)363 void ProceduralSky::set_sun_curve(float p_curve) {
364 
365 	sun_curve = p_curve;
366 	_queue_update();
367 }
get_sun_curve() const368 float ProceduralSky::get_sun_curve() const {
369 
370 	return sun_curve;
371 }
372 
set_sun_energy(float p_energy)373 void ProceduralSky::set_sun_energy(float p_energy) {
374 
375 	sun_energy = p_energy;
376 	_queue_update();
377 }
get_sun_energy() const378 float ProceduralSky::get_sun_energy() const {
379 
380 	return sun_energy;
381 }
382 
set_texture_size(TextureSize p_size)383 void ProceduralSky::set_texture_size(TextureSize p_size) {
384 	ERR_FAIL_INDEX(p_size, TEXTURE_SIZE_MAX);
385 
386 	texture_size = p_size;
387 	_queue_update();
388 }
get_texture_size() const389 ProceduralSky::TextureSize ProceduralSky::get_texture_size() const {
390 	return texture_size;
391 }
392 
get_rid() const393 RID ProceduralSky::get_rid() const {
394 	return sky;
395 }
396 
_update_sky()397 void ProceduralSky::_update_sky() {
398 
399 	bool use_thread = true;
400 	if (first_time) {
401 		use_thread = false;
402 		first_time = false;
403 	}
404 #ifdef NO_THREADS
405 	use_thread = false;
406 #endif
407 	if (use_thread) {
408 
409 		if (!sky_thread) {
410 			sky_thread = Thread::create(_thread_function, this);
411 			regen_queued = false;
412 		} else {
413 			regen_queued = true;
414 		}
415 
416 	} else {
417 		Ref<Image> image = _generate_sky();
418 		VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
419 		VS::get_singleton()->texture_set_data(texture, image);
420 		_radiance_changed();
421 	}
422 }
423 
_queue_update()424 void ProceduralSky::_queue_update() {
425 
426 	if (update_queued)
427 		return;
428 
429 	update_queued = true;
430 	call_deferred("_update_sky");
431 }
432 
_thread_done(const Ref<Image> & p_image)433 void ProceduralSky::_thread_done(const Ref<Image> &p_image) {
434 
435 	VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
436 	VS::get_singleton()->texture_set_data(texture, p_image);
437 	_radiance_changed();
438 	Thread::wait_to_finish(sky_thread);
439 	memdelete(sky_thread);
440 	sky_thread = NULL;
441 	if (regen_queued) {
442 		sky_thread = Thread::create(_thread_function, this);
443 		regen_queued = false;
444 	}
445 }
446 
_thread_function(void * p_ud)447 void ProceduralSky::_thread_function(void *p_ud) {
448 
449 	ProceduralSky *psky = (ProceduralSky *)p_ud;
450 	psky->call_deferred("_thread_done", psky->_generate_sky());
451 }
452 
_bind_methods()453 void ProceduralSky::_bind_methods() {
454 
455 	ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky);
456 
457 	ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSky::set_sky_top_color);
458 	ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSky::get_sky_top_color);
459 
460 	ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSky::set_sky_horizon_color);
461 	ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSky::get_sky_horizon_color);
462 
463 	ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSky::set_sky_curve);
464 	ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSky::get_sky_curve);
465 
466 	ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSky::set_sky_energy);
467 	ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSky::get_sky_energy);
468 
469 	ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSky::set_ground_bottom_color);
470 	ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSky::get_ground_bottom_color);
471 
472 	ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSky::set_ground_horizon_color);
473 	ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSky::get_ground_horizon_color);
474 
475 	ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSky::set_ground_curve);
476 	ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSky::get_ground_curve);
477 
478 	ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSky::set_ground_energy);
479 	ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSky::get_ground_energy);
480 
481 	ClassDB::bind_method(D_METHOD("set_sun_color", "color"), &ProceduralSky::set_sun_color);
482 	ClassDB::bind_method(D_METHOD("get_sun_color"), &ProceduralSky::get_sun_color);
483 
484 	ClassDB::bind_method(D_METHOD("set_sun_latitude", "degrees"), &ProceduralSky::set_sun_latitude);
485 	ClassDB::bind_method(D_METHOD("get_sun_latitude"), &ProceduralSky::get_sun_latitude);
486 
487 	ClassDB::bind_method(D_METHOD("set_sun_longitude", "degrees"), &ProceduralSky::set_sun_longitude);
488 	ClassDB::bind_method(D_METHOD("get_sun_longitude"), &ProceduralSky::get_sun_longitude);
489 
490 	ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSky::set_sun_angle_min);
491 	ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSky::get_sun_angle_min);
492 
493 	ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSky::set_sun_angle_max);
494 	ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSky::get_sun_angle_max);
495 
496 	ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSky::set_sun_curve);
497 	ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSky::get_sun_curve);
498 
499 	ClassDB::bind_method(D_METHOD("set_sun_energy", "energy"), &ProceduralSky::set_sun_energy);
500 	ClassDB::bind_method(D_METHOD("get_sun_energy"), &ProceduralSky::get_sun_energy);
501 
502 	ClassDB::bind_method(D_METHOD("set_texture_size", "size"), &ProceduralSky::set_texture_size);
503 	ClassDB::bind_method(D_METHOD("get_texture_size"), &ProceduralSky::get_texture_size);
504 
505 	ClassDB::bind_method(D_METHOD("_thread_done", "image"), &ProceduralSky::_thread_done);
506 
507 	ADD_GROUP("Sky", "sky_");
508 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color");
509 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color");
510 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
511 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
512 
513 	ADD_GROUP("Ground", "ground_");
514 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color");
515 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color");
516 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
517 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
518 
519 	ADD_GROUP("Sun", "sun_");
520 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sun_color"), "set_sun_color", "get_sun_color");
521 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude");
522 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude");
523 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min");
524 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max");
525 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
526 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy");
527 
528 	ADD_GROUP("Texture", "texture_");
529 	ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size");
530 
531 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_256);
532 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_512);
533 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_1024);
534 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_2048);
535 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_4096);
536 	BIND_ENUM_CONSTANT(TEXTURE_SIZE_MAX);
537 }
538 
ProceduralSky(bool p_desaturate)539 ProceduralSky::ProceduralSky(bool p_desaturate) {
540 
541 	sky = VS::get_singleton()->sky_create();
542 	texture = VS::get_singleton()->texture_create();
543 
544 	update_queued = false;
545 	sky_top_color = Color::hex(0xa5d6f1ff);
546 	sky_horizon_color = Color::hex(0xd6eafaff);
547 	sky_curve = 0.09;
548 	sky_energy = 1;
549 
550 	ground_bottom_color = Color::hex(0x282f36ff);
551 	ground_horizon_color = Color::hex(0x6c655fff);
552 	ground_curve = 0.02;
553 	ground_energy = 1;
554 
555 	if (p_desaturate) {
556 		sky_top_color.set_hsv(sky_top_color.get_h(), 0, sky_top_color.get_v());
557 		sky_horizon_color.set_hsv(sky_horizon_color.get_h(), 0, sky_horizon_color.get_v());
558 		ground_bottom_color.set_hsv(ground_bottom_color.get_h(), 0, ground_bottom_color.get_v());
559 		ground_horizon_color.set_hsv(ground_horizon_color.get_h(), 0, ground_horizon_color.get_v());
560 	}
561 	sun_color = Color(1, 1, 1);
562 	sun_latitude = 35;
563 	sun_longitude = 0;
564 	sun_angle_min = 1;
565 	sun_angle_max = 100;
566 	sun_curve = 0.05;
567 	sun_energy = 1;
568 
569 	texture_size = TEXTURE_SIZE_1024;
570 	sky_thread = NULL;
571 	regen_queued = false;
572 	first_time = true;
573 
574 	_queue_update();
575 }
576 
~ProceduralSky()577 ProceduralSky::~ProceduralSky() {
578 
579 	if (sky_thread) {
580 		Thread::wait_to_finish(sky_thread);
581 		memdelete(sky_thread);
582 		sky_thread = NULL;
583 	}
584 	VS::get_singleton()->free(sky);
585 	VS::get_singleton()->free(texture);
586 }
587