summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-11-19 13:23:37 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-11-19 13:23:37 -0300
commitc39d2b3f429639803f4f4fe80eda6935659e9c51 (patch)
treea6c991d572d7dc0f0a59e9ac729ce52ac0331355 /scene
parenta7078a4be9f4c44a41e5c7e7a633169b53f78d48 (diff)
working reflection probes!!
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/reflection_probe.cpp266
-rw-r--r--scene/3d/reflection_probe.h92
-rw-r--r--scene/main/scene_main_loop.cpp7
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/environment.cpp9
-rw-r--r--scene/resources/environment.h7
-rw-r--r--scene/resources/sky_box.cpp158
-rw-r--r--scene/resources/sky_box.h71
8 files changed, 607 insertions, 8 deletions
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
new file mode 100644
index 0000000000..09082b0f28
--- /dev/null
+++ b/scene/3d/reflection_probe.cpp
@@ -0,0 +1,266 @@
+#include "reflection_probe.h"
+
+
+void ReflectionProbe::set_intensity(float p_intensity) {
+
+ intensity=p_intensity;
+ VS::get_singleton()->reflection_probe_set_intensity(probe,p_intensity);
+}
+
+float ReflectionProbe::get_intensity() const{
+
+ return intensity;
+}
+
+
+void ReflectionProbe::set_interior_ambient(Color p_ambient) {
+
+ interior_ambient=p_ambient;
+ VS::get_singleton()->reflection_probe_set_interior_ambient(probe,p_ambient);
+}
+
+void ReflectionProbe::set_interior_ambient_energy(float p_energy) {
+ interior_ambient_energy=p_energy;
+ VS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe,p_energy);
+}
+
+float ReflectionProbe::get_interior_ambient_energy() const{
+ return interior_ambient_energy;
+}
+
+
+Color ReflectionProbe::get_interior_ambient() const{
+
+ return interior_ambient;
+}
+
+void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) {
+
+ interior_ambient_probe_contribution=p_contribution;
+ VS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe,p_contribution);
+}
+
+float ReflectionProbe::get_interior_ambient_probe_contribution() const{
+
+ return interior_ambient_probe_contribution;
+}
+
+
+void ReflectionProbe::set_max_distance(float p_distance){
+
+ max_distance=p_distance;
+ VS::get_singleton()->reflection_probe_set_max_distance(probe,p_distance);
+}
+float ReflectionProbe::get_max_distance() const{
+
+ return max_distance;
+}
+
+
+void ReflectionProbe::set_extents(const Vector3& p_extents){
+
+ extents=p_extents;
+
+ for(int i=0;i<3;i++) {
+ if (extents[i]<0.01) {
+ extents[i]=0.01;
+ }
+
+ if (extents[i]-0.01<ABS(origin_offset[i])) {
+ origin_offset[i]=SGN(origin_offset[i])*(extents[i]-0.01);
+ _change_notify("origin_offset");
+ }
+ }
+
+ VS::get_singleton()->reflection_probe_set_extents(probe,extents);
+ VS::get_singleton()->reflection_probe_set_origin_offset(probe,origin_offset);
+ _change_notify("extents");
+ update_gizmo();
+
+}
+Vector3 ReflectionProbe::get_extents() const{
+
+ return extents;
+}
+
+void ReflectionProbe::set_origin_offset(const Vector3& p_extents){
+
+ origin_offset=p_extents;
+
+ for(int i=0;i<3;i++) {
+
+ if (extents[i]-0.01<ABS(origin_offset[i])) {
+ origin_offset[i]=SGN(origin_offset[i])*(extents[i]-0.01);
+
+ }
+ }
+ VS::get_singleton()->reflection_probe_set_extents(probe,extents);
+ VS::get_singleton()->reflection_probe_set_origin_offset(probe,origin_offset);
+
+ _change_notify("origin_offset");
+ update_gizmo();
+}
+Vector3 ReflectionProbe::get_origin_offset() const{
+
+ return origin_offset;
+}
+
+void ReflectionProbe::set_enable_box_projection(bool p_enable){
+
+ box_projection=p_enable;
+ VS::get_singleton()->reflection_probe_set_enable_box_projection(probe,p_enable);
+
+}
+bool ReflectionProbe::is_box_projection_enabled() const{
+
+ return box_projection;
+}
+
+
+void ReflectionProbe::set_as_interior(bool p_enable) {
+
+ interior=p_enable;
+ VS::get_singleton()->reflection_probe_set_as_interior(probe,interior);
+ _change_notify();
+
+}
+
+bool ReflectionProbe::is_set_as_interior() const {
+
+ return interior;
+}
+
+
+
+void ReflectionProbe::set_enable_shadows(bool p_enable) {
+
+ enable_shadows=p_enable;
+ VS::get_singleton()->reflection_probe_set_enable_shadows(probe,p_enable);
+}
+bool ReflectionProbe::are_shadows_enabled() const {
+
+ return enable_shadows;
+}
+
+void ReflectionProbe::set_cull_mask(uint32_t p_layers) {
+
+ cull_mask=p_layers;
+ VS::get_singleton()->reflection_probe_set_enable_shadows(probe,p_layers);
+}
+uint32_t ReflectionProbe::get_cull_mask() const {
+
+ return cull_mask;
+}
+
+void ReflectionProbe::set_update_mode(UpdateMode p_mode) {
+ update_mode=p_mode;
+ VS::get_singleton()->reflection_probe_set_update_mode(probe,VS::ReflectionProbeUpdateMode(p_mode));
+}
+
+ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const {
+ return update_mode;
+}
+
+
+AABB ReflectionProbe::get_aabb() const {
+
+ AABB aabb;
+ aabb.pos=-origin_offset;
+ aabb.size=origin_offset+extents;
+ return aabb;
+}
+DVector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
+
+ return DVector<Face3>();
+}
+
+void ReflectionProbe::_validate_property(PropertyInfo& property) const {
+
+ if (property.name=="interior/ambient_color" || property.name=="interior/ambient_energy" || property.name=="interior/ambient_contrib") {
+ if (!interior) {
+ property.usage=PROPERTY_USAGE_NOEDITOR;
+ }
+ }
+}
+
+void ReflectionProbe::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_intensity","intensity"),&ReflectionProbe::set_intensity);
+ ObjectTypeDB::bind_method(_MD("get_intensity"),&ReflectionProbe::get_intensity);
+
+ ObjectTypeDB::bind_method(_MD("set_interior_ambient","ambient"),&ReflectionProbe::set_interior_ambient);
+ ObjectTypeDB::bind_method(_MD("get_interior_ambient"),&ReflectionProbe::get_interior_ambient);
+
+ ObjectTypeDB::bind_method(_MD("set_interior_ambient_energy","ambient_energy"),&ReflectionProbe::set_interior_ambient_energy);
+ ObjectTypeDB::bind_method(_MD("get_interior_ambient_energy"),&ReflectionProbe::get_interior_ambient_energy);
+
+ ObjectTypeDB::bind_method(_MD("set_interior_ambient_probe_contribution","ambient_probe_contribution"),&ReflectionProbe::set_interior_ambient_probe_contribution);
+ ObjectTypeDB::bind_method(_MD("get_interior_ambient_probe_contribution"),&ReflectionProbe::get_interior_ambient_probe_contribution);
+
+ ObjectTypeDB::bind_method(_MD("set_max_distance","max_distance"),&ReflectionProbe::set_max_distance);
+ ObjectTypeDB::bind_method(_MD("get_max_distance"),&ReflectionProbe::get_max_distance);
+
+ ObjectTypeDB::bind_method(_MD("set_extents","extents"),&ReflectionProbe::set_extents);
+ ObjectTypeDB::bind_method(_MD("get_extents"),&ReflectionProbe::get_extents);
+
+ ObjectTypeDB::bind_method(_MD("set_origin_offset","origin_offset"),&ReflectionProbe::set_origin_offset);
+ ObjectTypeDB::bind_method(_MD("get_origin_offset"),&ReflectionProbe::get_origin_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_as_interior","enable"),&ReflectionProbe::set_as_interior);
+ ObjectTypeDB::bind_method(_MD("is_set_as_interior"),&ReflectionProbe::is_set_as_interior);
+
+ ObjectTypeDB::bind_method(_MD("set_enable_box_projection","enable"),&ReflectionProbe::set_enable_box_projection);
+ ObjectTypeDB::bind_method(_MD("is_box_projection_enabled"),&ReflectionProbe::is_box_projection_enabled);
+
+
+ ObjectTypeDB::bind_method(_MD("set_enable_shadows","enable"),&ReflectionProbe::set_enable_shadows);
+ ObjectTypeDB::bind_method(_MD("are_shadows_enabled"),&ReflectionProbe::are_shadows_enabled);
+
+ ObjectTypeDB::bind_method(_MD("set_cull_mask","layers"),&ReflectionProbe::set_cull_mask);
+ ObjectTypeDB::bind_method(_MD("get_cull_mask"),&ReflectionProbe::get_cull_mask);
+
+ ObjectTypeDB::bind_method(_MD("set_update_mode","mode"),&ReflectionProbe::set_update_mode);
+ ObjectTypeDB::bind_method(_MD("get_update_mode"),&ReflectionProbe::get_update_mode);
+
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"update_mode",PROPERTY_HINT_ENUM,"Once,Always"),_SCS("set_update_mode"),_SCS("get_update_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"intensity",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_intensity"),_SCS("get_intensity"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"max_distance",PROPERTY_HINT_RANGE,"0,16384,0.1"),_SCS("set_max_distance"),_SCS("get_max_distance"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"extents"),_SCS("set_extents"),_SCS("get_extents"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"origin_offset"),_SCS("set_origin_offset"),_SCS("get_origin_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"box_projection"),_SCS("set_enable_box_projection"),_SCS("is_box_projection_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enable_shadows"),_SCS("set_enable_shadows"),_SCS("are_shadows_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_cull_mask"),_SCS("get_cull_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior/enable"),_SCS("set_as_interior"),_SCS("is_set_as_interior"));
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"interior/ambient_color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_interior_ambient"),_SCS("get_interior_ambient"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior/ambient_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_interior_ambient_energy"),_SCS("get_interior_ambient_energy"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior/ambient_contrib",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_interior_ambient_probe_contribution"),_SCS("get_interior_ambient_probe_contribution"));
+
+
+ BIND_CONSTANT( UPDATE_ONCE );
+ BIND_CONSTANT( UPDATE_ALWAYS );
+
+}
+
+ReflectionProbe::ReflectionProbe() {
+
+ intensity=1.0;
+ interior_ambient=Color(0,0,0);
+ interior_ambient_probe_contribution=0;
+ interior_ambient_energy=1.0;
+ max_distance=0;
+ extents=Vector3(1,1,1);
+ origin_offset=Vector3(0,0,0);
+ box_projection=false;
+ interior=false;
+ enable_shadows=false;
+ cull_mask=(1<<20)-1;
+ update_mode=UPDATE_ONCE;
+
+ probe=VisualServer::get_singleton()->reflection_probe_create();
+ VS::get_singleton()->instance_set_base(get_instance(),probe);
+}
+
+ReflectionProbe::~ReflectionProbe() {
+
+ VS::get_singleton()->free(probe);
+}
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
new file mode 100644
index 0000000000..5ea41a91c9
--- /dev/null
+++ b/scene/3d/reflection_probe.h
@@ -0,0 +1,92 @@
+#ifndef REFLECTIONPROBE_H
+#define REFLECTIONPROBE_H
+
+#include "scene/3d/visual_instance.h"
+#include "scene/resources/texture.h"
+#include "scene/resources/sky_box.h"
+#include "servers/visual_server.h"
+
+class ReflectionProbe : public VisualInstance {
+ OBJ_TYPE(ReflectionProbe,VisualInstance);
+
+public:
+
+ enum UpdateMode {
+ UPDATE_ONCE,
+ UPDATE_ALWAYS,
+ };
+
+
+private:
+
+ RID probe;
+ float intensity;
+ float max_distance;
+ Vector3 extents;
+ Vector3 origin_offset;
+ bool box_projection;
+ bool enable_shadows;
+ bool interior;
+ Color interior_ambient;
+ float interior_ambient_energy;
+ float interior_ambient_probe_contribution;
+
+ uint32_t cull_mask;
+ UpdateMode update_mode;
+
+protected:
+
+ static void _bind_methods();
+ void _validate_property(PropertyInfo& property) const;
+
+public:
+
+ void set_intensity(float p_intensity);
+ float get_intensity() const;
+
+ void set_interior_ambient(Color p_ambient);
+ Color get_interior_ambient() const;
+
+ void set_interior_ambient_energy(float p_energy);
+ float get_interior_ambient_energy() const;
+
+ void set_interior_ambient_probe_contribution(float p_contribution);
+ float get_interior_ambient_probe_contribution() const;
+
+ void set_max_distance(float p_distance);
+ float get_max_distance() const;
+
+ void set_extents(const Vector3& p_extents);
+ Vector3 get_extents() const;
+
+ void set_origin_offset(const Vector3& p_extents);
+ Vector3 get_origin_offset() const;
+
+ void set_as_interior(bool p_enable);
+ bool is_set_as_interior() const;
+
+ void set_enable_box_projection(bool p_enable);
+ bool is_box_projection_enabled() const;
+
+ void set_enable_shadows(bool p_enable);
+ bool are_shadows_enabled() const;
+
+ void set_cull_mask(uint32_t p_layers);
+ uint32_t get_cull_mask() const;
+
+ void set_update_mode(UpdateMode p_mode);
+ UpdateMode get_update_mode() const;
+
+ virtual AABB get_aabb() const;
+ virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+
+
+
+ ReflectionProbe();
+ ~ReflectionProbe();
+};
+
+
+VARIANT_ENUM_CAST( ReflectionProbe::UpdateMode );
+
+#endif // REFLECTIONPROBE_H
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index ef619244d0..abc4bf3fe2 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -2296,6 +2296,7 @@ SceneTree::SceneTree() {
collision_debug_contacts=GLOBAL_DEF("debug/collision_max_contacts_displayed",10000);
+
tree_version=1;
fixed_process_time=1;
idle_process_time=1;
@@ -2319,6 +2320,12 @@ SceneTree::SceneTree() {
root->set_as_audio_listener_2d(true);
current_scene=NULL;
+ int ref_atlas_size = GLOBAL_DEF("rendering/reflections/atlas_size",2048);
+ int ref_atlas_subdiv = GLOBAL_DEF("rendering/reflections/atlas_subdiv",8);
+
+ VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(),ref_atlas_size,ref_atlas_subdiv);
+
+
stretch_mode=STRETCH_MODE_DISABLED;
stretch_aspect=STRETCH_ASPECT_IGNORE;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index e2f5b56796..d2b9def5c7 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -166,6 +166,7 @@
#include "scene/resources/sample.h"
#include "scene/audio/sample_player.h"
#include "scene/resources/texture.h"
+#include "scene/resources/sky_box.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/room.h"
@@ -203,6 +204,7 @@
#include "scene/3d/mesh_instance.h"
#include "scene/3d/quad.h"
#include "scene/3d/light.h"
+#include "scene/3d/reflection_probe.h"
#include "scene/3d/particles.h"
#include "scene/3d/portal.h"
#include "scene/resources/environment.h"
@@ -421,6 +423,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<DirectionalLight>();
ObjectTypeDB::register_type<OmniLight>();
ObjectTypeDB::register_type<SpotLight>();
+ ObjectTypeDB::register_type<ReflectionProbe>();
ObjectTypeDB::register_type<AnimationTreePlayer>();
ObjectTypeDB::register_type<Portal>();
//ObjectTypeDB::register_type<Particles>();
@@ -578,6 +581,8 @@ void register_scene_types() {
ObjectTypeDB::register_type<Environment>();
ObjectTypeDB::register_type<World2D>();
ObjectTypeDB::register_virtual_type<Texture>();
+ ObjectTypeDB::register_virtual_type<SkyBox>();
+ ObjectTypeDB::register_type<ImageSkyBox>();
ObjectTypeDB::register_type<ImageTexture>();
ObjectTypeDB::register_type<AtlasTexture>();
ObjectTypeDB::register_type<LargeTexture>();
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 47f4370cc2..d35200d98c 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -44,16 +44,15 @@ void Environment::set_background(BGMode p_bg) {
_change_notify();
}
-void Environment::set_skybox(const Ref<CubeMap>& p_skybox){
+void Environment::set_skybox(const Ref<SkyBox> &p_skybox){
bg_skybox=p_skybox;
RID sb_rid;
if (bg_skybox.is_valid())
sb_rid=bg_skybox->get_rid();
- print_line("skybox valid: "+itos(sb_rid.is_valid()));
- VS::get_singleton()->environment_set_skybox(environment,sb_rid,Globals::get_singleton()->get("rendering/skybox/radiance_cube_resolution"));
+ VS::get_singleton()->environment_set_skybox(environment,sb_rid);
}
void Environment::set_skybox_scale(float p_scale) {
@@ -97,7 +96,7 @@ Environment::BGMode Environment::get_background() const{
return bg_mode;
}
-Ref<CubeMap> Environment::get_skybox() const{
+Ref<SkyBox> Environment::get_skybox() const{
return bg_skybox;
}
@@ -326,7 +325,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Clear Color,Custom Color,Skybox,Canvas,Keep"),_SCS("set_background"),_SCS("get_background") );
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"background/skybox",PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"),_SCS("set_skybox"),_SCS("get_skybox") );
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"background/skybox",PROPERTY_HINT_RESOURCE_TYPE,"SkyBox"),_SCS("set_skybox"),_SCS("get_skybox") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"background/skybox_scale",PROPERTY_HINT_RANGE,"0,32,0.01"),_SCS("set_skybox_scale"),_SCS("get_skybox_scale") );
ADD_PROPERTY(PropertyInfo(Variant::COLOR,"background/color"),_SCS("set_bg_color"),_SCS("get_bg_color") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_bg_energy"),_SCS("get_bg_energy") );
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 394b67dadf..ca55b51b20 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -32,6 +32,7 @@
#include "resource.h"
#include "servers/visual_server.h"
#include "scene/resources/texture.h"
+#include "scene/resources/sky_box.h"
class Environment : public Resource {
@@ -69,7 +70,7 @@ private:
RID environment;
BGMode bg_mode;
- Ref<CubeMap> bg_skybox;
+ Ref<SkyBox> bg_skybox;
float bg_skybox_scale;
Color bg_color;
float bg_energy;
@@ -102,7 +103,7 @@ public:
void set_background(BGMode p_bg);
- void set_skybox(const Ref<CubeMap>& p_skybox);
+ void set_skybox(const Ref<SkyBox>& p_skybox);
void set_skybox_scale(float p_scale);
void set_bg_color(const Color& p_color);
void set_bg_energy(float p_energy);
@@ -112,7 +113,7 @@ public:
void set_ambient_light_skybox_contribution(float p_energy);
BGMode get_background() const;
- Ref<CubeMap> get_skybox() const;
+ Ref<SkyBox> get_skybox() const;
float get_skybox_scale() const;
Color get_bg_color() const;
float get_bg_energy() const;
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
new file mode 100644
index 0000000000..e8017cb084
--- /dev/null
+++ b/scene/resources/sky_box.cpp
@@ -0,0 +1,158 @@
+#include "sky_box.h"
+#include "io/image_loader.h"
+
+
+void SkyBox::set_radiance_size(RadianceSize p_size) {
+ ERR_FAIL_INDEX(p_size,RADIANCE_SIZE_MAX);
+
+ radiance_size=p_size;
+ _radiance_changed();
+}
+
+SkyBox::RadianceSize SkyBox::get_radiance_size() const {
+
+ return radiance_size;
+}
+
+void SkyBox::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_radiance_size","size"),&SkyBox::set_radiance_size);
+ ObjectTypeDB::bind_method(_MD("get_radiance_size"),&SkyBox::get_radiance_size);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"radiance_size",PROPERTY_HINT_ENUM,"256,512,1024,2048"),_SCS("set_radiance_size"),_SCS("get_radiance_size"));
+
+
+ BIND_CONSTANT( RADIANCE_SIZE_256 );
+ BIND_CONSTANT( RADIANCE_SIZE_512 );
+ BIND_CONSTANT( RADIANCE_SIZE_1024 );
+ BIND_CONSTANT( RADIANCE_SIZE_2048 );
+ BIND_CONSTANT( RADIANCE_SIZE_MAX );
+}
+
+SkyBox::SkyBox()
+{
+ radiance_size=RADIANCE_SIZE_512;
+}
+
+/////////////////////////////////////////
+
+
+
+void ImageSkyBox::_radiance_changed() {
+
+ if (cube_map_valid) {
+ static const int size[RADIANCE_SIZE_MAX]={
+ 256,512,1024,2048
+ };
+ VS::get_singleton()->skybox_set_texture(sky_box,cube_map,size[get_radiance_size()]);
+ }
+}
+
+void ImageSkyBox::set_image_path(ImagePath p_image,const String &p_path) {
+
+ ERR_FAIL_INDEX(p_image,IMAGE_PATH_MAX);
+ image_path[p_image]=p_path;
+
+ bool all_ok=true;
+ for(int i=0;i<IMAGE_PATH_MAX;i++) {
+ if (image_path[i]==String()) {
+ all_ok=false;
+ }
+ }
+
+ cube_map_valid=false;
+
+ if (all_ok) {
+
+ Image images[IMAGE_PATH_MAX];
+ int w=0,h=0;
+ Image::Format format;
+
+ for(int i=0;i<IMAGE_PATH_MAX;i++) {
+ Error err = ImageLoader::load_image(image_path[i],&images[i]);
+ if (err) {
+ ERR_PRINTS("Error loading image for skybox: "+image_path[i]);
+ return;
+ }
+
+ if (i==0) {
+ w=images[0].get_width();
+ h=images[0].get_height();
+ format=images[0].get_format();
+ } else {
+ if (images[i].get_width()!=w || images[i].get_height()!=h || images[i].get_format()!=format) {
+ ERR_PRINTS("Image size mismatch ("+itos(images[i].get_width())+","+itos(images[i].get_height())+":"+Image::get_format_name(images[i].get_format())+" when it should be "+itos(w)+","+itos(h)+":"+Image::get_format_name(format)+"): "+image_path[i]);
+ return;
+ }
+ }
+ }
+
+ VS::get_singleton()->texture_allocate(cube_map,w,h,format,VS::TEXTURE_FLAG_FILTER|VS::TEXTURE_FLAG_CUBEMAP|VS::TEXTURE_FLAG_MIPMAPS);
+ for(int i=0;i<IMAGE_PATH_MAX;i++) {
+ VS::get_singleton()->texture_set_data(cube_map,images[i],VS::CubeMapSide(i));
+ }
+
+ cube_map_valid=true;
+ _radiance_changed();
+ }
+
+
+}
+
+String ImageSkyBox::get_image_path(ImagePath p_image) const {
+
+ ERR_FAIL_INDEX_V(p_image,IMAGE_PATH_MAX,String());
+ return image_path[p_image];
+
+}
+
+RID ImageSkyBox::get_rid() const {
+
+ return sky_box;
+}
+
+void ImageSkyBox::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_image_path","image","path"),&ImageSkyBox::set_image_path);
+ ObjectTypeDB::bind_method(_MD("get_image_path","image"),&ImageSkyBox::get_image_path);
+
+ List<String> extensions;
+ ImageLoader::get_recognized_extensions(&extensions);
+ String hints;
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ if (hints!=String()) {
+ hints+=",";
+ }
+ hints+="*."+E->get();
+ }
+
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/negative_x",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/positive_x",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/negative_y",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/positive_y",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/negative_z",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path/positive_z",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_Z);
+
+ BIND_CONSTANT( IMAGE_PATH_NEGATIVE_X );
+ BIND_CONSTANT( IMAGE_PATH_POSITIVE_X );
+ BIND_CONSTANT( IMAGE_PATH_NEGATIVE_Y );
+ BIND_CONSTANT( IMAGE_PATH_POSITIVE_Y );
+ BIND_CONSTANT( IMAGE_PATH_NEGATIVE_Z );
+ BIND_CONSTANT( IMAGE_PATH_POSITIVE_Z );
+ BIND_CONSTANT( IMAGE_PATH_MAX );
+
+}
+
+ImageSkyBox::ImageSkyBox() {
+
+ cube_map=VS::get_singleton()->texture_create();
+ sky_box=VS::get_singleton()->skybox_create();
+ cube_map_valid=false;
+}
+
+ImageSkyBox::~ImageSkyBox() {
+
+ VS::get_singleton()->free(cube_map);
+ VS::get_singleton()->free(sky_box);
+}
+
diff --git a/scene/resources/sky_box.h b/scene/resources/sky_box.h
new file mode 100644
index 0000000000..3a3dd1b2de
--- /dev/null
+++ b/scene/resources/sky_box.h
@@ -0,0 +1,71 @@
+#ifndef SKYBOX_H
+#define SKYBOX_H
+
+#include "scene/resources/texture.h"
+
+class SkyBox : public Resource {
+ OBJ_TYPE(SkyBox,Resource);
+
+public:
+
+ enum RadianceSize {
+ RADIANCE_SIZE_256,
+ RADIANCE_SIZE_512,
+ RADIANCE_SIZE_1024,
+ RADIANCE_SIZE_2048,
+ RADIANCE_SIZE_MAX
+ };
+private:
+
+ RadianceSize radiance_size;
+protected:
+ static void _bind_methods();
+ virtual void _radiance_changed()=0;
+public:
+
+ void set_radiance_size(RadianceSize p_size);
+ RadianceSize get_radiance_size() const;
+ SkyBox();
+};
+
+VARIANT_ENUM_CAST(SkyBox::RadianceSize)
+
+
+class ImageSkyBox : public SkyBox {
+ OBJ_TYPE(ImageSkyBox,SkyBox);
+
+public:
+
+ enum ImagePath {
+ IMAGE_PATH_NEGATIVE_X,
+ IMAGE_PATH_POSITIVE_X,
+ IMAGE_PATH_NEGATIVE_Y,
+ IMAGE_PATH_POSITIVE_Y,
+ IMAGE_PATH_NEGATIVE_Z,
+ IMAGE_PATH_POSITIVE_Z,
+ IMAGE_PATH_MAX
+ };
+private:
+ RID cube_map;
+ RID sky_box;
+ bool cube_map_valid;
+
+ String image_path[IMAGE_PATH_MAX];
+protected:
+ static void _bind_methods();
+ virtual void _radiance_changed();
+public:
+
+ void set_image_path(ImagePath p_image, const String &p_path);
+ String get_image_path(ImagePath p_image) const;
+
+ virtual RID get_rid() const;
+
+ ImageSkyBox();
+ ~ImageSkyBox();
+};
+
+VARIANT_ENUM_CAST(ImageSkyBox::ImagePath)
+
+
+#endif // SKYBOX_H